Merge remote-tracking branch 'origin/main' into react/collections

This commit is contained in:
Elian Doran
2025-09-03 22:41:44 +03:00
155 changed files with 2125 additions and 6547 deletions

View File

@@ -1,16 +1,11 @@
import utils from "../../services/utils.js";
import contextMenu from "../../menus/context_menu.js";
import contextMenu, { MenuCommandItem } from "../../menus/context_menu.js";
import treeService from "../../services/tree.js";
import ButtonFromNoteWidget from "./button_from_note.js";
import type FNote from "../../entities/fnote.js";
import type { CommandNames } from "../../components/app_context.js";
import type { WebContents } from "electron";
interface ContextMenuItem {
title: string;
idx: string;
uiIcon: string;
}
import link from "../../services/link.js";
export default class HistoryNavigationButton extends ButtonFromNoteWidget {
private webContents?: WebContents;
@@ -47,24 +42,20 @@ export default class HistoryNavigationButton extends ButtonFromNoteWidget {
return;
}
let items: ContextMenuItem[] = [];
let items: MenuCommandItem<string>[] = [];
const history = this.webContents.navigationHistory;
const activeIndex = history.getActiveIndex();
const history = this.webContents.navigationHistory.getAllEntries();
const activeIndex = this.webContents.navigationHistory.getActiveIndex();
for (const idx in history) {
const url = history[idx];
const parts = url.split("#");
if (parts.length < 2) continue;
const notePathWithTab = parts[1];
const notePath = notePathWithTab.split("-")[0];
const { notePath } = link.parseNavigationStateFromUrl(history[idx].url);
if (!notePath) continue;
const title = await treeService.getNotePathTitle(notePath);
items.push({
title,
idx,
command: idx,
uiIcon:
parseInt(idx) === activeIndex
? "bx bx-radio-circle-marked" // compare with type coercion!
@@ -84,9 +75,10 @@ export default class HistoryNavigationButton extends ButtonFromNoteWidget {
x: e.pageX,
y: e.pageY,
items,
selectMenuItemHandler: (item: any) => {
if (item && item.idx && this.webContents) {
this.webContents.goToIndex(item.idx);
selectMenuItemHandler: (item: MenuCommandItem<string>) => {
if (item && item.command && this.webContents) {
const idx = parseInt(item.command, 10);
this.webContents.navigationHistory.goToIndex(idx);
}
}
});

View File

@@ -382,7 +382,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
if (event.shiftKey && !ctrlKey) {
const activeNode = this.getActiveNode();
if (activeNode.getParent() !== node.getParent()) {
if (activeNode?.getParent() !== node.getParent()) {
return true;
}
@@ -729,7 +729,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
shortcutService.bindElShortcut($(this.tree.$container), key, () => {
const node = this.tree.getActiveNode();
return handler(node, {} as JQuery.KeyDownEvent);
return node && handler(node, {} as JQuery.KeyDownEvent);
// return false from the handler will stop default handling.
});
}
@@ -921,8 +921,9 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
nodes.push(node);
}
if (nodes.length === 0) {
nodes.push(this.getActiveNode());
const activeNode = this.getActiveNode();
if (nodes.length === 0 && activeNode) {
nodes.push(activeNode);
}
// hidden subtree is hackily hidden via CSS when hoisted to root
@@ -967,9 +968,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
this.collapseTree();
}
/**
* @returns {FancytreeNode|null}
*/
getActiveNode() {
return this.tree.getActiveNode();
}
@@ -1219,7 +1217,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
}
const activeNode = this.getActiveNode();
const activeNodeFocused = activeNode?.hasFocus();
const activeNodeFocused = !!activeNode?.hasFocus();
const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null;
const refreshCtx: RefreshContext = {
@@ -1531,7 +1529,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
// Automatically expand the hoisted note by default
const node = this.getActiveNode();
if (node.data.noteId === this.noteContext.hoistedNoteId){
if (node?.data.noteId === this.noteContext.hoistedNoteId){
this.setExpanded(node.data.branchId, true);
}
}
@@ -1809,6 +1807,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
buildTouchBarCommand({ TouchBar, buildIcon }: CommandListenerData<"buildTouchBar">) {
const triggerCommand = (command: TreeCommandNames) => {
const node = this.getActiveNode();
if (!node) return;
const notePath = treeService.getNotePath(node);
this.triggerCommand<TreeCommandNames>(command, {
@@ -1825,6 +1824,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
icon: buildIcon("NSImageNameTouchBarAddTemplate"),
click: () => {
const node = this.getActiveNode();
if (!node) return;
const notePath = treeService.getNotePath(node);
noteCreateService.createNote(notePath, {
isProtected: node.data.isProtected

View File

@@ -15,13 +15,15 @@ const TPL = /*html*/`
padding: 10px 10px 10px 0px;
height: 50px;
}
.quick-search button, .quick-search input {
border: 0;
font-size: 100% !important;
}
.quick-search .dropdown-menu {
--quick-search-item-delimiter-color: var(--dropdown-border-color);
max-height: 80vh;
min-width: 400px;
max-width: 720px;
@@ -38,14 +40,14 @@ const TPL = /*html*/`
position: relative;
}
.quick-search .dropdown-item:not(:last-child)::after {
.quick-search .dropdown-item + .dropdown-item::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
top: 0;
width: 100%;
height: 1px;
background: var(--dropdown-border-color);
border-bottom: 1px solid var(--quick-search-item-delimiter-color);
}
.quick-search .dropdown-item:last-child::after {
@@ -92,6 +94,8 @@ const TPL = /*html*/`
background-color: var(--accented-background-color);
color: var(--main-text-color);
font-size: .85em;
overflow: hidden;
text-overflow: ellipsis;
}
/* Search result highlighting */
@@ -106,6 +110,10 @@ const TPL = /*html*/`
margin: 0;
}
.quick-search .bx-loader {
margin-inline-end: 4px;
}
</style>
<div class="input-group-prepend">
@@ -220,7 +228,11 @@ export default class QuickSearchWidget extends BasicWidget {
this.isLoadingMore = false;
this.$dropdownMenu.empty();
this.$dropdownMenu.append(`<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span>${t("quick-search.searching")}</span>`);
this.$dropdownMenu.append(`
<span class="dropdown-item disabled">
<span class="bx bx-loader bx-spin"></span>
${t("quick-search.searching")}
</span>`);
const { searchResultNoteIds, searchResults, error } = await server.get<QuickSearchResponse>(`quick-search/${encodeURIComponent(searchString)}`);

View File

@@ -388,7 +388,7 @@ async function setupFonts() {
if (!glob.isDev) {
path = `${window.location.pathname}/node_modules/@excalidraw/excalidraw/dist/prod`;
} else {
path = (await import("../../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2?url")).default;
path = (await import("../../../../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2?url")).default;
let pathComponents = path.split("/");
path = pathComponents.slice(0, pathComponents.length - 2).join("/");
}

View File

@@ -4,7 +4,7 @@ import { buildExtraCommands, type EditorConfig, PREMIUM_PLUGINS } from "@trilium
import { getHighlightJsNameForMime } from "../../../services/mime_types.js";
import options from "../../../services/options.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/emoji_definitions/en.json?url";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/src/emoji_definitions/en.json?url";
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
import getTemplates from "./snippets.js";
import { t } from "../../../services/i18n.js";

View File

@@ -1,5 +1,6 @@
import utils from "../../../services/utils.js";
import options from "../../../services/options.js";
import IconAlignCenter from "@ckeditor/ckeditor5-icons/theme/icons/align-center.svg?raw";
const TEXT_FORMATTING_GROUP = {
label: "Text formatting",
@@ -77,7 +78,7 @@ export function buildClassicToolbar(multilineToolbar: boolean) {
items: ["imageUpload", "|", "link", "bookmark", "internallink", "includeNote", "|", "specialCharacters", "emoji", "math", "mermaid", "horizontalLine", "pageBreak", "dateTime"]
},
"|",
"alignment",
buildAlignmentToolbar(),
"outdent",
"indent",
"|",
@@ -134,7 +135,7 @@ export function buildFloatingToolbar() {
items: ["link", "bookmark", "internallink", "includeNote", "|", "math", "mermaid", "horizontalLine", "pageBreak", "dateTime"]
},
"|",
"alignment",
buildAlignmentToolbar(),
"outdent",
"indent",
"|",
@@ -147,3 +148,11 @@ export function buildFloatingToolbar() {
]
};
}
function buildAlignmentToolbar() {
return {
label: "Alignment",
icon: IconAlignCenter,
items: ["alignment:left", "alignment:center", "alignment:right", "|", "alignment:justify"]
};
}

View File

@@ -12,7 +12,6 @@ import { buildSelectedBackgroundColor } from "../../components/touch_bar.js";
import { buildConfig, BuildEditorOptions, OPEN_SOURCE_LICENSE_KEY } from "./ckeditor/config.js";
import type FNote from "../../entities/fnote.js";
import { PopupEditor, ClassicEditor, EditorWatchdog, type CKTextEditor, type MentionFeed, type WatchdogConfig, EditorConfig } from "@triliumnext/ckeditor5";
import "@triliumnext/ckeditor5/index.css";
import { updateTemplateCache } from "./ckeditor/snippets.js";
const TPL = /*html*/`