Merge branch 'main' into markoer-i-titlen

Begge grene føjede prøver til i enden af smoke.spec.js, og begge beholdes:
fire markør-prøver og fire fra tal-en-opgave-ind. Den fælles `/**` ovenfor
dækkede kun den første, så den anden blok har fået sin egen.

Suiten på den løste fletning: 129 bestod, 0 netafbrydelser.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kristianwind
2026-10-08 10:06:42 +02:00
co-authored by Claude Opus 5
8 changed files with 469 additions and 20 deletions
+29
View File
@@ -6,6 +6,7 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import Sidebar from '$lib/components/Sidebar.svelte';
import DictateSheet from '$lib/components/DictateSheet.svelte';
import CommandPalette from '$lib/components/CommandPalette.svelte';
import SignIn from '$lib/components/SignIn.svelte';
import NoConnection from '$lib/components/NoConnection.svelte';
@@ -57,6 +58,25 @@
app.load();
});
/**
* Hvilken dør dette vindue er inde ad.
*
* To døre, og reglen er én sætning: den, du sidst kom ind ad, bestemmer
* ansigtet. `/urd` sætter urd, `/` sætter verdande, og alt derimellem rører
* det ikke — så et klik videre til en note eller en opgave beholder det navn,
* vinduet åbnede med.
*
* Symmetrien er det, der gør det forudsigeligt. Uden `/`-halvdelen ville en
* fane, der én gang havde set /urd, blive ved med at hedde urd, også på
* opgavesiderne. I de installerede apps sker det aldrig — deres start_url er
* hver sin dør — men en browserfane springer mellem dem hele tiden.
*/
$effect(() => {
const here = $page.url.pathname;
if (here === '/urd') app.enterUrd();
else if (here === '/') app.leaveUrd();
});
/**
* Opgavernes sider findes ikke i noter-udgaven.
*
@@ -295,6 +315,15 @@
tabindex="-1"
></button>
{/if}
<!-- Tal en opgave ind. Kun på telefonen, og kun hvor der er opgaver — se
komponenten.
UBETINGET monteret, og det er ikke en forglemmelse: feltet inde i den
skal kunne få fokus i samme hug som klikket, ellers åbner iOS ikke
tastaturet. Et `{#if}` her ville tage feltet ud af DOM'en og gøre det
umuligt. Menuen dækker den i stedet, fordi den har højere z-index. -->
<DictateSheet />
</div>
<CommandPalette bind:open={paletteOpen} />
+5 -12
View File
@@ -7,25 +7,18 @@
* hvad appen gør, når den så er startet: husker hvilken dør den kom ind ad, og
* går videre til noterne.
*
* `sessionStorage` og ikke `localStorage`, og det er hele grunden til at de to
* apps kan være to apps: de deler origin, så de deler localStorage, cookies og
* service worker. sessionStorage er per vindue — og en installeret PWA er sit
* eget vindue — så urd-appen har sit ansigt og verdande-appen sit, uden at
* træde på hinanden. Det overlever også en genindlæsning, hvilket det skal:
* efter et par klik står adressen på /noter, og en F5 dér går ikke gennem /urd
* igen.
* Ansigtet sættes ikke her, men i layoutet, hvor begge døre står ved siden af
* hinanden — `/urd` sætter urd og `/` sætter verdande. Delt op, fordi en regel
* med to halvdele, der ligger i hver sin fil, er en regel, hvor kun den ene
* halvdel bliver vedligeholdt.
*
* `replaceState`, så telefonens tilbage-gestus ikke fører tilbage til en side,
* der kun omdirigerer.
*/
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
import { app } from '$lib/stores.svelte.js';
onMount(() => {
app.enterUrd();
goto('/noter', { replaceState: true });
});
onMount(() => goto('/noter', { replaceState: true }));
</script>
<!-- Bevidst tom. Omdirigeringen sker i samme hug som tegningen, så alt her ville