feat(notes): et billede kan indsættes og trækkes ind i en note

Rapporteret fra brug: man kunne ikke indsætte billeder eller trække filer ind i
noter. Det passede — importen kunne tage billeder med, og intet andet kunne.
Indsætningen tog kun `text/plain` og smed resten væk, og der var slet ingen
håndtering af et træk. At indsætte et skærmbillede er det mest almindelige, der
findes i et noteprogram, og det gjorde ingenting overhovedet.

Der manglede også et sted at lægge filen. Vedhæftninger på en note fandtes i
databasen, siden migration 0021, men kun importen kunne skrive dem; der var ingen
rute. Nu er der en, med editor-rettigheder på noten og samme svar for "findes
ikke" og "ikke din", så et id ikke kan afprøves.

Skrevet ind som `![](…)` og ikke som en data-URL: en note er Markdown i en
database, og et fotografi fra en telefon som base64 midt i teksten ville gøre
noten til fire megabyte tekst, der skal læses hver gang listen tegnes.

`execCommand` frem for at bygge noden selv, fordi det er dét, der lægger
handlingen i browserens egen fortryd-historik — ⌘Z tager billedet ud igen,
ligesom det tager et ord ud.

`preventDefault` på både dragover og drop. Uden den første kommer der intet drop;
uden den anden åbner browseren filen i stedet, og man mister det, man var i gang
med at skrive, til en fane med et billede i. Kun filer: et træk inde fra appen
selv bærer vores egen nyttelast og skal falde igennem til den, der lyttede.

Prøven går begge veje ind, ser at billederne bliver hentet og tegnet, og læser
filen bagefter for at sikre, at der står to bilagsadresser og ingen data-URL.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-20 07:32:03 +02:00
co-authored by Claude Opus 5
parent 241c5ed37d
commit 3991ec9445
8 changed files with 271 additions and 2 deletions
+39
View File
@@ -1396,6 +1396,45 @@ paths:
description: The environment variables that are not set.
"403": { $ref: "#/components/responses/Forbidden" }
/api/v1/notes/{noteID}/attachments:
post:
tags: [notes]
summary: Put a file into a note.
description: |
A picture pasted or dropped into a note. Until this existed the import
could bring files in and nothing else could, so the most ordinary act in
a notes app — paste a screenshot — did nothing at all.
Editor rights on the note. The same answer for "no such note" and "not
yours", so an id cannot be probed.
The response carries the attachment's URL; the editor writes that into the
note's text as a Markdown image. The file is never inlined as a data URL —
a photograph as base64 would make the note itself megabytes of text.
parameters:
- name: noteID
in: path
required: true
schema: { type: string }
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file:
type: string
format: binary
responses:
"201":
description: Stored, and hung on the note.
"404":
description: No such note, or not yours to write in.
"413":
description: Larger than 25 MB.
/api/v1/beacon:
post:
tags: [auth]