diff --git a/src/App.svelte b/src/App.svelte index ee14117..744a4b9 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -212,6 +212,7 @@ let overlayAutosaveAttemptedSignature = ''; let pendingOverlayDraft: { overlayName: string; overlaySlug: string; overlayHtml: string; overlayCss: string; overlayJavascript: string; overlayEnabled: boolean; overlayDisabledDesign: string; overlayAlertGroupWindowMs: number; overlayAlertGroupSize: number; overlayAlertDisplayMs: number } | null = null; let overlayDiagnosticsOpen = false; + let overlayEditorTab: 'HTML' | 'CSS' | 'JAVASCRIPT' = 'HTML'; let overlayAutosaveTimer: number | undefined; let oauthScopes: Record<'streamer' | 'bot', { connected: boolean; missing_scopes: string[]; reauthorization_required: boolean }> = { streamer: { connected: false, missing_scopes: [], reauthorization_required: false }, @@ -1281,6 +1282,10 @@ return warnings; } + function overlayLineNumbers(source: string) { + return Array.from({ length: Math.max(1, source.split('\n').length) }, (_, index) => index + 1); + } + function overlayDraftCacheKey(id: string) { return `trixie.overlay.draft.${id}`; } @@ -1577,7 +1582,7 @@ {/if} {:else if activeView === 'Overlays'} -
OVERLAYS
{#if selectedOverlayId || overlayName}
LIVE PREVIEW
{#if overlayError}
{overlayError}
{/if}{:else}
Select or create an overlayDrafts autosave when explicitly saved; publishing controls the browser source.
{/if}
+
OVERLAYS
{#if selectedOverlayId || overlayName}
{#each ['HTML', 'CSS', 'JAVASCRIPT'] as tab}{/each}
{#if overlayEditorTab === 'HTML'}
{:else if overlayEditorTab === 'CSS'}
{:else}
{/if}
LIVE PREVIEW
{#if overlayError}
{overlayError}
{/if}{:else}
Select or create an overlayDrafts autosave when explicitly saved; publishing controls the browser source.
{/if}
ALERT PLAYBACK

Configure grouping and playback for the selected browser-source overlay. Changes are saved with the next draft save.

{:else if activeView === 'Settings'}
SERVER SETTINGS
DATABASE BACKUPS

Daily backups use the server's local schedule. Restore replaces the current database and is permanently destructive.

{#if backupError}
{backupError}
{/if}{#if backups.length}
{#each backups as backup}
{backup.filename}{Math.round(backup.size_bytes / 1024)} KiB{backup.modified_at ? new Date(backup.modified_at).toLocaleString() : 'UNKNOWN TIME'}
{/each}
{:else}
No backup archives are available.
{/if}
diff --git a/src/styles.css b/src/styles.css index ec22117..f246cda 100644 --- a/src/styles.css +++ b/src/styles.css @@ -662,9 +662,35 @@ label { display: grid; gap: 7px; } +.overlay-source-tabs { + display: flex; + gap: 4px; + border-bottom: 1px solid var(--ui-divider); +} +.overlay-code-wrap { + display: grid; + grid-template-columns: 42px minmax(0, 1fr); + min-height: 190px; + border: 1px solid var(--ui-line); + background: var(--ui-surface-low); +} +.overlay-line-numbers { + display: grid; + align-content: start; + justify-items: end; + gap: 0; + padding: 9px 8px; + color: var(--ed-dim); + background: var(--ui-surface-hi); + font: 12px/1.4 var(--font-data); + user-select: none; +} .overlay-code { min-height: 110px; resize: vertical; + width: 100%; + min-width: 0; + border: 0; color: var(--ed-dim); background: var(--ui-surface-low); font: 12px/1.4 var(--font-data);