+
+
+ {#if state === 'loading'}
+ {t('ai.thinking')}
+ {:else if state === 'failed'}
+ {error}
+ {:else if !rows.length}
+ {t('ai.nothingToSuggest')}
+ {:else}
+ {#if hint}{hint}
{/if}
+
+ {#if !left}
+ {t('ai.allDone')}
+ {/if}
+ {/if}
+
+
+
diff --git a/web/src/lib/locales/da.js b/web/src/lib/locales/da.js
index 1c0ba37..fa0d98e 100644
--- a/web/src/lib/locales/da.js
+++ b/web/src/lib/locales/da.js
@@ -77,6 +77,22 @@ export const da = {
'notes.sortUpdated': 'Senest rørt',
'notes.sortCreated': 'Oprettet',
'notes.sortTitle': 'Navn',
+ // AI'ens forslag. Ordene skal gøre det klart, at der bliver foreslået og ikke
+ // rettet: den, der siger ja, er den, der bestemmer.
+ 'ai.tidyInbox': 'Ryd op i indbakken',
+ 'ai.tidyTitle': 'Forslag til indbakken',
+ 'ai.tidyHint':
+ 'Sådan kunne linjerne have set ud, hvis de var skrevet færdig. Ret i dem, du vil rette i — der sker først noget, når du siger ja.',
+ 'ai.findActions': 'Find opgaver i noten',
+ 'ai.actionsTitle': 'Opgaver i noten',
+ 'ai.actionsHint':
+ 'Det, nogen har lovet eller er blevet bedt om i teksten. Citatet under hver linje er de ord, den kom fra.',
+ 'ai.thinking': 'Læser …',
+ 'ai.nothingToSuggest': 'Der er ikke noget at foreslå.',
+ 'ai.accept': 'Tilføj',
+ 'ai.skip': 'Nej tak',
+ 'ai.applied': 'Gjort.',
+ 'ai.allDone': 'Ikke mere at tage stilling til.',
'beacon.title': 'Tælling af installationer',
'beacon.hint': 'Én gang i døgnet melder denne installation, at den findes, så projektet kan se hvor mange der bruger det. Der sendes kun de to værdier herunder — et tilfældigt id og versionen — og intet andet: ingen IP bliver gemt, ingen navne, ingen adresser, intet om hvad du bruger det til. Slået til som udgangspunkt, og du kan slå den fra her.',
'beacon.send': 'Send en anonym daglig melding',
diff --git a/web/src/lib/locales/en.js b/web/src/lib/locales/en.js
index feb2ff0..34d5791 100644
--- a/web/src/lib/locales/en.js
+++ b/web/src/lib/locales/en.js
@@ -74,6 +74,22 @@ export const en = {
'notes.sortUpdated': 'Last touched',
'notes.sortCreated': 'Created',
'notes.sortTitle': 'Name',
+ // The AI's suggestions. The words have to make it plain that this proposes
+ // rather than edits: whoever says yes is the one deciding.
+ 'ai.tidyInbox': 'Tidy up the inbox',
+ 'ai.tidyTitle': 'Suggestions for the inbox',
+ 'ai.tidyHint':
+ 'How the lines could have read if they had been finished. Edit the ones you want to edit — nothing happens until you say yes.',
+ 'ai.findActions': 'Find tasks in the note',
+ 'ai.actionsTitle': 'Tasks in the note',
+ 'ai.actionsHint':
+ 'What somebody promised or was asked to do in the text. The quote under each line is the words it came from.',
+ 'ai.thinking': 'Reading …',
+ 'ai.nothingToSuggest': 'There is nothing to suggest.',
+ 'ai.accept': 'Add',
+ 'ai.skip': 'No thanks',
+ 'ai.applied': 'Done.',
+ 'ai.allDone': 'Nothing left to decide on.',
'beacon.title': 'Counting installations',
'beacon.hint': 'Once a day this installation reports that it exists, so the project can see how many people run it. It sends only the two values below — a random id and the version — and nothing else: no IP is stored, no names, no addresses, nothing about what you use it for. On by default, and you can turn it off here.',
'beacon.send': 'Send an anonymous daily report',
diff --git a/web/src/routes/noter/+page.svelte b/web/src/routes/noter/+page.svelte
index ea3cdb7..1c9126c 100644
--- a/web/src/routes/noter/+page.svelte
+++ b/web/src/routes/noter/+page.svelte
@@ -19,6 +19,7 @@
import { NOTE, startDrag } from '$lib/dnd.js';
import { colorVar } from '$lib/colors.js';
import NoteEditor from '$lib/components/NoteEditor.svelte';
+ import AISuggestions from '$lib/components/AISuggestions.svelte';
let notes = $state([]);
@@ -207,6 +208,9 @@
// Linket vises kun, når instansen ikke kan sende post. Så er det den eneste vej
// frem, og det skal kunne kopieres frem for at forsvinde.
let shareInviteLink = $state('');
+ // Opgaver, der ligger i notens tekst. Lukket, indtil nogen spørger: det koster
+ // et kald til en model, og de fleste noter er ikke referater.
+ let showActions = $state(false);
const ownsSelected = $derived(!!selected && selected.created_by === app.user?.id);
// Dem, et `@` kan betyde i den åbne note.
@@ -246,8 +250,9 @@
$effect(() => {
const id = selected?.id;
- // Nulstil ved hvert skift, så den forrige notes folk ikke står et øjeblik
- // under den nye.
+ // Nulstil ved hvert skift, så den forrige notes folk — og den forrige notes
+ // forslag — ikke står et øjeblik under den nye.
+ showActions = false;
shares = [];
shareCandidates = [];
shareFollows = [];
@@ -1086,6 +1091,16 @@
onsave={save}
/>
+ {#if showActions}
+