<script lang="ts">
import { ui } from "../../stores/ui.svelte.js";
import { sync } from "../../stores/sync.svelte.js";
type View = "confirm" | "progress" | "done" | "error";
let view: View = $state("confirm");
let errorMessage: string = $state("");
function startResync() {
const started = sync.triggerResync(
() => {
view = "done";
},
(err) => {
errorMessage = err.message;
view = "error";
},
);
if (started) {
view = "progress";
} else {
errorMessage = "A sync is already in progress.";
view = "error";
}
}
function close() {
ui.activeModal = null;
}
function handleOverlayClick(e: MouseEvent) {
if (
view !== "progress" &&
(e.target as HTMLElement).classList.contains(
"modal-overlay",
)
) {
close();
}
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === "Escape" && view !== "progress") {
close();
}
}
const progressPct = $derived(
sync.progress
? sync.progress.sessions_total > 0
? (sync.progress.sessions_done /
sync.progress.sessions_total) *
100
: 0
: 0,
);
</script>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="modal-overlay"
onclick={handleOverlayClick}
onkeydown={handleKeydown}
>
<div class="modal-panel resync-panel">
<div class="modal-header">
<h3 class="modal-title">Full Resync</h3>
{#if view !== "progress"}
<button class="modal-close" onclick={close}>
×
</button>
{/if}
</div>
<div class="modal-body">
{#if view === "confirm"}
<p class="confirm-text">
Re-parse all session files from scratch. Existing
sessions will be updated in place — no data is
deleted. Use this after upgrading or when sessions
appear incorrect.
</p>
<div class="confirm-actions">
<button class="modal-btn" onclick={close}>
Cancel
</button>
<button
class="modal-btn modal-btn-primary"
onclick={startResync}
>
Start Full Resync
</button>
</div>
{:else if view === "progress"}
<div class="progress-view">
<div class="modal-spinner"></div>
<p class="progress-label">
{#if sync.progress}
Syncing {sync.progress.sessions_done}
/ {sync.progress.sessions_total} sessions...
{:else}
Preparing...
{/if}
</p>
<div class="progress-bar-track">
<div
class="progress-bar-fill"
style="width: {progressPct}%"
></div>
</div>
</div>
{:else if view === "done"}
<div class="done-view">
{#if sync.lastSyncStats}
<p class="done-summary">
Sessions synced: {sync.lastSyncStats.synced}
</p>
{#if sync.lastSyncStats.failed > 0}
<p class="done-warning">
Failed: {sync.lastSyncStats.failed}
</p>
{/if}
{/if}
<div class="done-actions">
<button
class="modal-btn modal-btn-primary"
onclick={close}
>
Close
</button>
</div>
</div>
{:else if view === "error"}
<div class="error-view">
<p class="modal-error">{errorMessage}</p>
<div class="error-actions">
<button
class="modal-btn modal-btn-primary"
onclick={startResync}
>
Retry
</button>
<button class="modal-btn" onclick={close}>
Close
</button>
</div>
</div>
{/if}
</div>
</div>
</div>
<style>
.resync-panel {
width: 400px;
}
.confirm-text {
font-size: var(--wb-font-size-12);
color: var(--vscode-foreground);
line-height: 1.5;
margin-bottom: var(--wb-spacing-16);
}
.confirm-actions {
display: flex;
gap: var(--wb-spacing-8);
justify-content: flex-end;
}
.progress-view {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--wb-spacing-12);
padding: var(--wb-spacing-16) 0;
}
.progress-label {
font-size: var(--wb-font-size-12);
color: var(--vscode-foreground);
font-variant-numeric: tabular-nums;
}
.progress-bar-track {
width: 100%;
height: var(--wb-control-size-4);
background: var(--vscode-input-background);
border-radius: var(--wb-corner-radius-2);
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
background: var(--vscode-focusBorder);
border-radius: var(--wb-corner-radius-2);
transition: width 0.3s;
}
.done-view {
display: flex;
flex-direction: column;
gap: var(--wb-spacing-16);
}
.done-summary {
font-size: var(--wb-font-size-12);
color: var(--vscode-editor-foreground);
font-variant-numeric: tabular-nums;
}
.done-warning {
font-size: var(--wb-font-size-12);
color: var(--wb-accent-orange, #e09040);
font-variant-numeric: tabular-nums;
}
.done-actions {
display: flex;
justify-content: flex-end;
}
.error-view {
display: flex;
flex-direction: column;
gap: var(--wb-spacing-12);
}
.error-actions {
display: flex;
gap: var(--wb-spacing-8);
justify-content: flex-end;
}
</style>