multiple groups per user
This commit is contained in:
+34
-11
@@ -1,6 +1,6 @@
|
||||
import type { Card } from '@cardy/shared';
|
||||
import type { Api } from './api.js';
|
||||
import { cardImageIds, images, storage, type UsageMap, type VersionMap } from './storage.js';
|
||||
import type { Api, GroupApi } from './api.js';
|
||||
import { LEGACY_GROUP_ID, cardImageIds, images, storage, type Session, type UsageMap, type VersionMap } from './storage.js';
|
||||
|
||||
export const MAX_PARALLEL_DOWNLOADS = 5;
|
||||
|
||||
@@ -31,13 +31,35 @@ export function cardsNeedingImages(cards: Card[], versions: VersionMap, stored:
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the list of cards and replaces the local list (only when the download succeeded).
|
||||
* Re-reads the key owner's groups from the server and returns the updated session:
|
||||
* - a legacy session (from before multi-group) gets its groups, and its local data moves to the first
|
||||
* group (the one the group-less routes served);
|
||||
* - local data of groups the user no longer belongs to is removed;
|
||||
* - the current group falls back to the first group when it is gone.
|
||||
*/
|
||||
export async function refreshGroups(api: Api, session: Session): Promise<Session> {
|
||||
const { groups } = await api.auth();
|
||||
const firstId = groups[0]!.id;
|
||||
if (!session.groups?.length) {
|
||||
await storage.moveGroup(LEGACY_GROUP_ID, firstId);
|
||||
} else {
|
||||
for (const old of session.groups) if (!groups.some((g) => g.id === old.id)) await storage.removeGroup(old.id);
|
||||
}
|
||||
const current = groups.some((g) => g.id === session.currentGroupId) ? session.currentGroupId : firstId;
|
||||
const { groupName: _legacy, ...rest } = session;
|
||||
const next: Session = { ...rest, groups, currentGroupId: current };
|
||||
await storage.setSession(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the group's list of cards and replaces the local list (only when the download succeeded).
|
||||
* Cards gone from the server are removed locally with their images and usage.
|
||||
*/
|
||||
export async function refreshCardList(api: Api): Promise<Card[]> {
|
||||
export async function refreshCardList(api: GroupApi, groupId: string): Promise<Card[]> {
|
||||
const fresh = await api.cards();
|
||||
const [old, usage, versions] = await Promise.all([storage.getCards(), storage.getUsage(), storage.getVersions()]);
|
||||
await storage.setCards(fresh);
|
||||
const [old, usage, versions] = await Promise.all([storage.getCards(groupId), storage.getUsage(groupId), storage.getVersions(groupId)]);
|
||||
await storage.setCards(groupId, fresh);
|
||||
|
||||
const freshIds = new Set(fresh.map((c) => c.id));
|
||||
const gone = old.filter((c) => !freshIds.has(c.id));
|
||||
@@ -47,7 +69,7 @@ export async function refreshCardList(api: Api): Promise<Card[]> {
|
||||
delete versions[c.id];
|
||||
await images.prune(c.id);
|
||||
}
|
||||
await Promise.all([storage.setUsage(usage), storage.setVersions(versions)]);
|
||||
await Promise.all([storage.setUsage(groupId, usage), storage.setVersions(groupId, versions)]);
|
||||
}
|
||||
return fresh;
|
||||
}
|
||||
@@ -62,13 +84,14 @@ export interface ImageSyncResult {
|
||||
* A card's version is recorded only after all its files are stored, so failures are retried next time.
|
||||
*/
|
||||
export async function syncImages(
|
||||
api: Api,
|
||||
api: GroupApi,
|
||||
groupId: string,
|
||||
cards: Card[],
|
||||
onCardDone?: (card: Card) => void,
|
||||
onProgress?: (done: number, total: number) => void,
|
||||
): Promise<ImageSyncResult> {
|
||||
const stored = await images.storedKeys();
|
||||
const changed = cardsNeedingImages(cards, await storage.getVersions(), stored);
|
||||
const changed = cardsNeedingImages(cards, await storage.getVersions(groupId), stored);
|
||||
const tasks = changed.flatMap((card) =>
|
||||
cardImageIds(card)
|
||||
.filter((id) => !stored.has(images.key(card.id, id)))
|
||||
@@ -85,9 +108,9 @@ export async function syncImages(
|
||||
if (failedCards.has(card.id)) return versionWrites;
|
||||
versionWrites = versionWrites.then(async () => {
|
||||
await images.prune(card.id, cardImageIds(card));
|
||||
const versions = await storage.getVersions();
|
||||
const versions = await storage.getVersions(groupId);
|
||||
versions[card.id] = card.imagesVersion;
|
||||
await storage.setVersions(versions);
|
||||
await storage.setVersions(groupId, versions);
|
||||
onCardDone?.(card);
|
||||
});
|
||||
return versionWrites;
|
||||
|
||||
Reference in New Issue
Block a user