diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-07 23:34:03 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-07 23:34:03 +0900 |
| commit | 0c042ac89fc0822fcbe09c48702857faa5494ae1 (patch) | |
| tree | ea1f1d180f747613343040d441a07f92b2760840 /src/client/sync/queue.ts | |
| parent | ae5a0bb97fbf013417a6962f7e077f0408b2a951 (diff) | |
| download | kioku-0c042ac89fc0822fcbe09c48702857faa5494ae1.tar.gz kioku-0c042ac89fc0822fcbe09c48702857faa5494ae1.tar.zst kioku-0c042ac89fc0822fcbe09c48702857faa5494ae1.zip | |
feat(client): add sync status indicator component
Add SyncStatusIndicator component to display current sync state in the
UI header. The component shows online/offline status, syncing progress,
pending changes count, and sync errors.
- Create SyncProvider context to wrap SyncManager for React components
- Add SyncStatusIndicator component with visual status indicators
- Integrate indicator into HomePage header
- Add comprehensive tests for SyncStatusIndicator and SyncProvider
- Update existing tests to include SyncProvider wrapper
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/client/sync/queue.ts')
| -rw-r--r-- | src/client/sync/queue.ts | 71 |
1 files changed, 46 insertions, 25 deletions
diff --git a/src/client/sync/queue.ts b/src/client/sync/queue.ts index f0b112a..01c62cc 100644 --- a/src/client/sync/queue.ts +++ b/src/client/sync/queue.ts @@ -1,4 +1,9 @@ -import { db, type LocalCard, type LocalDeck, type LocalReviewLog } from "../db/index"; +import { + db, + type LocalCard, + type LocalDeck, + type LocalReviewLog, +} from "../db/index"; import { localCardRepository, localDeckRepository, @@ -41,7 +46,10 @@ const SYNC_STATE_KEY = "kioku_sync_state"; /** * Load sync state from localStorage */ -function loadSyncState(): Pick<SyncQueueState, "lastSyncVersion" | "lastSyncAt"> { +function loadSyncState(): Pick< + SyncQueueState, + "lastSyncVersion" | "lastSyncAt" +> { const stored = localStorage.getItem(SYNC_STATE_KEY); if (!stored) { return { lastSyncVersion: 0, lastSyncAt: null }; @@ -137,7 +145,9 @@ export class SyncQueue { */ async getPendingCount(): Promise<number> { const changes = await this.getPendingChanges(); - return changes.decks.length + changes.cards.length + changes.reviewLogs.length; + return ( + changes.decks.length + changes.cards.length + changes.reviewLogs.length + ); } /** @@ -205,17 +215,24 @@ export class SyncQueue { cards: { id: string; syncVersion: number }[]; reviewLogs: { id: string; syncVersion: number }[]; }): Promise<void> { - await db.transaction("rw", [db.decks, db.cards, db.reviewLogs], async () => { - for (const deck of results.decks) { - await localDeckRepository.markSynced(deck.id, deck.syncVersion); - } - for (const card of results.cards) { - await localCardRepository.markSynced(card.id, card.syncVersion); - } - for (const reviewLog of results.reviewLogs) { - await localReviewLogRepository.markSynced(reviewLog.id, reviewLog.syncVersion); - } - }); + await db.transaction( + "rw", + [db.decks, db.cards, db.reviewLogs], + async () => { + for (const deck of results.decks) { + await localDeckRepository.markSynced(deck.id, deck.syncVersion); + } + for (const card of results.cards) { + await localCardRepository.markSynced(card.id, card.syncVersion); + } + for (const reviewLog of results.reviewLogs) { + await localReviewLogRepository.markSynced( + reviewLog.id, + reviewLog.syncVersion, + ); + } + }, + ); await this.notifyListeners(); } @@ -227,17 +244,21 @@ export class SyncQueue { cards: LocalCard[]; reviewLogs: LocalReviewLog[]; }): Promise<void> { - await db.transaction("rw", [db.decks, db.cards, db.reviewLogs], async () => { - for (const deck of data.decks) { - await localDeckRepository.upsertFromServer(deck); - } - for (const card of data.cards) { - await localCardRepository.upsertFromServer(card); - } - for (const reviewLog of data.reviewLogs) { - await localReviewLogRepository.upsertFromServer(reviewLog); - } - }); + await db.transaction( + "rw", + [db.decks, db.cards, db.reviewLogs], + async () => { + for (const deck of data.decks) { + await localDeckRepository.upsertFromServer(deck); + } + for (const card of data.cards) { + await localCardRepository.upsertFromServer(card); + } + for (const reviewLog of data.reviewLogs) { + await localReviewLogRepository.upsertFromServer(reviewLog); + } + }, + ); await this.notifyListeners(); } |
