fix sync
This commit is contained in:
parent
a320b1c291
commit
71d5a6593a
|
|
@ -1 +1 @@
|
||||||
1.0.6
|
1.0.7
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
import { newId } from '$lib/db/helpers';
|
import { newId } from '$lib/db/helpers';
|
||||||
import type { AgendaContext, ContextType } from '@ka-note/shared';
|
import type { AgendaContext, ContextType } from '@ka-note/shared';
|
||||||
import { account, logout } from '$lib/auth/authStore.js';
|
import { account, logout } from '$lib/auth/authStore.js';
|
||||||
import { syncStatus, lastSyncAt } from '$lib/sync/syncService';
|
import { syncStatus, lastSyncAt, fullSync } from '$lib/sync/syncService';
|
||||||
|
|
||||||
const isDev = import.meta.env.DEV;
|
const isDev = import.meta.env.DEV;
|
||||||
let appVersion = $state('…');
|
let appVersion = $state('…');
|
||||||
|
|
@ -285,17 +285,27 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="mt-auto border-t border-border pt-3">
|
<div class="mt-auto border-t border-border pt-3">
|
||||||
<div class="mb-2 flex items-center gap-1.5 px-1 text-xs text-muted">
|
<div class="mb-2 flex items-center justify-between px-1">
|
||||||
{#if $syncStatus === 'syncing'}
|
<div class="flex items-center gap-1.5 text-xs text-muted">
|
||||||
<svg class="h-3 w-3 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
{#if $syncStatus === 'syncing'}
|
||||||
<path d="M21 12a9 9 0 1 1-6.219-8.56" stroke-linecap="round"/>
|
<svg class="h-3 w-3 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
</svg>
|
<path d="M21 12a9 9 0 1 1-6.219-8.56" stroke-linecap="round"/>
|
||||||
<span>Syncing…</span>
|
</svg>
|
||||||
{:else if $syncStatus === 'error'}
|
<span>Syncing…</span>
|
||||||
<span class="text-danger">✗ Sync error</span>
|
{:else if $syncStatus === 'error'}
|
||||||
{:else if $lastSyncAt}
|
<span class="text-danger">✗ Sync error</span>
|
||||||
<span>✓ {$lastSyncAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>
|
{:else if $lastSyncAt}
|
||||||
{/if}
|
<span>✓ {$lastSyncAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</span>
|
||||||
|
{:else}
|
||||||
|
<span>Not synced</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="text-xs text-muted hover:text-white disabled:opacity-30 transition-colors"
|
||||||
|
onclick={() => fullSync()}
|
||||||
|
disabled={$syncStatus === 'syncing'}
|
||||||
|
title="Full sync"
|
||||||
|
>⟳</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white"
|
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-muted transition-colors hover:bg-white/5 hover:text-white"
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,19 @@ async function pushAll(): Promise<void> {
|
||||||
if (!res.ok) throw new Error(`Push failed: ${res.status}`);
|
if (!res.ok) throw new Error(`Push failed: ${res.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fullSync(): Promise<void> {
|
||||||
|
await doSync(null);
|
||||||
|
}
|
||||||
|
|
||||||
export async function sync(): Promise<void> {
|
export async function sync(): Promise<void> {
|
||||||
|
let since: Date | null = null;
|
||||||
|
lastSyncAt.subscribe((v) => (since = v))();
|
||||||
|
await doSync(since);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doSync(since: Date | null): Promise<void> {
|
||||||
syncStatus.set('syncing');
|
syncStatus.set('syncing');
|
||||||
try {
|
try {
|
||||||
let since: Date | null = null;
|
|
||||||
lastSyncAt.subscribe((v) => (since = v))();
|
|
||||||
const serverTimestamp = await pullAndMerge(since);
|
const serverTimestamp = await pullAndMerge(since);
|
||||||
await pushAll();
|
await pushAll();
|
||||||
const syncTime = new Date(serverTimestamp);
|
const syncTime = new Date(serverTimestamp);
|
||||||
|
|
@ -95,7 +103,7 @@ export async function sync(): Promise<void> {
|
||||||
syncStatus.set('idle');
|
syncStatus.set('idle');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const msg = err instanceof Error ? err.message : String(err);
|
const msg = err instanceof Error ? err.message : String(err);
|
||||||
if (err instanceof TypeError && msg === 'Failed to fetch') {
|
if (err instanceof TypeError && (msg === 'Failed to fetch' || msg.includes('fetch'))) {
|
||||||
// Offline or server unreachable — stay idle silently
|
// Offline or server unreachable — stay idle silently
|
||||||
syncStatus.set('idle');
|
syncStatus.set('idle');
|
||||||
} else if (msg === 'Redirecting for token' || msg.includes('no_account_in_silent_request')) {
|
} else if (msg === 'Redirecting for token' || msg.includes('no_account_in_silent_request')) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue