feat(include_note): remember value of box size (closes #1623)

This commit is contained in:
Elian Doran
2026-04-11 13:21:23 +03:00
parent ae751bfb91
commit 46d6d6fdee
6 changed files with 35 additions and 4 deletions

View File

@@ -338,6 +338,16 @@ Trilium provides powerful user scripting capabilities:
- **Server-side**: `import { t } from "i18next"` with keys in `apps/server/src/assets/translations/en/server.json`
- **Interpolation**: Use `{{variable}}` for normal interpolation; use `{{- variable}}` (with hyphen) for **unescaped** interpolation when the value contains special characters like quotes that shouldn't be HTML-escaped
### Storing User Preferences
- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices
- To add a new user preference:
1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts`
2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array
3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates)
4. Use `useTriliumOption("optionName")` hook in React components to read/write the option
- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson`
- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation
## Testing Conventions
- **Write concise tests**: Group related assertions together in a single test case rather than creating many one-shot tests

View File

@@ -157,6 +157,16 @@ Trilium provides powerful user scripting capabilities:
- **Do not use `crypto.randomUUID()`** or other Web Crypto APIs that require secure contexts - Trilium can run over HTTP, not just HTTPS
- Use `randomString()` from `apps/client/src/services/utils.ts` for generating IDs instead
### Storing User Preferences
- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices
- To add a new user preference:
1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts`
2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array
3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates)
4. Use `useTriliumOption("optionName")` hook in React components to read/write the option
- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson`
- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation
### Shared Types Policy
- Types shared between client and server belong in `@triliumnext/commons` (`packages/commons/src/lib/`)
- Import shared types directly from `@triliumnext/commons` - do not re-export them from app-specific modules

View File

@@ -8,7 +8,7 @@ import Button from "../react/Button";
import { Suggestion, triggerRecentNotes } from "../../services/note_autocomplete";
import tree from "../../services/tree";
import froca from "../../services/froca";
import { useTriliumEvent } from "../react/hooks";
import { useTriliumEvent, useTriliumOption } from "../react/hooks";
import { type BoxSize, CKEditorApi } from "../type_widgets/text/CKEditorWithWatchdog";
export interface IncludeNoteOpts {
@@ -18,11 +18,13 @@ export interface IncludeNoteOpts {
export default function IncludeNoteDialog() {
const editorApiRef = useRef<CKEditorApi>(null);
const [suggestion, setSuggestion] = useState<Suggestion | null>(null);
const [boxSize, setBoxSize] = useState<string>("medium");
const [defaultBoxSize, setDefaultBoxSize] = useTriliumOption("includeNoteDefaultBoxSize");
const [boxSize, setBoxSize] = useState<string>(defaultBoxSize);
const [shown, setShown] = useState(false);
useTriliumEvent("showIncludeNoteDialog", ({ editorApi }) => {
editorApiRef.current = editorApi;
setBoxSize(defaultBoxSize); // Reset to default when opening dialog
setShown(true);
});
@@ -35,10 +37,14 @@ export default function IncludeNoteDialog() {
size="lg"
onShown={() => triggerRecentNotes(autoCompleteRef.current)}
onHidden={() => setShown(false)}
onSubmit={() => {
onSubmit={async () => {
if (!suggestion?.notePath || !editorApiRef.current) return;
setShown(false);
includeNote(suggestion.notePath, editorApiRef.current, boxSize as BoxSize);
await includeNote(suggestion.notePath, editorApiRef.current, boxSize as BoxSize);
// Save the selected box size as the new default
if (boxSize !== defaultBoxSize) {
setDefaultBoxSize(boxSize);
}
}}
footer={<Button text={t("include_note.button_include")} keyboardShortcut="Enter" />}
show={shown}

View File

@@ -95,6 +95,7 @@ const ALLOWED_OPTIONS = new Set<OptionNames>([
"textNoteEmojiCompletionEnabled",
"textNoteCompletionEnabled",
"textNoteSlashCommandsEnabled",
"includeNoteDefaultBoxSize",
"layoutOrientation",
"backgroundEffects",
"allowedHtmlTags",

View File

@@ -223,6 +223,7 @@ const defaultOptions: DefaultOption[] = [
{ name: "textNoteEmojiCompletionEnabled", value: "true", isSynced: true },
{ name: "textNoteCompletionEnabled", value: "true", isSynced: true },
{ name: "textNoteSlashCommandsEnabled", value: "true", isSynced: true },
{ name: "includeNoteDefaultBoxSize", value: "medium", isSynced: true },
// HTML import configuration
{ name: "layoutOrientation", value: "vertical", isSynced: false },

View File

@@ -142,6 +142,9 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActi
seenCallToActions: string;
experimentalFeatures: string;
// Include note settings
includeNoteDefaultBoxSize: "small" | "medium" | "full" | "expandable";
// AI / LLM
/** JSON array of configured LLM providers with their API keys */
llmProviders: string;