feat(window): restore recently closed windows from tray
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 727 B |
|
After Width: | Height: | Size: 828 B |
|
After Width: | Height: | Size: 931 B |
BIN
apps/desktop/src/assets/images/tray/closed-windowsTemplate.png
Normal file
|
After Width: | Height: | Size: 292 B |
|
After Width: | Height: | Size: 355 B |
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 492 B |
@ -382,6 +382,8 @@
|
|||||||
"tooltip": "Trilium Notes",
|
"tooltip": "Trilium Notes",
|
||||||
"close": "Quit Trilium",
|
"close": "Quit Trilium",
|
||||||
"recents": "Recent notes",
|
"recents": "Recent notes",
|
||||||
|
"recently-closed-windows": "Recently closed windows",
|
||||||
|
"tabs-total": "total {{number}} tabs",
|
||||||
"bookmarks": "Bookmarks",
|
"bookmarks": "Bookmarks",
|
||||||
"today": "Open today's journal note",
|
"today": "Open today's journal note",
|
||||||
"new-note": "New note",
|
"new-note": "New note",
|
||||||
|
|||||||
@ -196,6 +196,44 @@ function updateTrayMenu() {
|
|||||||
return menuItems;
|
return menuItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildClosedWindowsMenu() {
|
||||||
|
const savedOpenNoteContexts = JSON.parse(optionService.getOption("openNoteContexts") || "[]");
|
||||||
|
const openedWindowIds = windowService.getAllWindowIds();
|
||||||
|
const closedWindows = savedOpenNoteContexts
|
||||||
|
.filter(win => !openedWindowIds.includes(win.windowId))
|
||||||
|
.sort((a, b) => {
|
||||||
|
// If closedAt is null, it indicates an abnormal closure and should be placed at the end
|
||||||
|
if (a.closedAt === null && b.closedAt === null) return 0;
|
||||||
|
if (a.closedAt === null) return 1;
|
||||||
|
if (b.closedAt === null) return -1;
|
||||||
|
// Otherwise, sort by time in descending order
|
||||||
|
return b.closedAt - a.closedAt;
|
||||||
|
});
|
||||||
|
const menuItems: Electron.MenuItemConstructorOptions[] = [];
|
||||||
|
for (const win of closedWindows) {
|
||||||
|
const activeCtx = win.contexts.find(c => c.active === true);
|
||||||
|
const activateNotePath = (activeCtx ?? win.contexts[0])?.notePath;
|
||||||
|
const activateNoteId = activateNotePath?.split("/").pop() ?? null;
|
||||||
|
|
||||||
|
// Get the title of the closed window
|
||||||
|
const rawTitle = activateNoteId ? becca_service.getNoteTitle(activateNoteId) : "";
|
||||||
|
let winTitle = rawTitle.length > 20 ? `${rawTitle.slice(0, 17)}...` : rawTitle;
|
||||||
|
const mainTabCount = win.contexts.filter(ctx => ctx.mainNtxId === null).length;
|
||||||
|
if (mainTabCount > 1) {
|
||||||
|
const tabSuffix = t("tray.tabs-total", { number: mainTabCount });
|
||||||
|
winTitle += ` (${tabSuffix})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuItems.push({
|
||||||
|
label: winTitle,
|
||||||
|
type: "normal",
|
||||||
|
click: () => win.windowId !== "main" ? windowService.createExtraWindow(win.windowId, "") : windowService.createMainWindow()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuItems;
|
||||||
|
}
|
||||||
|
|
||||||
const windowVisibilityMenuItems: Electron.MenuItemConstructorOptions[] = [];
|
const windowVisibilityMenuItems: Electron.MenuItemConstructorOptions[] = [];
|
||||||
|
|
||||||
// Only call getWindowTitle if windowVisibilityMap has more than one window
|
// Only call getWindowTitle if windowVisibilityMap has more than one window
|
||||||
@ -258,6 +296,12 @@ function updateTrayMenu() {
|
|||||||
icon: getIconPath("recents"),
|
icon: getIconPath("recents"),
|
||||||
submenu: buildRecentNotesMenu()
|
submenu: buildRecentNotesMenu()
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t("tray.recently-closed-windows"),
|
||||||
|
type: "submenu",
|
||||||
|
icon: getIconPath("closed-windows"),
|
||||||
|
submenu: buildClosedWindowsMenu()
|
||||||
|
},
|
||||||
{ type: "separator" },
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: t("tray.close"),
|
label: t("tray.close"),
|
||||||
|
|||||||