From 72637a153a8c5abcf812ee91eb995a1b19175413 Mon Sep 17 00:00:00 2001 From: kristianwind Date: Sat, 12 Sep 2026 09:11:26 +0200 Subject: [PATCH] =?UTF-8?q?fix(kalender):=20en=20abonnementsadresse=20skub?= =?UTF-8?q?ber=20ikke=20siden=20ud=20over=20sk=C3=A6rmen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adressen på et kalenderabonnement blev vist i en punktliste uden noget, der lod den ombryde. En URL er ét ord på et par hundrede tegn uden et mellemrum i, så den kan ikke bryde af sig selv — og det bredeste element på en side bestemmer sidens bredde. På en telefon betød det, at hele indholdsspalten fik et vandret rullepanel, ikke bare den ene linje. `overflow-wrap: anywhere` er det, resten af indstillingerne allerede bruger til et token og en hemmelighed; listen her var den, der blev glemt. Samtidig får den layout frem for at ligge som løse inline-spans: navn, adresse og knap under hinanden, uden punkttegnets indrykning. Prøven måler `.content` og ikke dokumentet. Skallen holder selv siden på skærmens bredde, så en måling på documentElement består med fejlen i behold — den blev skrevet først og bestod, hvilket er grunden til at kommentaren står der. Co-Authored-By: Claude Opus 5 (1M context) --- web/e2e/smoke.spec.js | 63 +++++++++++++++++++ .../indstillinger/integrationer/+page.svelte | 34 ++++++++++ 2 files changed, 97 insertions(+) diff --git a/web/e2e/smoke.spec.js b/web/e2e/smoke.spec.js index 413accd..e5557bf 100644 --- a/web/e2e/smoke.spec.js +++ b/web/e2e/smoke.spec.js @@ -4360,3 +4360,66 @@ test('dagens plan står på I dag, og ikke kun som en besked', async ({ page }) expect(trouble).toEqual([]); }); + +/** + * En kalenderadresse gør ikke siden bredere end telefonen. + * + * Adressen på et abonnement er ét ord på et par hundrede tegn uden et mellemrum i, + * og den stod i en liste uden noget, der lod den ombryde. Det, man så, var ikke en + * linje, der løb ud over kanten — det var hele siden, der fik et vandret + * rullepanel, fordi det bredeste element på en side bestemmer sidens bredde. Derfor + * måler prøven dokumentet og ikke elementet: det er dokumentet, der var galt. + * + * Abonnementet kommer fra et svar, prøven selv skriver. Serveren ville skulle hente + * kalenderen for at have et at vise, og en prøve, der går på nettet, er en prøve, + * der fejler en dag af en anden grund end sin egen. + */ +test('en lang kalenderadresse giver ikke vandret rulning', async ({ page }) => { + const trouble = watchForTrouble(page); + + await page.route('**/api/v1/calendar', (route) => + route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + connected: false, + calendars: [], + has_client: false, + read_only: true, + redirect_uri: 'http://localhost:8097/api/v1/calendar/callback', + subscriptions: [ + { + id: '0198f000-0000-7000-8000-000000000001', + provider: 'ics', + account: 'kw@netic.dk', + url: + 'https://calendar.google.com/calendar/ical/kw%40netic.dk/private-3f9a1c7e5b2d4a6f8c0e1d2b3a4f5e6d/basic.ics', + created_at: '2026-09-01T09:00:00+02:00' + } + ] + }) + }) + ); + + // En iPhone i stående format. Bredden er det eneste, der betyder noget her. + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto('/indstillinger/integrationer'); + await expect(page.getByText('kw@netic.dk')).toBeVisible(); + + // `.content` og ikke dokumentet. Skallen holder selv siden på skærmens bredde, + // så documentElement måler 390 uanset hvad — det er indholdsspalten indeni, der + // ruller, og det er den, man skubber med tommelfingeren. En prøve på dokumentet + // består med fejlen i behold; den er prøvet. + const spill = await page.evaluate(() => { + const el = document.querySelector('.content'); + const url = document.querySelector('.subs-list .url'); + return { + content: el.scrollWidth - el.clientWidth, + past: Math.round(url.getBoundingClientRect().right) - document.documentElement.clientWidth + }; + }); + expect(spill.content).toBe(0); + expect(spill.past).toBeLessThanOrEqual(0); + + expect(trouble).toEqual([]); +}); diff --git a/web/src/routes/indstillinger/integrationer/+page.svelte b/web/src/routes/indstillinger/integrationer/+page.svelte index f948921..b4eec34 100644 --- a/web/src/routes/indstillinger/integrationer/+page.svelte +++ b/web/src/routes/indstillinger/integrationer/+page.svelte @@ -884,4 +884,38 @@ a { color: var(--accent); } + + /* The bullet list this was is why the page scrolled sideways on a phone. A + subscription address is one word with nothing to break at, so it cannot wrap + on its own — and the widest element on a page sets the width of the page, not + of its own line. Hence `anywhere`, which breaks mid-word when there is no + other opportunity, plus `min-width: 0` so the flex item is allowed to be + narrower than its content in the first place. */ + .subs-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: var(--s3); + } + + .subs-list li { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--s1); + min-width: 0; + } + + .subs-list .url { + font-size: var(--text-xs); + color: var(--ink-muted); + overflow-wrap: anywhere; + max-width: 100%; + } + + .subs-list button { + margin-top: var(--s1); + }