fix type errors in autosave utils
keep the code around in case we revisit later
This commit is contained in:
parent
97bdccd218
commit
640a0d1c19
2 changed files with 59 additions and 8 deletions
|
|
@ -70,6 +70,9 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
|
||||||
|
|
||||||
function schedule() {
|
function schedule() {
|
||||||
if (timer) clearTimeout(timer)
|
if (timer) clearTimeout(timer)
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug(`[AutoSave] Scheduled (${debounceMs}ms debounce)`)
|
||||||
|
}
|
||||||
timer = setTimeout(() => void run(), debounceMs)
|
timer = setTimeout(() => void run(), debounceMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,24 +83,44 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = opts.getPayload()
|
const payload = opts.getPayload()
|
||||||
if (!payload) return
|
if (!payload) {
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Skipped: getPayload returned null/undefined')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const hash = safeHash(payload)
|
const hash = safeHash(payload)
|
||||||
if (lastSentHash && hash === lastSentHash) return
|
if (lastSentHash && hash === lastSentHash) {
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Skipped: payload unchanged (hash match)')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (controller) controller.abort()
|
if (controller) controller.abort()
|
||||||
controller = new AbortController()
|
controller = new AbortController()
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Saving...', { hashChanged: lastSentHash !== hash })
|
||||||
|
}
|
||||||
|
|
||||||
setStatus('saving')
|
setStatus('saving')
|
||||||
lastError = null
|
lastError = null
|
||||||
try {
|
try {
|
||||||
const res = await opts.save(payload, { signal: controller.signal })
|
const res = await opts.save(payload, { signal: controller.signal })
|
||||||
lastSentHash = hash
|
lastSentHash = hash
|
||||||
setStatus('saved')
|
setStatus('saved')
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Saved successfully')
|
||||||
|
}
|
||||||
if (opts.onSaved) opts.onSaved(res, { prime })
|
if (opts.onSaved) opts.onSaved(res, { prime })
|
||||||
} catch (e: unknown) {
|
} catch (e) {
|
||||||
if (e?.name === 'AbortError') {
|
if (e instanceof Error && e.name === 'AbortError') {
|
||||||
// Newer save superseded this one
|
// Newer save superseded this one
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Aborted: superseded by newer save')
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
|
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
|
||||||
|
|
@ -105,7 +128,10 @@ export function createAutoSaveStore<TPayload, TResponse = unknown>(
|
||||||
} else {
|
} else {
|
||||||
setStatus('error')
|
setStatus('error')
|
||||||
}
|
}
|
||||||
lastError = e?.message || 'Auto-save failed'
|
lastError = e instanceof Error ? e.message : 'Auto-save failed'
|
||||||
|
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
|
||||||
|
console.debug('[AutoSave] Error:', lastError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
lastSavedAt?: Date | string | null
|
lastSavedAt?: Date | string | null
|
||||||
showTimestamp?: boolean
|
showTimestamp?: boolean
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
|
onclick?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
|
@ -19,7 +20,8 @@
|
||||||
error: errorProp,
|
error: errorProp,
|
||||||
lastSavedAt,
|
lastSavedAt,
|
||||||
showTimestamp = true,
|
showTimestamp = true,
|
||||||
compact = true
|
compact = true,
|
||||||
|
onclick
|
||||||
}: Props = $props()
|
}: Props = $props()
|
||||||
|
|
||||||
// Support both old subscription-based stores and new reactive values
|
// Support both old subscription-based stores and new reactive values
|
||||||
|
|
@ -81,12 +83,19 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if label}
|
{#if label}
|
||||||
<div class="autosave-status" class:compact>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="autosave-status"
|
||||||
|
class:compact
|
||||||
|
class:clickable={!!onclick && status !== 'saving'}
|
||||||
|
onclick={onclick}
|
||||||
|
disabled={status === 'saving'}
|
||||||
|
>
|
||||||
{#if status === 'saving'}
|
{#if status === 'saving'}
|
||||||
<span class="spinner" aria-hidden="true"></span>
|
<span class="spinner" aria-hidden="true"></span>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="text">{label}</span>
|
<span class="text">{label}</span>
|
||||||
</div>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
@ -96,10 +105,26 @@
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
color: $gray-40;
|
color: $gray-40;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
|
||||||
&.compact {
|
&.compact {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $gray-20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue