Compare commits

..

37 Commits

Author SHA1 Message Date
SiriusXT
21cb896849 feat(window): add the extra-window class to the body of extra windows 2026-01-12 09:58:43 +08:00
SiriusXT
b9bcb07b6d Merge branch 'main' into feat/extra-window 2026-01-12 09:20:14 +08:00
SiriusXT
787b180378 Merge branch 'main' into feat/extra-window 2026-01-09 16:45:20 +08:00
SiriusXT
80404b83b0 Merge branch 'main' into feat/extra-window 2026-01-05 11:28:47 +08:00
SiriusXT
c612bdbfc1 fix(window): normalize closedAt of OpenNoteContexts for abnormally closed windows 2026-01-05 11:21:40 +08:00
SiriusXT
3a9e686533 chore(window): simplify replacement logic for open windows 2026-01-04 18:49:08 +08:00
SiriusXT
9e8d89a170 chore(window): avoid missing windowId 2026-01-04 15:18:57 +08:00
SiriusXT
31c70938d6 Merge branch 'main' into feat/extra-window 2026-01-04 14:13:25 +08:00
SiriusXT
07f3c48d0b chore(window): import randomString only when needed 2026-01-04 14:13:18 +08:00
SiriusXT
2821b6da9d chore(window): add TS type WindowState 2026-01-03 20:04:17 +08:00
SiriusXT
daba7c398d Merge branch 'main' into feat/extra-window 2026-01-03 20:04:11 +08:00
SiriusXT
de1ef5b98b chore(test): fix errors caused by layout changes 2026-01-03 19:04:34 +08:00
SiriusXT
1bb206d978 chore(i18n): tabs total 2026-01-03 18:15:45 +08:00
SiriusXT
2fd5ddab86 chore(window): optimize the replacement logic for old window notes 2026-01-03 11:07:48 +08:00
SiriusXT
27dc662636 fix(window): a window with no open notes appears blank. 2026-01-02 18:17:05 +08:00
SiriusXT
52691b5c8c Merge branch 'main' into feat/extra-window 2026-01-02 17:44:39 +08:00
SiriusXT
8087ed5688 Merge branch 'main' into feat/extra-window 2026-01-02 14:58:10 +08:00
SiriusXT
79e2c97882 chore(window): initialize closed time of openNoteContents to 0 2026-01-01 16:09:03 +08:00
SiriusXT
1078107776 chore(window): initialize closed time of openNoteContents to 0 2026-01-01 14:30:01 +08:00
SiriusXT
9c9e123e3d Merge branch 'main' into feat/extra-window 2026-01-01 14:04:45 +08:00
SiriusXT
a8c2947062 Merge branch 'main' into feat/extra-window 2025-12-31 14:23:42 +08:00
SiriusXT
366166a561 fix(window): avoid invalid fallback value for openNoteContexts 2025-12-30 09:44:58 +08:00
SiriusXT
4d2b02eddb Merge branch 'main' into feat/extra-window 2025-12-30 09:03:26 +08:00
SiriusXT
07871853a5 fix(window): cannot save when switching between multiple windows 2025-12-29 19:24:53 +08:00
SiriusXT
254145f0e5 chore(window): handle potential JSON parsing failures 2025-12-29 16:26:50 +08:00
SiriusXT
c28f11336e chore(window_db): fix potential migration error 2025-12-29 16:11:49 +08:00
SiriusXT
2e30683b7b chore(window): avoid reduce error when no candidates 2025-12-29 16:08:29 +08:00
SiriusXT
0af7b8b145 chore(window): use MAX_SAVED_WINDOWS constant 2025-12-29 15:56:04 +08:00
SiriusXT
5d39b84886 fix(window): Fix incorrect noteContents error 2025-12-29 15:28:27 +08:00
SiriusXT
537c4051cc feat(window): add class to extra windows 2025-12-29 15:27:35 +08:00
SiriusXT
d0a22bc517 fix(window): Fix empty array issue during openNoteContents data migration 2025-12-29 15:27:11 +08:00
SiriusXT
19a75acf3f Merge branch 'main' into feat/extra-window 2025-12-29 14:44:25 +08:00
SiriusXT
3f0abce874 feat(window_db): migrate openNoteContexts to structured format with window metadata 2025-12-29 14:43:49 +08:00
SiriusXT
36dd29f919 feat(window): add class to extra windows 2025-12-29 14:37:40 +08:00
SiriusXT
d7838f0b67 feat(window): restore recently closed windows from tray 2025-12-29 14:37:35 +08:00
SiriusXT
3353d4f436 feat(window): record openNoteContents of recently closed windows 2025-12-29 14:33:34 +08:00
SiriusXT
7740154bdc feat(window): add windowId for extra windows 2025-12-29 14:32:53 +08:00
60 changed files with 416 additions and 366 deletions

View File

@@ -16,7 +16,7 @@
"fs-extra": "11.3.3",
"react": "19.2.3",
"react-dom": "19.2.3",
"typedoc": "0.28.16",
"typedoc": "0.28.15",
"typedoc-plugin-missing-exports": "4.1.2"
}
}

View File

@@ -59,9 +59,9 @@
"mind-elixir": "5.5.0",
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.28.2",
"preact": "10.28.1",
"react-i18next": "16.5.1",
"react-window": "2.2.5",
"react-window": "2.2.4",
"reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",

View File

@@ -542,6 +542,7 @@ export type FilteredCommandNames<T extends CommandData> = keyof Pick<CommandMapp
export class AppContext extends Component {
isMainWindow: boolean;
windowId: string;
components: Component[];
beforeUnloadListeners: (WeakRef<BeforeUploadListener> | (() => boolean))[];
tabManager!: TabManager;
@@ -550,10 +551,11 @@ export class AppContext extends Component {
lastSearchString?: string;
constructor(isMainWindow: boolean) {
constructor(isMainWindow: boolean, windowId: string) {
super();
this.isMainWindow = isMainWindow;
this.windowId = windowId;
// non-widget/layout components needed for the application
this.components = [];
this.beforeUnloadListeners = [];
@@ -683,8 +685,7 @@ export class AppContext extends Component {
this.beforeUnloadListeners = this.beforeUnloadListeners.filter(l => l !== listener);
}
}
const appContext = new AppContext(window.glob.isMainWindow);
const appContext = new AppContext(window.glob.isMainWindow, window.glob.windowId);
// we should save all outstanding changes before the page/app is closed
$(window).on("beforeunload", () => {

View File

@@ -142,14 +142,15 @@ export default class Entrypoints extends Component {
}
async openInWindowCommand({ notePath, hoistedNoteId, viewScope }: NoteCommandData) {
const extraWindowId = utils.randomString(4);
const extraWindowHash = linkService.calculateHash({ notePath, hoistedNoteId, viewScope });
if (utils.isElectron()) {
const { ipcRenderer } = utils.dynamicRequire("electron");
ipcRenderer.send("create-extra-window", { extraWindowHash });
ipcRenderer.send("create-extra-window", { extraWindowId, extraWindowHash });
} else {
const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extraWindow=1${extraWindowHash}`;
const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extraWindow=${extraWindowId}${extraWindowHash}`;
window.open(url, "", "width=1000,height=800");
}

View File

@@ -11,6 +11,8 @@ import linkService from "../services/link.js";
import type { EventData } from "./app_context.js";
import type FNote from "../entities/fnote.js";
const MAX_SAVED_WINDOWS = 10;
interface TabState {
contexts: NoteContext[];
position: number;
@@ -25,6 +27,13 @@ interface NoteContextState {
viewScope: Record<string, any>;
}
interface WindowState {
windowId: string;
createdAt: number;
closedAt: number;
contexts: NoteContextState[];
}
export default class TabManager extends Component {
public children: NoteContext[];
public mutex: Mutex;
@@ -41,9 +50,6 @@ export default class TabManager extends Component {
this.recentlyClosedTabs = [];
this.tabsUpdate = new SpacedUpdate(async () => {
if (!appContext.isMainWindow) {
return;
}
if (options.is("databaseReadonly")) {
return;
}
@@ -52,9 +58,21 @@ export default class TabManager extends Component {
.map((nc) => nc.getPojoState())
.filter((t) => !!t);
await server.put("options", {
openNoteContexts: JSON.stringify(openNoteContexts)
});
// Update the current windows openNoteContexts in options
const savedWindows = options.getJson("openNoteContexts") || [];
const win = savedWindows.find((w: WindowState) => w.windowId === appContext.windowId);
if (win) {
win.contexts = openNoteContexts;
} else {
savedWindows.push({
windowId: appContext.windowId,
createdAt: Date.now(),
closedAt: 0,
contexts: openNoteContexts
} as WindowState);
}
await options.save("openNoteContexts", JSON.stringify(savedWindows));
});
appContext.addBeforeUnloadListener(this);
@@ -69,8 +87,13 @@ export default class TabManager extends Component {
}
async loadTabs() {
// Get the current windows openNoteContexts
const savedWindows = options.getJson("openNoteContexts") || [];
const currentWin = savedWindows.find(w => w.windowId === appContext.windowId);
const openNoteContexts = currentWin ? currentWin.contexts : undefined;
try {
const noteContextsToOpen = (appContext.isMainWindow && options.getJson("openNoteContexts")) || [];
const noteContextsToOpen = openNoteContexts || [];
// preload all notes at once
await froca.getNotes([...noteContextsToOpen.flatMap((tab: NoteContextState) =>
@@ -119,6 +142,51 @@ export default class TabManager extends Component {
}
});
// Save window contents
if (currentWin as WindowState) {
currentWin.createdAt = Date.now();
currentWin.closedAt = 0;
currentWin.contexts = filteredNoteContexts;
} else {
if (savedWindows?.length >= MAX_SAVED_WINDOWS) {
// Filter out the oldest entry
// 1) Never remove the "main" window
// 2) Prefer removing the oldest closed window (closedAt !== 0)
// 3) If no closed window exists, remove the window with the oldest created window
let oldestClosedIndex = -1;
let oldestClosedTime = Infinity;
let oldestCreatedIndex = -1;
let oldestCreatedTime = Infinity;
savedWindows.forEach((w: WindowState, i: number) => {
if (w.windowId === "main") return;
if (w.closedAt !== 0) {
if (w.closedAt < oldestClosedTime) {
oldestClosedTime = w.closedAt;
oldestClosedIndex = i;
}
} else {
if (w.createdAt < oldestCreatedTime) {
oldestCreatedTime = w.createdAt;
oldestCreatedIndex = i;
}
}
});
const indexToRemove = oldestClosedIndex !== -1 ? oldestClosedIndex : oldestCreatedIndex;
if (indexToRemove !== -1) {
savedWindows.splice(indexToRemove, 1);
}
}
savedWindows.push({
windowId: appContext.windowId,
createdAt: Date.now(),
closedAt: 0,
contexts: filteredNoteContexts
} as WindowState);
}
await options.save("openNoteContexts", JSON.stringify(savedWindows));
// if there's a notePath in the URL, make sure it's open and active
// (useful, for e.g., opening clipped notes from clipper or opening link in an extra window)
if (parsedFromUrl.notePath) {

View File

@@ -71,7 +71,7 @@ function loadIcons() {
}
function setBodyAttributes() {
const { device, headingStyle, layoutOrientation, platform, isElectron, hasNativeTitleBar, hasBackgroundEffects, currentLocale } = window.glob;
const { device, headingStyle, layoutOrientation, platform, isElectron, hasNativeTitleBar, hasBackgroundEffects, currentLocale, isMainWindow } = window.glob;
const classesToSet = [
device,
`heading-style-${headingStyle}`,
@@ -79,7 +79,8 @@ function setBodyAttributes() {
`platform-${platform}`,
isElectron && "electron",
hasNativeTitleBar && "native-titlebar",
hasBackgroundEffects && "background-effects"
hasBackgroundEffects && "background-effects",
!isMainWindow && 'extra-window'
].filter(Boolean) as string[];
for (const classToSet of classesToSet) {

View File

@@ -27,10 +27,6 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
loadResults.addRevision(ec.entityId, ec.noteId, ec.componentId);
} else if (ec.entityName === "options") {
const attributeEntity = ec.entity as FAttributeRow;
if (attributeEntity.name === "openNoteContexts") {
continue; // only noise
}
options.set(attributeEntity.name as OptionNames, attributeEntity.value);
loadResults.addOption(attributeEntity.name as OptionNames);
} else if (ec.entityName === "attachments") {

View File

@@ -13,7 +13,8 @@ function injectGlobals() {
uncheckedWindow.$ = $;
uncheckedWindow.WebSocket = () => {};
uncheckedWindow.glob = {
isMainWindow: true
isMainWindow: true,
windowId: "main"
};
}

View File

@@ -798,8 +798,7 @@
"expand_tooltip": "展开此集合的直接子代(单层深度)。点击右方箭头以查看更多选项。",
"expand_first_level": "展开直接子代",
"expand_nth_level": "展开 {{depth}} 层",
"expand_all_levels": "展开所有层级",
"hide_child_notes": "隐藏树中的子笔记"
"expand_all_levels": "展开所有层级"
},
"edited_notes": {
"no_edited_notes_found": "今天还没有编辑过的笔记...",
@@ -1506,10 +1505,7 @@
"duplicate": "复制",
"open-in-popup": "快速编辑",
"archive": "归档",
"unarchive": "解压",
"open-in-a-new-window": "在新窗口中打开",
"hide-subtree": "隐藏子树",
"show-subtree": "显示子树"
"unarchive": "解压"
},
"shared_info": {
"help_link": "访问 <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a> 获取帮助。",
@@ -1602,9 +1598,7 @@
"shared-indicator-tooltip": "此笔记已公开分享",
"shared-indicator-tooltip-with-url": "此笔记已公开分享至:{{- url}}",
"clone-indicator-tooltip": "此笔记有 {{- count}} 个父级: {{- parents}}",
"clone-indicator-tooltip-single": "此笔记已克隆1 个额外的父级:{{- parent}}",
"subtree-hidden-tooltip_other": "从树中隐藏的 {{count}} 篇子笔记",
"subtree-hidden-moved-title": "已添加到 {{title}}"
"clone-indicator-tooltip-single": "此笔记已克隆1 个额外的父级:{{- parent}}"
},
"title_bar_buttons": {
"window-on-top": "保持此窗口置顶"

View File

@@ -1,10 +1,7 @@
{
"about": {
"title": "ट्रिलियम नोट्स के बारें में",
"build_date": "निर्माण की तारीख:",
"app_version": "ऐप वर्ज़न:",
"db_version": "DB वर्ज़न:",
"build_revision": "बिल्ड रिविज़न:"
"build_date": "निर्माण की तारीख:"
},
"toast": {
"widget-error": {

View File

@@ -443,10 +443,7 @@
"unhoist-note": "ノートのホイストを解除",
"edit-branch-prefix": "ブランチの接頭辞を編集",
"archive": "アーカイブ",
"unarchive": "アーカイブ解除",
"open-in-a-new-window": "新しいウィンドウで開く",
"hide-subtree": "サブツリーを非表示",
"show-subtree": "サブツリーを表示"
"unarchive": "アーカイブ解除"
},
"zen_mode": {
"button_exit": "禅モードを退出"
@@ -571,8 +568,7 @@
"expand_tooltip": "このコレクションの直下の子1階層下を展開します。その他のオプションについては、右側の矢印を押してください。",
"expand_first_level": "直下の子を展開",
"expand_nth_level": "{{depth}} 階層下まで展開",
"expand_all_levels": "すべての階層を展開",
"hide_child_notes": "ツリー内の子ノートを非表示"
"expand_all_levels": "すべての階層を展開"
},
"note_types": {
"geo-map": "ジオマップ",
@@ -1252,11 +1248,7 @@
"clone-indicator-tooltip": "このノートには {{- count}} 個の親があります: {{- parents}}",
"clone-indicator-tooltip-single": "このノートは複製されています (親が 1 件追加: {{- parent}})",
"shared-indicator-tooltip": "このノートは公開されています",
"shared-indicator-tooltip-with-url": "このノートは以下で公開されています: {{- url}}",
"subtree-hidden-tooltip_other": "{{count}} 個の子ノートがツリーで非表示になっています",
"subtree-hidden-moved-title": "{{title}} に追加されました",
"subtree-hidden-moved-description-collection": "このコレクションはツリー内の子ノートを非表示にします。",
"subtree-hidden-moved-description-other": "このノートのツリーでは子ノートは非表示になっています。"
"shared-indicator-tooltip-with-url": "このノートは以下で公開されています: {{- url}}"
},
"bulk_actions": {
"bulk_actions": "一括操作",

View File

@@ -18,47 +18,5 @@
"zpetne_odkazy": {
"backlink_one": "{{count}} Tilbakelenke",
"backlink_other": "{{count}} Tilbakelenker"
},
"add_link": {
"note": "Notat"
},
"branch_prefix": {
"prefix": "Prefiks : ",
"save": "Lagre"
},
"bulk_actions": {
"labels": "Etiketter",
"relations": "Relasjoner",
"notes": "Notater",
"other": "Andre"
},
"confirm": {
"confirmation": "Bekreftelse",
"cancel": "Avbryt",
"ok": "OK"
},
"delete_notes": {
"close": "Lukk",
"cancel": "Avbryt",
"ok": "OK"
},
"export": {
"close": "Lukk",
"export": "Eksporter"
},
"note_type_chooser": {
"templates": "Maler"
},
"help": {
"title": "Hurtigveiledning",
"troubleshooting": "Feilsøking",
"other": "Andre"
},
"import": {
"options": "Alternativer",
"import": "Importer"
},
"include_note": {
"label_note": "Notat"
}
}

View File

@@ -12,7 +12,7 @@
"toast": {
"critical-error": {
"title": "Kritische Error",
"message": "Een kritieke fout heeft plaatsgevonden waardoor de applicatie niet kon opstarten:\n\n{{message}}\n\nDit is waarschijnlijk veroorzaakt door een onverwachte fout in een script. Probeer de applicatie op te starten in veilige modus en het probleem op te lossen."
"message": "Een kritieke fout heeft plaatsgevonden waardoor de cliënt zich aanmeldt vanaf het begin:\n\n84X\n\nDit is waarschijnlijk veroorzaakt door een script dat op een onverwachte manier faalt. Probeer de sollicitatie in veilige modus te starten en de kwestie aan te spreken."
},
"widget-error": {
"title": "Starten widget mislukt",
@@ -22,16 +22,7 @@
"bundle-error": {
"title": "Custom script laden mislukt",
"message": "Script van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}"
},
"scripting-error": "Error met script: {{title}}",
"widget-list-error": {
"title": "Kon geen lijst met widgets ophalen van de server"
},
"widget-render-error": {
"title": "React-widget kon niet geladen worden"
},
"widget-missing-parent": "Widget heeft niet het verplichte '{{property}}'-veld gedefinieerd.\n\nAls dit script is bedoeld om zonder interface te draaien, gebruik dan in plaats daarvan '#run=frontendStartup'.",
"open-script-note": "Open scriptnotitie"
}
},
"add_link": {
"add_link": "Voeg link toe",
@@ -50,8 +41,7 @@
"help_on_tree_prefix": "Help bij boomvoorvoegsel",
"prefix": "Voorvoegsel: ",
"edit_branch_prefix_multiple": "Bewerk zijtakvoorvoegsel voor {{count}} zijtakken",
"branch_prefix_saved_multiple": "Vertakkingsvoorvoegsel opgeslagen voor {{count}} vertakkingen.",
"affected_branches": "Aangetaste takken ({{count}}):"
"branch_prefix_saved_multiple": "Vertakkingsvoorvoegsel opgeslagen voor {{count}} vertakkingen."
},
"bulk_actions": {
"bulk_actions": "Bulk acties",
@@ -64,8 +54,7 @@
"labels": "Labels",
"relations": "Relaties",
"notes": "Notities",
"other": "Andere",
"include_descendants": "Tel afstammelingen van de geselecteerde notities mee"
"other": "Andere"
},
"calendar": {
"april": "April",
@@ -89,35 +78,5 @@
},
"show_toc_widget_button": {
"show_toc": "Laat Inhoudsopgave zien"
},
"status_bar": {
"note_paths_one": "{{count}} pad",
"note_paths_other": "{{count}} paden",
"note_paths_title": "Notitiepaden",
"code_note_switcher": "Verander de taalmodus"
},
"attributes_panel": {
"title": "Notitie-attributen"
},
"right_pane": {
"empty_message": "Geen informatie voor deze notitie",
"empty_button": "Verberg dit paneel",
"toggle": "Schakel rechterpaneel in/uit",
"custom_widget_go_to_source": "Go naar de broncode"
},
"pdf": {
"attachments_one": "{{count}} bijlage",
"attachments_other": "{{count}} bijlagen",
"layers_one": "{{count}} laag",
"layers_other": "{{count}} lagen",
"pages_one": "{{count}} pagina",
"pages_other": "{{count}} pagina's",
"pages_alt": "Pagina {{pageNumber}}",
"pages_loading": "Laden..."
},
"clone_to": {
"clone_notes_to": "Kloon de notities naar...",
"help_on_links": "Hulp op links",
"notes_to_clone": "Notities om te klonen"
}
}

View File

@@ -22,16 +22,7 @@
"bundle-error": {
"title": "Falha para carregar o script customizado",
"message": "O script da nota com ID \"{{id}}\", intitulada \"{{title}}\", não pôde ser executado devido a:\n\n{{message}}"
},
"widget-list-error": {
"title": "Falha ao obter a lista de widgets do servidor"
},
"scripting-error": "Erro do script específicado: {{title}}",
"open-script-note": "Abrir script da nota",
"widget-render-error": {
"title": "Falha do renderizar um widget React personalizado"
},
"widget-missing-parent": "Widget adaptado não tem a propriedade '{{property}}' mandatória definida.\n\nSe este script é para ser executado sem um element de UI, usar '#run=frontendStartup'."
}
},
"add_link": {
"add_link": "Adicionar ligação",
@@ -48,10 +39,7 @@
"help_on_tree_prefix": "Ajuda sobre o prefixo da árvore de notas",
"prefix": "Prefixo: ",
"save": "Gravar",
"branch_prefix_saved": "O prefixo de ramificação foi gravado.",
"edit_branch_prefix_multiple": "Editar prefixo para {{count}} branches",
"branch_prefix_saved_multiple": "Prefixo dos branches foi editado para {{count}} branches.",
"affected_branches": "Alterados ({{count}}) branches:"
"branch_prefix_saved": "O prefixo de ramificação foi gravado."
},
"bulk_actions": {
"bulk_actions": "Ações em massa",
@@ -116,8 +104,7 @@
"export_status": "Estado da exportação",
"export_in_progress": "Exportação em andamento: {{progressCount}}",
"export_finished_successfully": "Exportação concluída com sucesso.",
"format_pdf": "PDF para impressão ou compartilhamento.",
"share-format": "HTML para publicação web - usa o mesmo tema que é usado para notas partilhadas, mas pode ser publicado como um site estatico."
"format_pdf": "PDF para impressão ou compartilhamento."
},
"help": {
"title": "Folha de Dicas",
@@ -171,8 +158,7 @@
"showSQLConsole": "mostrar console SQL",
"other": "Outros",
"quickSearch": "focar no campo de pesquisa rápida",
"inPageSearch": "pesquisa na página",
"editShortcuts": "Editar atalhos do teclado"
"inPageSearch": "pesquisa na página"
},
"import": {
"importIntoNote": "Importar para a nota",
@@ -198,8 +184,7 @@
},
"import-status": "Estado da importação",
"in-progress": "Importação em andamento: {{progress}}",
"successful": "Importação concluída com sucesso.",
"importZipRecommendation": "Quando a importar ficheiro ZIP, a hierarquia de notas vai reflectir a estrutura da sub directoria dentro do ficheiro."
"successful": "Importação concluída com sucesso."
},
"include_note": {
"dialog_title": "Incluir nota",
@@ -214,8 +199,7 @@
"info": {
"modalTitle": "Mensagem informativa",
"closeButton": "Fechar",
"okButton": "OK",
"copy_to_clipboard": "Copiar para a área de transferência"
"okButton": "OK"
},
"jump_to_note": {
"search_placeholder": "Pesquise uma nota pelo nome ou digite > para comandos...",
@@ -290,12 +274,7 @@
"download_button": "Descarregar",
"mime": "MIME: ",
"file_size": "Tamanho do ficheiro:",
"preview_not_available": "A visualização não está disponível para este tipo de nota.",
"diff_on": "Mostrar diferenças",
"diff_off": "Mostrar conteúdos",
"diff_on_hint": "Carregar para mostrar diferenças da fonte da nota",
"diff_off_hint": "Carregar para mostrar conteúdos da nota",
"diff_not_available": "Diferenças não disponível."
"preview_not_available": "A visualização não está disponível para este tipo de nota."
},
"sort_child_notes": {
"sort_children_by": "Ordenar notas filhas por...",
@@ -606,18 +585,7 @@
"september": "Setembro",
"october": "Outubro",
"november": "Novembro",
"december": "Dezembro",
"week": "Semana",
"week_previous": "Semana anterior",
"week_next": "Próxima semana",
"month": "Mês",
"month_previous": "Mês anterior",
"month_next": "Próximo mês",
"year": "Ano",
"year_previous": "Ano anterior",
"year_next": "Próximo ano",
"list": "Lista",
"today": "Hoje"
"december": "Dezembro"
},
"close_pane_button": {
"close_this_pane": "Fechar este painel"
@@ -660,9 +628,7 @@
"about": "Sobre o Trilium Notes",
"logout": "Sair",
"show-cheatsheet": "Exibir Cheatsheet",
"toggle-zen-mode": "Modo Zen",
"new-version-available": "Nova actualização disponível",
"download-update": "Obter versão {{latestVersion}}"
"toggle-zen-mode": "Modo Zen"
},
"zen_mode": {
"button_exit": "Sair do Modo Zen"
@@ -700,14 +666,7 @@
"convert_into_attachment_failed": "A conversão da nota '{{title}}' falhou.",
"convert_into_attachment_successful": "A nota '{{title}}' foi convertida para anexo.",
"convert_into_attachment_prompt": "Tem certeza que quer converter a nota '{{title}}' num anexo da nota pai?",
"print_pdf": "Exportar como PDF…",
"open_note_on_server": "Abrir nota no servidor",
"export_as_image": "Exportar como imagem",
"note_map": "Mapa de notas",
"advanced": "Avançadas",
"view_revisions": "Revisões da nota...",
"export_as_image_svg": "SVG (vectorial)",
"export_as_image_png": "PNG (matricial)"
"print_pdf": "Exportar como PDF…"
},
"onclick_button": {
"no_click_handler": "Componente de botão '{{componentId}}' não possui manipulador de clique definido"
@@ -753,26 +712,19 @@
"zpetne_odkazy": {
"relation": "relação",
"backlink_one": "{{count}} Ligação Reversa",
"backlink_many": "{{count}} Ligações Reversas",
"backlink_many": "",
"backlink_other": "{{count}} Ligações Reversas"
},
"mobile_detail_menu": {
"insert_child_note": "Inserir nota filha",
"delete_this_note": "Apagar esta nota",
"error_cannot_get_branch_id": "Não foi possível obter o branchId para o notePath '{{notePath}} '",
"error_unrecognized_command": "Comando não reconhecido {{command}}",
"note_revisions": "Revisões da nota"
"error_unrecognized_command": "Comando não reconhecido {{command}}"
},
"note_icon": {
"change_note_icon": "Alterar ícone da nota",
"search": "Pesquisa:",
"reset-default": "Redefinir para o ícone padrão",
"filter": "Filtrar",
"filter-none": "Todos os icons",
"filter-default": "Icons default",
"no_results": "Não foram encontrados icons.",
"search_placeholder_filtered": "Procurar {{number}} icons no {{name}}",
"icon_tooltip": "{{name}}\nPacote de icons: {{iconPack}}"
"reset-default": "Redefinir para o ícone padrão"
},
"basic_properties": {
"note_type": "Tipo da nota",
@@ -793,13 +745,7 @@
"calendar": "Calendário",
"table": "Tabela",
"geo-map": "Mapa geográfico",
"board": "Quadro",
"expand_first_level": "Expandir descendentes directos",
"presentation": "Apresentação",
"expand_nth_level": "Expandir {{depth}} níveis",
"expand_all_levels": "Expandir todos os níveis",
"include_archived_notes": "Mostrar notas arquivadas",
"expand_tooltip": "Expande a direcção dos descendentes desta colecção (um nível). Para mais opções, carregar na seta à direita."
"board": "Quadro"
},
"edited_notes": {
"no_edited_notes_found": "Ainda não há nenhuma nota editada neste dia…",
@@ -832,8 +778,7 @@
},
"inherited_attribute_list": {
"title": "Atributos Herdados",
"no_inherited_attributes": "Nenhum atributo herdado.",
"none": "Nenhum"
"no_inherited_attributes": "Nenhum atributo herdado."
},
"note_info_widget": {
"note_id": "ID da Nota",
@@ -844,9 +789,7 @@
"note_size_info": "O tamanho da nota fornece uma estimativa aproximada dos requisitos de armazenamento para esta nota. Leva em conta o conteúdo e o conteúdo das suas revisões de nota.",
"calculate": "calcular",
"subtree_size": "(tamanho da subárvore: {{size}} em {{count}} notas)",
"title": "Informações da nota",
"mime": "Tipo MIME",
"show_similar_notes": "Mostrar notas semelhantes"
"title": "Informações da nota"
},
"note_map": {
"open_full": "Expandir completamente",
@@ -909,8 +852,7 @@
"search_parameters": "Parâmetros de Pesquisa",
"unknown_search_option": "Opção de pesquisa desconhecida {{searchOptionName}}",
"search_note_saved": "Nota de pesquisa foi gravada em {{- notePathTitle}}",
"actions_executed": "As ações foram executadas.",
"view_options": "Ver opções:"
"actions_executed": "As ações foram executadas."
},
"similar_notes": {
"title": "Notas Similares",
@@ -1004,20 +946,14 @@
"no_attachments": "Esta nota não possuí anexos."
},
"book": {
"no_children_help": "Esta coleção não possui nenhum nota filha, então não há nada para exibir. Veja <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para pormenores.",
"drag_locked_title": "Bloqueado para edição",
"drag_locked_message": "Arrastar não permitida pois a coleção está bloqueada para edição."
"no_children_help": "Esta coleção não possui nenhum nota filha, então não há nada para exibir. Veja <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para pormenores."
},
"editable_code": {
"placeholder": "Digite o conteúdo da sua nota de código aqui…"
},
"editable_text": {
"placeholder": "Digite o conteúdo da sua nota aqui…",
"auto-detect-language": "Detetado automaticamente",
"editor_crashed_title": "O editor de texto quebrou",
"editor_crashed_details_button": "Ver mais detalhes...",
"editor_crashed_details_title": "Informação técnica",
"editor_crashed_details_intro": "Se teve este erro várias vezes, considerer reportar no GitHub disponibilizando a informação abaixo."
"auto-detect-language": "Detetado automaticamente"
},
"empty": {
"open_note_instruction": "Abra uma nota a digitar o título da nota no campo abaixo ou escolha uma nota na árvore.",

View File

@@ -797,8 +797,7 @@
"expand_tooltip": "展開此集合的直接子級(單層深度)。按下右側箭頭以查看更多選項。",
"expand_first_level": "展開直接子級",
"expand_nth_level": "展開 {{depth}} 層",
"expand_all_levels": "展開所有層級",
"hide_child_notes": "隱藏樹中的子筆記"
"expand_all_levels": "展開所有層級"
},
"edited_notes": {
"no_edited_notes_found": "今天還沒有編輯過的筆記...",
@@ -1467,10 +1466,7 @@
"duplicate": "複製副本",
"open-in-popup": "快速編輯",
"archive": "封存",
"unarchive": "解除封存",
"open-in-a-new-window": "在新視窗打開",
"hide-subtree": "隱藏子階層",
"show-subtree": "顯示子階層"
"unarchive": "解除封存"
},
"shared_info": {
"help_link": "如需幫助,請訪問 <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a>。",
@@ -1564,11 +1560,7 @@
"clone-indicator-tooltip": "此筆記有 {{- count}} 個父級:{{- parents}}",
"clone-indicator-tooltip-single": "此筆記已克隆(新增 1 個父級:{{- parent}}",
"shared-indicator-tooltip": "此筆記已公開分享",
"shared-indicator-tooltip-with-url": "此筆記已公開分享至:{{- url}}",
"subtree-hidden-tooltip_one": "從樹中隱藏的 {{count}} 篇子筆記",
"subtree-hidden-moved-title": "已新增至 {{title}}",
"subtree-hidden-moved-description-collection": "此集合隱藏其樹中的子筆記。",
"subtree-hidden-moved-description-other": "子筆記隱藏於此筆記的樹中。"
"shared-indicator-tooltip-with-url": "此筆記已公開分享至:{{- url}}"
},
"title_bar_buttons": {
"window-on-top": "保持此視窗置頂"

View File

@@ -36,6 +36,7 @@ interface CustomGlobals {
isProtectedSessionAvailable: boolean;
isDev: boolean;
isMainWindow: boolean;
windowId: string;
maxEntityChangeIdAtLoad: number;
maxEntityChangeSyncIdAtLoad: number;
assetPath: string;

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

View File

@@ -6,6 +6,7 @@ import sqlInit from "@triliumnext/server/src/services/sql_init.js";
import windowService from "@triliumnext/server/src/services/window.js";
import tray from "@triliumnext/server/src/services/tray.js";
import options from "@triliumnext/server/src/services/options.js";
import electronDebug from "electron-debug";
import electronDl from "electron-dl";
import { PRODUCT_NAME } from "./app-info";
@@ -69,10 +70,12 @@ async function main() {
globalShortcut.unregisterAll();
});
app.on("second-instance", (event, commandLine) => {
app.on("second-instance", async (event, commandLine) => {
const lastFocusedWindow = windowService.getLastFocusedWindow();
if (commandLine.includes("--new-window")) {
windowService.createExtraWindow("");
const randomString = (await import("@triliumnext/server/src/services/utils.js")).randomString;
const extraWindowId = randomString(4);
windowService.createExtraWindow(extraWindowId, "");
} else if (lastFocusedWindow) {
if (lastFocusedWindow.isMinimized()) {
lastFocusedWindow.restore();
@@ -124,7 +127,8 @@ async function onReady() {
}
});
}
await normalizeOpenNoteContexts();
tray.createTray();
} else {
await windowService.createSetupWindow();
@@ -133,6 +137,30 @@ async function onReady() {
await windowService.registerGlobalShortcuts();
}
/**
* Some windows may have closed abnormally, leaving closedAt as 0 in openNoteContexts.
* This function normalizes those timestamps to the current time for correct sorting/filtering.
*/
async function normalizeOpenNoteContexts() {
const savedWindows = options.getOptionJson("openNoteContexts") || [];
const now = Date.now();
let changed = false;
for (const win of savedWindows) {
if (win.windowId !== "main" && win.closedAt === 0) {
win.closedAt = now;
changed = true;
}
}
if (changed) {
const { default: cls } = (await import("@triliumnext/server/src/services/cls.js"));
cls.wrap(() => {
options.setOption("openNoteContexts", JSON.stringify(savedWindows));
})();
}
}
function getElectronLocale() {
const uiLocale = options.getOptionOrNull("locale");
const formattingLocale = options.getOptionOrNull("formattingLocale");

View File

@@ -43,7 +43,7 @@ test("Highlights list is displayed", async ({ page, context }) => {
await app.closeAllTabs();
await app.goToNoteInNewTab("Highlights list");
await expect(app.sidebar).toContainText("10 highlights");
await expect(app.sidebar).toContainText(/highlights/i);
const rootList = app.sidebar.locator(".highlights-list ol");
let index = 0;
for (const highlightedEl of ["Bold 1", "Italic 1", "Underline 1", "Colored text 1", "Background text 1", "Bold 2", "Italic 2", "Underline 2", "Colored text 2", "Background text 2"]) {

View File

@@ -59,7 +59,7 @@ export default class App {
// Wait for the page to load.
if (url === "/") {
await expect(this.page.locator(".tree")).toContainText("Trilium Integration Test");
await expect(this.noteTree).toContainText("Trilium Integration Test");
if (!preserveTabs) {
await this.closeAllTabs();
}

View File

@@ -123,6 +123,7 @@
"password-confirmation": "密码确认",
"button": "设置密码"
},
"javascript-required": "Trilium需要启用JavaScript。",
"setup": {
"heading": "TriliumNext笔记设置",
"new-document": "我是新用户我想为我的笔记创建一个新的Trilium文档",

View File

@@ -123,6 +123,7 @@
"password-confirmation": "Passwortbestätigung",
"button": "Passwort festlegen"
},
"javascript-required": "Trilium erfordert, dass JavaScript aktiviert ist.",
"setup": {
"heading": "Trilium Notes Setup",
"new-document": "Ich bin ein neuer Benutzer und möchte ein neues Trilium-Dokument für meine Notizen erstellen",

View File

@@ -381,6 +381,8 @@
"tooltip": "Trilium Notes",
"close": "Quit Trilium",
"recents": "Recent notes",
"recently-closed-windows": "Recently closed windows",
"tabs-total": "{{number}} tabs total",
"bookmarks": "Bookmarks",
"today": "Open today's journal note",
"new-note": "New note",

View File

@@ -123,6 +123,7 @@
"password-confirmation": "Confirmación de contraseña",
"button": "Establecer contraseña"
},
"javascript-required": "Trilium requiere que JavaScript esté habilitado.",
"setup": {
"heading": "Configuración de Trilium Notes",
"new-document": "Soy un usuario nuevo y quiero crear un nuevo documento de Trilium para mis notas",

View File

@@ -123,6 +123,7 @@
"password-confirmation": "Confirmation du mot de passe",
"button": "Définir le mot de passe"
},
"javascript-required": "Trilium nécessite que JavaScript soit activé.",
"setup": {
"heading": "Configuration de Trilium Notes",
"new-document": "Je suis un nouvel utilisateur et je souhaite créer un nouveau document Trilium pour mes notes",

View File

@@ -22,10 +22,6 @@
"ninth-tab": "लिस्ट में नौवीं टैब एक्टिवेट करें",
"last-tab": "लिस्ट में आखिरी टैब एक्टिवेट करें",
"show-sql-console": "\"SQL कंसोल\" पेज खोलें",
"show-backend-log": "\"बैकेंड लॉग\" पेज खोलें",
"quick-search": "क्विक सर्च बार को एक्टिवेट करें",
"search-in-subtree": "एक्टिव नोट के सब-ट्री में नोट्स खोजें",
"expand-subtree": "मौजूदा नोट के सब-ट्री को (subtree) एक्सपैंड करें",
"delete-note": "नोट डिलीट करें"
"show-backend-log": "\"बैकेंड लॉग\" पेज खोलें"
}
}

View File

@@ -324,6 +324,7 @@
"password-confirmation": "Conferma della password",
"button": "Imposta password"
},
"javascript-required": "Trilium richiede JavaScript abilitato per funzionare.",
"setup": {
"heading": "Configurazione di Trilium Notes",
"new-document": "Sono un nuovo utente, e desidero creare un nuovo documento Trilium per le mie note",

View File

@@ -220,6 +220,7 @@
"button": "パスワードの設定",
"password-confirmation": "パスワードの再入力"
},
"javascript-required": "Triliumを使用するにはJavaScriptを有効にする必要があります。",
"setup": {
"heading": "Trilium Notes セットアップ",
"new-document": "私は新しいユーザーで、ートを取るために新しいTriliumドキュメントを作成したい",

View File

@@ -7,11 +7,6 @@
"scroll-to-active-note": "Skroll notat-treet til aktivt notat",
"quick-search": "Aktiver hurtigsøk-feltet",
"search-in-subtree": "Søk etter notater i det aktive notatets understruktur",
"creating-and-moving-notes": "Lage og flytte notater",
"dialogs": "Dialogbokser",
"other": "Andre"
},
"setup_sync-from-desktop": {
"step6-here": "her"
"creating-and-moving-notes": "Lage og flytte notater"
}
}

View File

@@ -212,6 +212,7 @@
"button": "Zaloguj",
"sign_in_with_sso": "Zaloguj przez {{ ssoIssuerName }}"
},
"javascript-required": "Trilium wymaga włączenia obsługi JavaScript.",
"setup_sync-from-server": {
"server-host": "Adres serwera Trilium",
"proxy-server": "Serwer proxy (opcjonalnie)",

View File

@@ -220,6 +220,7 @@
"password-confirmation": "Confirmar Palavra-passe",
"button": "Definir palavra-passe"
},
"javascript-required": "Trilium precisa que JavaScript esteja ativado.",
"setup": {
"heading": "Trilium Notes setup",
"new-document": "Sou um novo utilizador e quero criar um documento Trilium para as minhas notas",

View File

@@ -123,6 +123,7 @@
"password-confirmation": "Confirmar Senha",
"button": "Definir senha"
},
"javascript-required": "Trilium precisa que JavaScript esteja habilitado.",
"setup": {
"heading": "Trilium Notes setup",
"new-document": "Sou um novo usuário e quero criar um novo documento Trilium para minhas notas",

View File

@@ -123,6 +123,7 @@
"password": "Parolă",
"password-confirmation": "Confirmarea parolei"
},
"javascript-required": "Trilium necesită JavaScript să fie activat pentru a putea funcționa.",
"setup": {
"heading": "Instalarea Trilium Notes",
"init-in-progress": "Se inițializează documentul",

View File

@@ -398,6 +398,7 @@
"parent": "родитель:",
"clipped-from": "Эта заметка изначально была вырезана из {{- url}}"
},
"javascript-required": "Для работы Trilium требуется JavaScript.",
"setup_sync-from-desktop": {
"heading": "Синхронизация с приложения ПК",
"description": "Эту настройку необходимо инициировать из приложения для ПК:",

View File

@@ -123,6 +123,7 @@
"password-confirmation": "確認密碼",
"button": "設定密碼"
},
"javascript-required": "Trilium 需要啟用 JavaScript。",
"setup": {
"heading": "Trilium 筆記設定",
"new-document": "我是新用戶,我想為我的筆記建立一個新的 Trilium 文件",

View File

@@ -220,6 +220,7 @@
"password-confirmation": "Підтвердження пароля",
"button": "Встановити пароль"
},
"javascript-required": "Для роботи Trilium потрібен JavaScript.",
"setup": {
"heading": "Налаштування Trilium Notes",
"new-document": "Я новий користувач і хочу створити новий документ Trilium для своїх нотаток",

View File

@@ -0,0 +1,48 @@
import cls from "../services/cls.js";
import sql from "../services/sql.js";
export default () => {
cls.init(() => {
const row = sql.getRow<{ value: string }>(
`SELECT value FROM options WHERE name = 'openNoteContexts'`
);
if (!row || !row.value) {
return;
}
let parsed: any;
try {
parsed = JSON.parse(row.value);
} catch {
return;
}
// Already in new format (array + windowId), skip
if (
Array.isArray(parsed) &&
parsed.length > 0 &&
parsed[0] &&
typeof parsed[0] === "object" &&
parsed[0].windowId
) {
return;
}
// Old format: just contexts
const migrated = [
{
windowId: "main",
createdAt: 0,
closedAt: 0,
contexts: parsed
}
];
sql.execute(
`UPDATE options SET value = ? WHERE name = 'openNoteContexts'`,
[JSON.stringify(migrated)]
);
});
};

View File

@@ -6,6 +6,11 @@
// Migrations should be kept in descending order, so the latest migration is first.
const MIGRATIONS: (SqlMigration | JsMigration)[] = [
// Migrate openNoteContexts option to the new structured format with window metadata
{
version: 234,
module: async () => import("./0234__migrate_open_note_contexts_format")
},
// Migrate geo map to collection
{
version: 233,

View File

@@ -50,6 +50,7 @@ export function bootstrap(req: Request, res: Response) {
appCssNoteIds: getAppCssNoteIds(),
isDev,
isMainWindow: view === "mobile" ? true : !req.query.extraWindow,
windowId: view !== "mobile" && req.query.extraWindow ? req.query.extraWindow : "main",
isProtectedSessionAvailable: protectedSessionService.isProtectedSessionAvailable(),
triliumVersion: packageJson.version,
assetPath,

View File

@@ -4,7 +4,7 @@ import packageJson from "../../package.json" with { type: "json" };
import dataDir from "./data_dir.js";
import { AppInfo } from "@triliumnext/commons";
const APP_DB_VERSION = 233;
const APP_DB_VERSION = 234;
const SYNC_VERSION = 36;
const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@@ -72,6 +72,19 @@ function getOptionBool(name: FilterOptionsByType<boolean>): boolean {
return val === "true";
}
function getOptionJson(name: OptionNames) {
const val = getOptionOrNull(name);
if (typeof val !== "string") {
return null;
}
try {
return JSON.parse(val);
} catch (e) {
return null;
}
}
function setOption<T extends OptionNames>(name: T, value: string | OptionDefinitions[T]) {
const option = becca.getOption(name);
@@ -137,6 +150,7 @@ export default {
getOption,
getOptionInt,
getOptionBool,
getOptionJson,
setOption,
createOption,
getOptions,

View File

@@ -45,8 +45,15 @@ async function initNotSyncedOptions(initialized: boolean, opts: NotSyncedOpts =
"openNoteContexts",
JSON.stringify([
{
notePath: "root",
active: true
windowId: "main",
createdAt: 0,
closedAt: 0,
contexts: [
{
notePath: "root",
active: true
}
]
}
]),
false
@@ -257,8 +264,15 @@ function initStartupOptions() {
"openNoteContexts",
JSON.stringify([
{
notePath: process.env.TRILIUM_START_NOTE_ID || "root",
active: true
windowId: "main",
createdAt: 0,
closedAt: 0,
contexts: [
{
notePath: process.env.TRILIUM_START_NOTE_ID || "root",
active: true
}
]
}
])
);

View File

@@ -147,8 +147,15 @@ async function createInitialDatabase(skipDemoDb?: boolean) {
"openNoteContexts",
JSON.stringify([
{
notePath: startNoteId,
active: true
windowId: "main",
createdAt: 0,
closedAt: 0,
contexts: [
{
notePath: startNoteId,
active: true
}
]
}
])
);

View File

@@ -196,6 +196,39 @@ function updateTrayMenu() {
return menuItems;
}
function buildClosedWindowsMenu() {
const savedWindows = optionService.getOptionJson("openNoteContexts") || [];
const openedWindowIds = windowService.getAllWindowIds();
const closedWindows = savedWindows
.filter(win => !openedWindowIds.includes(win.windowId))
.sort((a, b) => { return a.closedAt - b.closedAt; }); // sort by time in ascending order
const menuItems: Electron.MenuItemConstructorOptions[] = [];
for (let i = closedWindows.length - 1; i >= 0; i--) {
const win = closedWindows[i];
const activeCtx = win.contexts.find(c => c.active === true);
const activateNotePath = (activeCtx ?? win.contexts[0])?.notePath;
const activateNoteId = activateNotePath?.split("/").pop() ?? null;
if (!activateNoteId) continue;
// Get the title of the closed window
const winTitle = (() => {
const raw = becca_service.getNoteTitle(activateNoteId);
const truncated = raw.length > 20 ? `${raw.slice(0, 17)}` : raw;
const tabCount = win.contexts.filter(ctx => ctx.mainNtxId === null).length;
return tabCount > 1 ? `${truncated} (${t("tray.tabs-total", { number: tabCount })})` : truncated;
})();
menuItems.push({
label: winTitle,
type: "normal",
click: () => win.windowId !== "main" ? windowService.createExtraWindow(win.windowId, "") : windowService.createMainWindow()
});
}
return menuItems;
}
const windowVisibilityMenuItems: Electron.MenuItemConstructorOptions[] = [];
// Only call getWindowTitle if windowVisibilityMap has more than one window
@@ -258,6 +291,12 @@ function updateTrayMenu() {
icon: getIconPath("recents"),
submenu: buildRecentNotesMenu()
},
{
label: t("tray.recently-closed-windows"),
type: "submenu",
icon: getIconPath("closed-windows"),
submenu: buildClosedWindowsMenu()
},
{ type: "separator" },
{
label: t("tray.close"),

View File

@@ -16,28 +16,45 @@ import { formatDownloadTitle, isMac, isWindows } from "./utils.js";
// Prevent the window being garbage collected
let mainWindow: BrowserWindow | null;
let setupWindow: BrowserWindow | null;
let allWindows: BrowserWindow[] = []; // // Used to store all windows, sorted by the order of focus.
function trackWindowFocus(win: BrowserWindow) {
interface WindowEntry {
window: BrowserWindow;
windowId: string; // custom window ID
}
let allWindowEntries: WindowEntry[] = [];
function trackWindowFocus(win: BrowserWindow, windowId: string) {
// We need to get the last focused window from allWindows. If the last window is closed, we return the previous window.
// Therefore, we need to push the window into the allWindows array every time it gets focused.
win.on("focus", () => {
allWindows = allWindows.filter(w => !w.isDestroyed() && w !== win);
allWindows.push(win);
allWindowEntries = allWindowEntries.filter(w => !w.window.isDestroyed() && w.window !== win);
allWindowEntries.push({ window: win, windowId: windowId });
if (!optionService.getOptionBool("disableTray")) {
electron.ipcMain.emit("reload-tray");
}
});
win.on("closed", () => {
allWindows = allWindows.filter(w => !w.isDestroyed());
cls.wrap(() => {
const savedWindows = optionService.getOptionJson("openNoteContexts") || [];
const win = savedWindows.find(w => w.windowId === windowId);
if (win) {
win.closedAt = Date.now();
}
optionService.setOption("openNoteContexts", JSON.stringify(savedWindows));
})();
allWindowEntries = allWindowEntries.filter(w => !w.window.isDestroyed());
if (!optionService.getOptionBool("disableTray")) {
electron.ipcMain.emit("reload-tray");
}
});
}
async function createExtraWindow(extraWindowHash: string) {
async function createExtraWindow(extraWindowId: string, extraWindowHash: string) {
const spellcheckEnabled = optionService.getOptionBool("spellCheckEnabled");
const { BrowserWindow } = await import("electron");
@@ -56,15 +73,15 @@ async function createExtraWindow(extraWindowHash: string) {
});
win.setMenuBarVisibility(false);
win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1${extraWindowHash}`);
win.loadURL(`http://127.0.0.1:${port}/?extraWindow=${extraWindowId}${extraWindowHash}`);
configureWebContents(win.webContents, spellcheckEnabled);
trackWindowFocus(win);
trackWindowFocus(win, extraWindowId);
}
electron.ipcMain.on("create-extra-window", (event, arg) => {
createExtraWindow(arg.extraWindowHash);
createExtraWindow(arg.extraWindowId, arg.extraWindowHash);
});
interface PrintOpts {
@@ -168,8 +185,8 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string, ac
return { browserWindow, printReport };
}
async function createMainWindow(app: App) {
if ("setUserTasks" in app) {
async function createMainWindow(app?: App) {
if (app && "setUserTasks" in app) {
app.setUserTasks([
{
program: process.execPath,
@@ -219,7 +236,7 @@ async function createMainWindow(app: App) {
mainWindow.on("closed", () => (mainWindow = null));
configureWebContents(mainWindow.webContents, spellcheckEnabled);
trackWindowFocus(mainWindow);
trackWindowFocus(mainWindow, "main");
}
function getWindowExtraOpts() {
@@ -381,11 +398,15 @@ function getMainWindow() {
}
function getLastFocusedWindow() {
return allWindows.length > 0 ? allWindows[allWindows.length - 1] : null;
return allWindowEntries.length > 0 ? allWindowEntries[allWindowEntries.length - 1]?.window : null;
}
function getAllWindows() {
return allWindows;
return allWindowEntries.map(e => e.window);
}
function getAllWindowIds(): string[] {
return allWindowEntries.map(e => e.windowId);
}
export default {
@@ -396,5 +417,6 @@ export default {
registerGlobalShortcuts,
getMainWindow,
getLastFocusedWindow,
getAllWindows
getAllWindows,
getAllWindowIds
};

View File

@@ -11,7 +11,7 @@
"dependencies": {
"i18next": "25.7.3",
"i18next-http-backend": "3.0.2",
"preact": "10.28.2",
"preact": "10.28.1",
"preact-iso": "2.11.1",
"preact-render-to-string": "6.6.5",
"react-i18next": "16.5.1"

View File

@@ -8,8 +8,7 @@
"title": "अपने विचारों को व्यवस्थित करें। अपना व्यक्तिगत नॉलेज बेस बनाएं।",
"screenshot_alt": "ट्रिलियम नोट्स डेस्कटॉप एप्लिकेशन का स्क्रीनशॉट",
"get_started": "शुरू करें",
"github": "गिटहब",
"dockerhub": "डॉकर हब"
"github": "गिटहब"
},
"organization_benefits": {
"note_structure_title": "नोट संरचना",

View File

@@ -37,11 +37,5 @@
"search_content": "Of zoek naar tekst binnen notities en verfijn de zoekopdracht door in de bovenliggende notitie te filteren of zoekdiepte aan te geven.",
"web_clipper_title": "Web clipper",
"web_clipper_content": "Bewaar webpagina's (of schermafbeeldingen) en plaats deze direct in Trillium door de web clipper browser extensie te gebruiken."
},
"note_types": {
"title": "Meerdere manieren om je informatie te tonen",
"text_title": "Tekstnotities",
"text_description": "De notities worden bewerkt met een visuele (WYSIWYG) editor, met ondersteuning voor tabellen, plaatjes, wiskundige tekens, codeblokken met syntax-highlighting. Lijn tekst uit met Markdown-achtige syntax of met slash-commando's.",
"code_title": "Codenotities"
}
}

25
docs/README-hi.md vendored
View File

@@ -41,27 +41,26 @@ application with focus on building large personal knowledge bases.
unstable development version, updated daily with the latest features and
fixes.
## 📚 डॉक्यूमेंटेशन
## 📚 Documentation
**हमारे विस्तृत डॉक्यूमेंटेशन को
[docs.triliumnotes.org](https://docs.triliumnotes.org/) पर देखें**
**Visit our comprehensive documentation at
[docs.triliumnotes.org](https://docs.triliumnotes.org/)**
हमारा डॉक्यूमेंटेशन कई फॉर्मेट्स में उपलब्ध है:
- **ऑनलाइन डॉक्यूमेंटेशन**:
[docs.triliumnotes.org](https://docs.triliumnotes.org/) पर पूरा डॉक्यूमेंटेशन
देखें
- **इन-ऐप हेल्प**: उसी डॉक्यूमेंटेशन को सीधे ऐप में एक्सेस करने के लिए ट्रिलियम
के अंदर `F1` दबाएँ
Our documentation is available in multiple formats:
- **Online Documentation**: Browse the full documentation at
[docs.triliumnotes.org](https://docs.triliumnotes.org/)
- **In-App Help**: Press `F1` within Trilium to access the same documentation
directly in the application
- **GitHub**: Navigate through the [User Guide](./User%20Guide/User%20Guide/) in
this repository
### Quick Links
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup)
- [डॉकर
सेटअप](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
- [TriliumNext को अपग्रेड
करना](https://docs.triliumnotes.org/user-guide/setup/upgrading)
- [Docker
Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
- [Upgrading
TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading)
- [Basic Concepts and
Features](https://docs.triliumnotes.org/user-guide/concepts/notes)
- [Patterns of Personal Knowledge

View File

@@ -60,8 +60,8 @@ Vår dokumentasjon er tilgjengelig i flere format:
Docker](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
- [Oppgradere
TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading)
- [Grunnleggende konsepter og
funksjoner](https://docs.triliumnotes.org/user-guide/concepts/notes)
- [Basic Concepts and
Features](https://docs.triliumnotes.org/user-guide/concepts/notes)
- [Patterns of Personal Knowledge
Base](https://docs.triliumnotes.org/user-guide/misc/patterns-of-personal-knowledge)
@@ -112,7 +112,7 @@ Vår dokumentasjon er tilgjengelig i flere format:
* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced
showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases)
* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for
automatisering
automation
* Scales well in both usability and performance upwards of 100 000 notes
* Touch optimized [mobile
frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for
@@ -254,7 +254,7 @@ pnpm install
pnpm edit-docs:edit-docs
```
### Opprette kjørbar fil
### Building the Executable
Download the repository, install dependencies using `pnpm` and then build the
desktop app for Windows:
```shell

View File

@@ -98,7 +98,7 @@
},
"overrides": {
"mermaid": "11.12.2",
"preact": "10.28.2",
"preact": "10.28.1",
"roughjs": "4.6.6",
"@types/express-serve-static-core": "5.1.0",
"flat@<5.0.1": ">=5.0.1",

View File

@@ -54,7 +54,6 @@ export default function buildExtraCommands(): SlashCommandDefinition[] {
id: "math",
title: "Math equation",
description: "Insert a math equation",
aliases: [ "latex", "equation" ],
icon: mathIcons.ckeditor,
execute: (editor: Editor) => editor.plugins.get(MathUI)._showUI()
},

124
pnpm-lock.yaml generated
View File

@@ -6,7 +6,7 @@ settings:
overrides:
mermaid: 11.12.2
preact: 10.28.2
preact: 10.28.1
roughjs: 4.6.6
'@types/express-serve-static-core': 5.1.0
flat@<5.0.1: '>=5.0.1'
@@ -149,11 +149,11 @@ importers:
specifier: 19.2.3
version: 19.2.3(react@19.2.3)
typedoc:
specifier: 0.28.16
version: 0.28.16(typescript@5.9.3)
specifier: 0.28.15
version: 0.28.15(typescript@5.9.3)
typedoc-plugin-missing-exports:
specifier: 4.1.2
version: 4.1.2(typedoc@0.28.16(typescript@5.9.3))
version: 4.1.2(typedoc@0.28.15(typescript@5.9.3))
apps/client:
dependencies:
@@ -192,7 +192,7 @@ importers:
version: 2.11.8
'@preact/signals':
specifier: 2.5.1
version: 2.5.1(preact@10.28.2)
version: 2.5.1(preact@10.28.1)
'@triliumnext/ckeditor5':
specifier: workspace:*
version: link:../../packages/ckeditor5
@@ -287,14 +287,14 @@ importers:
specifier: 9.4.3
version: 9.4.3
preact:
specifier: 10.28.2
version: 10.28.2
specifier: 10.28.1
version: 10.28.1
react-i18next:
specifier: 16.5.1
version: 16.5.1(i18next@25.7.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
react-window:
specifier: 2.2.5
version: 2.2.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
specifier: 2.2.4
version: 2.2.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
reveal.js:
specifier: 5.2.1
version: 5.2.1
@@ -313,7 +313,7 @@ importers:
version: 5.0.0
'@prefresh/vite':
specifier: 2.4.11
version: 2.4.11(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.4.11(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@types/bootstrap':
specifier: 5.2.10
version: 5.2.10
@@ -820,21 +820,21 @@ importers:
specifier: 3.0.2
version: 3.0.2(encoding@0.1.13)
preact:
specifier: 10.28.2
version: 10.28.2
specifier: 10.28.1
version: 10.28.1
preact-iso:
specifier: 2.11.1
version: 2.11.1(preact-render-to-string@6.6.5(preact@10.28.2))(preact@10.28.2)
version: 2.11.1(preact-render-to-string@6.6.5(preact@10.28.1))(preact@10.28.1)
preact-render-to-string:
specifier: 6.6.5
version: 6.6.5(preact@10.28.2)
version: 6.6.5(preact@10.28.1)
react-i18next:
specifier: 16.5.1
version: 16.5.1(i18next@25.7.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
devDependencies:
'@preact/preset-vite':
specifier: 2.10.2
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
eslint:
specifier: 9.39.2
version: 9.39.2(jiti@2.6.1)
@@ -4011,7 +4011,7 @@ packages:
'@preact/signals@2.5.1':
resolution: {integrity: sha512-VPjk5YFt7i11Fi4UK0tzaEe5xLwfhUxXL3l89ocxQ5aPz7bRo8M5+N73LjBMPklyXKYKz6YsNo4Smp8n6nplng==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
'@prefresh/babel-plugin@0.5.2':
resolution: {integrity: sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==}
@@ -4019,7 +4019,7 @@ packages:
'@prefresh/core@1.5.5':
resolution: {integrity: sha512-H6GTXUl4V4fe3ijz7yhSa/mZ+pGSOh7XaJb6uP/sQsagBx9yl0D1HKDaeoMQA8Ad2Xm27LqvbitMGSdY9UFSKQ==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
'@prefresh/utils@1.2.1':
resolution: {integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==}
@@ -4027,13 +4027,13 @@ packages:
'@prefresh/vite@2.4.11':
resolution: {integrity: sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
vite: '>=2.0.0'
'@prefresh/vite@2.4.8':
resolution: {integrity: sha512-H7vlo9UbJInuRbZhRQrdgVqLP7qKjDoX7TgYWWwIVhEHeHO0hZ4zyicvwBrV1wX5A3EPOmArgRkUaN7cPI2VXQ==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
vite: '>=2.0.0'
'@promptbook/utils@0.69.5':
@@ -11667,16 +11667,16 @@ packages:
preact-iso@2.11.1:
resolution: {integrity: sha512-rLy0RmzP/hrDjnFdnEblxFgKtzUj4njkHrpGJBGS7S4QuYw1zv0lA38qsWpeAAB10JAz/hF2CsHrLen9ufCtbw==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
preact-render-to-string: '>=6.4.0'
preact-render-to-string@6.6.5:
resolution: {integrity: sha512-O6MHzYNIKYaiSX3bOw0gGZfEbOmlIDtDfWwN1JJdc/T3ihzRT6tGGSEWE088dWrEDGa1u7101q+6fzQnO9XCPA==}
peerDependencies:
preact: 10.28.2
preact: 10.28.1
preact@10.28.2:
resolution: {integrity: sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==}
preact@10.28.1:
resolution: {integrity: sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==}
prebuild-install@7.1.3:
resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
@@ -11946,8 +11946,8 @@ packages:
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-window@2.2.5:
resolution: {integrity: sha512-6viWvPSZvVuMIe9hrl4IIZoVfO/npiqOb03m4Z9w+VihmVzBbiudUrtUqDpsWdKvd/Ai31TCR25CBcFFAUm28w==}
react-window@2.2.4:
resolution: {integrity: sha512-FiZsQHvt2qbnTz6cN+/FXvX62v2xukQ+AajUivkm/Ivdp9rnU3bp0B1eDcCNpQXNaDBdqkEVGNYHlvIUGU9yBw==}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
@@ -13476,8 +13476,8 @@ packages:
peerDependencies:
typedoc: ^0.28.1
typedoc@0.28.16:
resolution: {integrity: sha512-x4xW77QC3i5DUFMBp0qjukOTnr/sSg+oEs86nB3LjDslvAmwe/PUGDWbe3GrIqt59oTqoXK5GRK9tAa0sYMiog==}
typedoc@0.28.15:
resolution: {integrity: sha512-mw2/2vTL7MlT+BVo43lOsufkkd2CJO4zeOSuWQQsiXoV2VuEn7f6IZp2jsUDPmBMABpgR0R5jlcJ2OGEFYmkyg==}
engines: {node: '>= 18', pnpm: '>= 10'}
hasBin: true
peerDependencies:
@@ -15024,8 +15024,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.3.0
'@ckeditor/ckeditor5-upload': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-ai@47.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
dependencies:
@@ -15172,8 +15170,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-code-block@47.3.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)':
dependencies:
@@ -15239,8 +15235,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-watchdog': 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-dev-build-tools@54.2.3(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)':
dependencies:
@@ -15366,8 +15360,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-classic@47.3.0':
dependencies:
@@ -15377,8 +15369,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-decoupled@47.3.0':
dependencies:
@@ -15388,8 +15378,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-inline@47.3.0':
dependencies:
@@ -15507,8 +15495,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-font@47.3.0':
dependencies:
@@ -15583,8 +15569,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-html-embed@47.3.0':
dependencies:
@@ -15884,8 +15868,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.3.0
'@ckeditor/ckeditor5-engine': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-real-time-collaboration@47.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
dependencies:
@@ -15916,8 +15898,6 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-restricted-editing@47.3.0':
dependencies:
@@ -16004,8 +15984,6 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-special-characters@47.3.0':
dependencies:
@@ -17401,7 +17379,7 @@ snapshots:
'@fullcalendar/core@6.1.20':
dependencies:
preact: 10.28.2
preact: 10.28.1
'@fullcalendar/daygrid@6.1.20(@fullcalendar/core@6.1.20)':
dependencies:
@@ -18426,12 +18404,12 @@ snapshots:
'@popperjs/core@2.11.8': {}
'@preact/preset-vite@2.10.2(@babel/core@7.28.0)(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@preact/preset-vite@2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.0
'@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0)
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.0)
'@prefresh/vite': 2.4.8(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@prefresh/vite': 2.4.8(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@rollup/pluginutils': 4.2.1
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.0)
debug: 4.4.1
@@ -18444,39 +18422,39 @@ snapshots:
'@preact/signals-core@1.12.1': {}
'@preact/signals@2.5.1(preact@10.28.2)':
'@preact/signals@2.5.1(preact@10.28.1)':
dependencies:
'@preact/signals-core': 1.12.1
preact: 10.28.2
preact: 10.28.1
'@prefresh/babel-plugin@0.5.2': {}
'@prefresh/core@1.5.5(preact@10.28.2)':
'@prefresh/core@1.5.5(preact@10.28.1)':
dependencies:
preact: 10.28.2
preact: 10.28.1
'@prefresh/utils@1.2.1': {}
'@prefresh/vite@2.4.11(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@prefresh/vite@2.4.11(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.0
'@prefresh/babel-plugin': 0.5.2
'@prefresh/core': 1.5.5(preact@10.28.2)
'@prefresh/core': 1.5.5(preact@10.28.1)
'@prefresh/utils': 1.2.1
'@rollup/pluginutils': 4.2.1
preact: 10.28.2
preact: 10.28.1
vite: 7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
'@prefresh/vite@2.4.8(preact@10.28.2)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@prefresh/vite@2.4.8(preact@10.28.1)(vite@7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.0
'@prefresh/babel-plugin': 0.5.2
'@prefresh/core': 1.5.5(preact@10.28.2)
'@prefresh/core': 1.5.5(preact@10.28.1)
'@prefresh/utils': 1.2.1
'@rollup/pluginutils': 4.2.1
preact: 10.28.2
preact: 10.28.1
vite: 7.3.1(@types/node@24.10.7)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
@@ -23965,7 +23943,7 @@ snapshots:
dependencies:
d3-selection: 3.0.0
kapsule: 1.16.3
preact: 10.28.2
preact: 10.28.1
flora-colossus@2.0.0:
dependencies:
@@ -27815,16 +27793,16 @@ snapshots:
potpack@2.1.0: {}
preact-iso@2.11.1(preact-render-to-string@6.6.5(preact@10.28.2))(preact@10.28.2):
preact-iso@2.11.1(preact-render-to-string@6.6.5(preact@10.28.1))(preact@10.28.1):
dependencies:
preact: 10.28.2
preact-render-to-string: 6.6.5(preact@10.28.2)
preact: 10.28.1
preact-render-to-string: 6.6.5(preact@10.28.1)
preact-render-to-string@6.6.5(preact@10.28.2):
preact-render-to-string@6.6.5(preact@10.28.1):
dependencies:
preact: 10.28.2
preact: 10.28.1
preact@10.28.2: {}
preact@10.28.1: {}
prebuild-install@7.1.3:
dependencies:
@@ -28113,7 +28091,7 @@ snapshots:
prop-types: 15.8.1
react: 19.2.3
react-window@2.2.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
react-window@2.2.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
@@ -30126,11 +30104,11 @@ snapshots:
typedarray@0.0.6: {}
typedoc-plugin-missing-exports@4.1.2(typedoc@0.28.16(typescript@5.9.3)):
typedoc-plugin-missing-exports@4.1.2(typedoc@0.28.15(typescript@5.9.3)):
dependencies:
typedoc: 0.28.16(typescript@5.9.3)
typedoc: 0.28.15(typescript@5.9.3)
typedoc@0.28.16(typescript@5.9.3):
typedoc@0.28.15(typescript@5.9.3):
dependencies:
'@gerrit0/mini-shiki': 3.17.0
lunr: 2.3.9