fix(groups): assignation en lot 1 requête + trackBy (plus de wipe/429)
This commit is contained in:
@@ -183,28 +183,34 @@ export class SubscriptionsComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/** Crée le groupe suggéré (ou complète l'existant) et y assigne les chaînes. */
|
||||
/** Crée le groupe suggéré (ou complète l'existant) : 2 requêtes max, pas de tempête. */
|
||||
applySuggestion(s: GroupSuggestion): Promise<void> {
|
||||
if (this.suggestBusy()) return Promise.resolve();
|
||||
this.suggestBusy.set(true);
|
||||
const assignAll = (groupId: string): Promise<void> => {
|
||||
const calls = s.channelIds
|
||||
.filter((sid) => !(this.members()[String(sid)] || []).includes(groupId))
|
||||
.map((sid) => new Promise<void>((resolve) => {
|
||||
const current = this.members()[String(sid)] || [];
|
||||
this.subs.setSubscriptionGroups(sid, [...current, groupId]).subscribe({ next: () => resolve(), error: () => resolve() });
|
||||
}));
|
||||
return Promise.all(calls).then(() => undefined);
|
||||
};
|
||||
const done = () => this.suggestBusy.set(false);
|
||||
const run = (gid: string): Promise<void> => new Promise<void>((resolve) => {
|
||||
this.subs.setGroupMembers(gid, this.memberIdsOf(gid, s)).subscribe({ next: () => resolve(), error: () => resolve() });
|
||||
});
|
||||
if (s.kind === 'complete' && s.existingGroupId) {
|
||||
return assignAll(s.existingGroupId).finally(done);
|
||||
return run(s.existingGroupId).finally(done);
|
||||
}
|
||||
return new Promise<void>((resolve) => {
|
||||
this.subs.createGroup(s.name, s.color, s.icon).subscribe((g) => resolve(g?.id ? assignAll(g.id) : undefined));
|
||||
this.subs.createGroup(s.name, s.color, s.icon).subscribe((g) => {
|
||||
if (g?.id) run(g.id).then(() => resolve());
|
||||
else resolve();
|
||||
});
|
||||
}).finally(done);
|
||||
}
|
||||
|
||||
/** Ids déjà dans le groupe + nouveaux (union), pour l'assignation en lot. */
|
||||
private memberIdsOf(groupId: string, s: GroupSuggestion): number[] {
|
||||
const members = this.members();
|
||||
const current = Object.keys(members)
|
||||
.filter((k) => (members[k] || []).includes(groupId))
|
||||
.map(Number);
|
||||
return [...new Set([...current, ...s.channelIds])];
|
||||
}
|
||||
|
||||
/** Applique toutes les suggestions d'un coup, dans l'ordre. */
|
||||
async applyAllSuggestions(): Promise<void> {
|
||||
if (this.suggestBusy()) return;
|
||||
@@ -213,6 +219,19 @@ export class SubscriptionsComponent {
|
||||
}
|
||||
}
|
||||
|
||||
// --- trackBy : DOM stable (pas de re-rendu complet + recharge d'images à chaque tick) ---
|
||||
trackBySubscriptionId(_idx: number, item: SubscriptionItem): number {
|
||||
return item.subscriptionId;
|
||||
}
|
||||
|
||||
trackByGroupId(_idx: number, group: SubscriptionGroup): string {
|
||||
return group.id;
|
||||
}
|
||||
|
||||
trackBySuggestion(_idx: number, s: GroupSuggestion): string {
|
||||
return `${s.kind}:${s.existingGroupId || s.name}`;
|
||||
}
|
||||
|
||||
readonly items = computed(() => this.subs.items());
|
||||
readonly groups = computed(() => this.subs.subscriptionGroups());
|
||||
readonly members = computed(() => this.subs.groupMembers());
|
||||
|
||||
Reference in New Issue
Block a user