# Generate UI lib
-nx g @nx/angular:lib ui
-
-# Add a component
-nx g @nx/angular:component ui/src/lib/button
-
-
-
-
- View interactive project graph
-
-
nx graph
-
-
-
-
- Run affected commands
-
-
# see what's been affected by changes
-nx affected:graph
-
-# run tests for current changes
-nx affected:test
-
-# run e2e tests for current changes
-nx affected:e2e
-
-
-
-
- Carefully crafted with
-
-
-
-
- `;
- }
-}
-customElements.define('triliumnext-root', AppElement);
diff --git a/apps/client/src-example/assets/.gitkeep b/apps/client/src-example/assets/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/client/src-example/favicon.ico b/apps/client/src-example/favicon.ico
deleted file mode 100644
index 317ebcb233..0000000000
Binary files a/apps/client/src-example/favicon.ico and /dev/null differ
diff --git a/apps/client/src-example/index.html b/apps/client/src-example/index.html
deleted file mode 100644
index e206d48372..0000000000
--- a/apps/client/src-example/index.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- Client
-
-
-
-
-
-
-
-
-
diff --git a/apps/client/src-example/main.ts b/apps/client/src-example/main.ts
deleted file mode 100644
index fdb879ded5..0000000000
--- a/apps/client/src-example/main.ts
+++ /dev/null
@@ -1 +0,0 @@
-import './app/app.element';
diff --git a/apps/client/src-example/styles.css b/apps/client/src-example/styles.css
deleted file mode 100644
index 90d4ee0072..0000000000
--- a/apps/client/src-example/styles.css
+++ /dev/null
@@ -1 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts
index 0cf5058ed6..4430145720 100644
--- a/apps/client/src/components/app_context.ts
+++ b/apps/client/src/components/app_context.ts
@@ -1,5 +1,4 @@
import froca from "../services/froca.js";
-import bundleService from "../services/bundle.js";
import RootCommandExecutor from "./root_command_executor.js";
import Entrypoints, { type SqlExecuteResults } from "./entrypoints.js";
import options from "../services/options.js";
@@ -470,6 +469,7 @@ export class AppContext extends Component {
this.tabManager.loadTabs();
+ const bundleService = (await import("../services/bundle.js")).default;
setTimeout(() => bundleService.executeStartupBundles(), 2000);
}
diff --git a/apps/client/src/components/note_context.ts b/apps/client/src/components/note_context.ts
index 11d32cf0db..3a8a543100 100644
--- a/apps/client/src/components/note_context.ts
+++ b/apps/client/src/components/note_context.ts
@@ -12,6 +12,7 @@ import type FNote from "../entities/fnote.js";
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
import type { CKTextEditor } from "@triliumnext/ckeditor5";
import type CodeMirror from "@triliumnext/codemirror";
+import { closeActiveDialog } from "../services/dialog.js";
export interface SetNoteOpts {
triggerSwitchEvent?: unknown;
@@ -83,7 +84,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
await this.triggerEvent("beforeNoteSwitch", { noteContext: this });
- utils.closeActiveDialog();
+ closeActiveDialog();
this.notePath = resolvedNotePath;
this.viewScope = opts.viewScope;
diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts
index 9e215821dd..fd35c09b8a 100644
--- a/apps/client/src/entities/fnote.ts
+++ b/apps/client/src/entities/fnote.ts
@@ -1,7 +1,6 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import ws from "../services/ws.js";
-import froca from "../services/froca.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
@@ -410,8 +409,8 @@ class FNote {
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
notePath: path,
isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId),
- isArchived: path.some((noteId) => froca.notes[noteId].isArchived),
- isSearch: path.some((noteId) => froca.notes[noteId].type === "search"),
+ isArchived: path.some((noteId) => this.froca.notes[noteId].isArchived),
+ isSearch: path.some((noteId) => this.froca.notes[noteId].type === "search"),
isHidden: path.includes("_hidden")
}));
@@ -982,7 +981,7 @@ class FNote {
continue;
}
- const parentNote = froca.notes[parentNoteId];
+ const parentNote = this.froca.notes[parentNoteId];
if (!parentNote || parentNote.type === "search") {
continue;
diff --git a/apps/client/src/services/bundle.ts b/apps/client/src/services/bundle.ts
index e6eea7ef1c..e7b88a3433 100644
--- a/apps/client/src/services/bundle.ts
+++ b/apps/client/src/services/bundle.ts
@@ -1,6 +1,6 @@
import ScriptContext from "./script_context.js";
import server from "./server.js";
-import toastService from "./toast.js";
+import toastService, { showError } from "./toast.js";
import froca from "./froca.js";
import utils from "./utils.js";
import { t } from "./i18n.js";
@@ -37,7 +37,9 @@ async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $cont
} catch (e: any) {
const note = await froca.getNote(bundle.noteId);
- toastService.showAndLogError(`Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`);
+ const message = `Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`;
+ showError(message);
+ logError(message);
}
}
diff --git a/apps/client/src/services/clipboard.ts b/apps/client/src/services/clipboard.ts
index 952ac2e222..9ca5f9d092 100644
--- a/apps/client/src/services/clipboard.ts
+++ b/apps/client/src/services/clipboard.ts
@@ -4,7 +4,7 @@ import froca from "./froca.js";
import linkService from "./link.js";
import utils from "./utils.js";
import { t } from "./i18n.js";
-import toast from "./toast.js";
+import { throwError } from "./ws.js";
let clipboardBranchIds: string[] = [];
let clipboardMode: string | null = null;
@@ -37,7 +37,7 @@ async function pasteAfter(afterBranchId: string) {
// copy will keep clipboardBranchIds and clipboardMode, so it's possible to paste into multiple places
} else {
- toastService.throwError(`Unrecognized clipboard mode=${clipboardMode}`);
+ throwError(`Unrecognized clipboard mode=${clipboardMode}`);
}
}
@@ -69,7 +69,7 @@ async function pasteInto(parentBranchId: string) {
// copy will keep clipboardBranchIds and clipboardMode, so it's possible to paste into multiple places
} else {
- toastService.throwError(`Unrecognized clipboard mode=${clipboardMode}`);
+ throwError(`Unrecognized clipboard mode=${clipboardMode}`);
}
}
diff --git a/apps/client/src/services/dialog.ts b/apps/client/src/services/dialog.ts
index e2d93250f5..240172f491 100644
--- a/apps/client/src/services/dialog.ts
+++ b/apps/client/src/services/dialog.ts
@@ -1,6 +1,41 @@
+import { Modal } from "bootstrap";
import appContext from "../components/app_context.js";
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js";
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
+import { focusSavedElement, saveFocusedElement } from "./focus.js";
+
+export async function openDialog($dialog: JQuery, closeActDialog = true) {
+ if (closeActDialog) {
+ closeActiveDialog();
+ glob.activeDialog = $dialog;
+ }
+
+ saveFocusedElement();
+ Modal.getOrCreateInstance($dialog[0]).show();
+
+ $dialog.on("hidden.bs.modal", () => {
+ const $autocompleteEl = $(".aa-input");
+ if ("autocomplete" in $autocompleteEl) {
+ $autocompleteEl.autocomplete("close");
+ }
+
+ if (!glob.activeDialog || glob.activeDialog === $dialog) {
+ focusSavedElement();
+ }
+ });
+
+ const keyboardActionsService = (await import("./keyboard_actions.js")).default;
+ keyboardActionsService.updateDisplayedShortcuts($dialog);
+
+ return $dialog;
+}
+
+export function closeActiveDialog() {
+ if (glob.activeDialog) {
+ Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
+ glob.activeDialog = null;
+ }
+}
async function info(message: string) {
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));
diff --git a/apps/client/src/services/focus.ts b/apps/client/src/services/focus.ts
new file mode 100644
index 0000000000..066c745581
--- /dev/null
+++ b/apps/client/src/services/focus.ts
@@ -0,0 +1,29 @@
+let $lastFocusedElement: JQuery | null;
+
+// perhaps there should be saved focused element per tab?
+export function saveFocusedElement() {
+ $lastFocusedElement = $(":focus");
+}
+
+export function focusSavedElement() {
+ if (!$lastFocusedElement) {
+ return;
+ }
+
+ if ($lastFocusedElement.hasClass("ck")) {
+ // must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
+ // the bug manifests itself in resetting the cursor position to the first character - jumping above
+
+ const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
+
+ if (editor) {
+ editor.editing.view.focus();
+ } else {
+ console.log("Could not find CKEditor instance to focus last element");
+ }
+ } else {
+ $lastFocusedElement.focus();
+ }
+
+ $lastFocusedElement = null;
+}
diff --git a/apps/client/src/services/i18n.spec.ts b/apps/client/src/services/i18n.spec.ts
index 9143097bed..e64605949a 100644
--- a/apps/client/src/services/i18n.spec.ts
+++ b/apps/client/src/services/i18n.spec.ts
@@ -1,6 +1,7 @@
import { LOCALES } from "@triliumnext/commons";
import { readFileSync } from "fs";
import { join } from "path";
+import { describe, expect, it } from "vitest";
describe("i18n", () => {
it("translations are valid JSON", () => {
diff --git a/apps/client/src/services/image.ts b/apps/client/src/services/image.ts
index 3cf1424d50..f13a9a3c71 100644
--- a/apps/client/src/services/image.ts
+++ b/apps/client/src/services/image.ts
@@ -1,5 +1,5 @@
import { t } from "./i18n.js";
-import toastService from "./toast.js";
+import toastService, { showError } from "./toast.js";
function copyImageReferenceToClipboard($imageWrapper: JQuery) {
try {
@@ -11,7 +11,9 @@ function copyImageReferenceToClipboard($imageWrapper: JQuery) {
if (success) {
toastService.showMessage(t("image.copied-to-clipboard"));
} else {
- toastService.showAndLogError(t("image.cannot-copy"));
+ const message = t("image.cannot-copy");
+ showError(message);
+ logError(message);
}
} finally {
window.getSelection()?.removeAllRanges();
diff --git a/apps/client/src/services/script_context.ts b/apps/client/src/services/script_context.ts
index 27a8a7d441..7c15db1aef 100644
--- a/apps/client/src/services/script_context.ts
+++ b/apps/client/src/services/script_context.ts
@@ -1,4 +1,4 @@
-import FrontendScriptApi, { type Entity } from "./frontend_script_api.js";
+import type { Entity } from "./frontend_script_api.js";
import utils from "./utils.js";
import froca from "./froca.js";
@@ -14,6 +14,8 @@ async function ScriptContext(startNoteId: string, allNoteIds: string[], originEn
throw new Error(`Could not find start note ${startNoteId}.`);
}
+ const FrontendScriptApi = (await import("./frontend_script_api.js")).default;
+
return {
modules: modules,
notes: utils.toObject(allNotes, (note) => [note.noteId, note]),
diff --git a/apps/client/src/services/server.ts b/apps/client/src/services/server.ts
index f577fbfb42..861a20e602 100644
--- a/apps/client/src/services/server.ts
+++ b/apps/client/src/services/server.ts
@@ -1,5 +1,6 @@
import utils, { isShare } from "./utils.js";
import ValidationError from "./validation_error.js";
+import { throwError } from "./ws.js";
type Headers = Record;
@@ -276,7 +277,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
} else {
const title = `${statusCode} ${method} ${url}`;
toastService.showErrorTitleAndMessage(title, messageStr);
- toastService.throwError(`${title} - ${message}`);
+ throwError(`${title} - ${message}`);
}
}
diff --git a/apps/client/src/services/toast.ts b/apps/client/src/services/toast.ts
index 18cc876a9b..66b3f7f50b 100644
--- a/apps/client/src/services/toast.ts
+++ b/apps/client/src/services/toast.ts
@@ -78,13 +78,7 @@ function showMessage(message: string, delay = 2000) {
});
}
-function showAndLogError(message: string, delay = 10000) {
- showError(message, delay);
-
- ws.logError(message);
-}
-
-function showError(message: string, delay = 10000) {
+export function showError(message: string, delay = 10000) {
console.log(utils.now(), "error: ", message);
toast({
@@ -108,18 +102,10 @@ function showErrorTitleAndMessage(title: string, message: string, delay = 10000)
});
}
-function throwError(message: string) {
- ws.logError(message);
-
- throw new Error(message);
-}
-
export default {
showMessage,
showError,
showErrorTitleAndMessage,
- showAndLogError,
- throwError,
showPersistent,
closePersistent
};
diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts
index 4126506052..c7d37e4d9a 100644
--- a/apps/client/src/services/utils.ts
+++ b/apps/client/src/services/utils.ts
@@ -1,5 +1,4 @@
import dayjs from "dayjs";
-import { Modal } from "bootstrap";
import type { ViewScope } from "./link.js";
const SVG_MIME = "image/svg+xml";
@@ -275,69 +274,6 @@ function getMimeTypeClass(mime: string) {
return `mime-${mime.toLowerCase().replace(/[\W_]+/g, "-")}`;
}
-function closeActiveDialog() {
- if (glob.activeDialog) {
- Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
- glob.activeDialog = null;
- }
-}
-
-let $lastFocusedElement: JQuery | null;
-
-// perhaps there should be saved focused element per tab?
-function saveFocusedElement() {
- $lastFocusedElement = $(":focus");
-}
-
-function focusSavedElement() {
- if (!$lastFocusedElement) {
- return;
- }
-
- if ($lastFocusedElement.hasClass("ck")) {
- // must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
- // the bug manifests itself in resetting the cursor position to the first character - jumping above
-
- const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
-
- if (editor) {
- editor.editing.view.focus();
- } else {
- console.log("Could not find CKEditor instance to focus last element");
- }
- } else {
- $lastFocusedElement.focus();
- }
-
- $lastFocusedElement = null;
-}
-
-async function openDialog($dialog: JQuery, closeActDialog = true) {
- if (closeActDialog) {
- closeActiveDialog();
- glob.activeDialog = $dialog;
- }
-
- saveFocusedElement();
- Modal.getOrCreateInstance($dialog[0]).show();
-
- $dialog.on("hidden.bs.modal", () => {
- const $autocompleteEl = $(".aa-input");
- if ("autocomplete" in $autocompleteEl) {
- $autocompleteEl.autocomplete("close");
- }
-
- if (!glob.activeDialog || glob.activeDialog === $dialog) {
- focusSavedElement();
- }
- });
-
- const keyboardActionsService = (await import("./keyboard_actions.js")).default;
- keyboardActionsService.updateDisplayedShortcuts($dialog);
-
- return $dialog;
-}
-
function isHtmlEmpty(html: string) {
if (!html) {
return true;
@@ -823,10 +759,6 @@ export default {
setCookie,
getNoteTypeClass,
getMimeTypeClass,
- closeActiveDialog,
- openDialog,
- saveFocusedElement,
- focusSavedElement,
isHtmlEmpty,
clearBrowserCache,
copySelectionToClipboard,
diff --git a/apps/client/src/services/ws.ts b/apps/client/src/services/ws.ts
index ccfd19592d..dcd63e5772 100644
--- a/apps/client/src/services/ws.ts
+++ b/apps/client/src/services/ws.ts
@@ -17,7 +17,7 @@ let lastProcessedEntityChangeId = window.glob.maxEntityChangeIdAtLoad;
let lastPingTs: number;
let frontendUpdateDataQueue: EntityChange[] = [];
-function logError(message: string) {
+export function logError(message: string) {
console.error(utils.now(), message); // needs to be separate from .trace()
if (ws && ws.readyState === 1) {
@@ -301,6 +301,12 @@ setTimeout(() => {
setInterval(sendPing, 1000);
}, 0);
+export function throwError(message: string) {
+ logError(message);
+
+ throw new Error(message);
+}
+
export default {
logError,
subscribeToMessages,
diff --git a/apps/client/src/widgets/attribute_widgets/attribute_detail.ts b/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
index 08bb764fc1..9017673f32 100644
--- a/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
+++ b/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
@@ -11,6 +11,7 @@ import utils from "../../services/utils.js";
import shortcutService from "../../services/shortcuts.js";
import appContext from "../../components/app_context.js";
import type { Attribute } from "../../services/attribute_parser.js";
+import { focusSavedElement, saveFocusedElement } from "../../services/focus.js";
const TPL = /*html*/`
@@ -483,7 +484,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
return;
}
- utils.saveFocusedElement();
+ saveFocusedElement();
this.attrType = this.getAttrType(attribute);
@@ -605,7 +606,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.hide();
- utils.focusSavedElement();
+ focusSavedElement();
}
async cancelAndClose() {
@@ -613,7 +614,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.hide();
- utils.focusSavedElement();
+ focusSavedElement();
}
userEditedAttribute() {
diff --git a/apps/client/src/widgets/dialogs/about.ts b/apps/client/src/widgets/dialogs/about.ts
index 2c364d7568..06cf118ecd 100644
--- a/apps/client/src/widgets/dialogs/about.ts
+++ b/apps/client/src/widgets/dialogs/about.ts
@@ -4,6 +4,7 @@ import BasicWidget from "../basic_widget.js";
import openService from "../../services/open.js";
import server from "../../services/server.js";
import utils from "../../services/utils.js";
+import { openDialog } from "../../services/dialog.js";
interface AppInfo {
appVersion: string;
@@ -111,6 +112,6 @@ export default class AboutDialog extends BasicWidget {
async openAboutDialogEvent() {
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/add_link.ts b/apps/client/src/widgets/dialogs/add_link.ts
index fe22954425..d7758c92d7 100644
--- a/apps/client/src/widgets/dialogs/add_link.ts
+++ b/apps/client/src/widgets/dialogs/add_link.ts
@@ -1,11 +1,11 @@
import { t } from "../../services/i18n.js";
import treeService from "../../services/tree.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import type { Suggestion } from "../../services/note_autocomplete.js";
import type { default as TextTypeWidget } from "../type_widgets/editable_text.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -111,7 +111,7 @@ export default class AddLinkDialog extends BasicWidget {
this.updateTitleSettingsVisibility();
- await utils.openDialog(this.$widget);
+ await openDialog(this.$widget);
this.$autoComplete.val("");
this.$linkTitle.val("");
diff --git a/apps/client/src/widgets/dialogs/branch_prefix.ts b/apps/client/src/widgets/dialogs/branch_prefix.ts
index 345d305570..496700a0c8 100644
--- a/apps/client/src/widgets/dialogs/branch_prefix.ts
+++ b/apps/client/src/widgets/dialogs/branch_prefix.ts
@@ -2,11 +2,11 @@ import treeService from "../../services/tree.js";
import server from "../../services/server.js";
import froca from "../../services/froca.js";
import toastService from "../../services/toast.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import appContext from "../../components/app_context.js";
import { t } from "../../services/i18n.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -93,7 +93,7 @@ export default class BranchPrefixDialog extends BasicWidget {
}
await this.refresh(notePath);
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
async savePrefix() {
diff --git a/apps/client/src/widgets/dialogs/bulk_actions.ts b/apps/client/src/widgets/dialogs/bulk_actions.ts
index a8680500d6..544a5d03ea 100644
--- a/apps/client/src/widgets/dialogs/bulk_actions.ts
+++ b/apps/client/src/widgets/dialogs/bulk_actions.ts
@@ -1,11 +1,11 @@
import BasicWidget from "../basic_widget.js";
import froca from "../../services/froca.js";
import bulkActionService from "../../services/bulk_action.js";
-import utils from "../../services/utils.js";
import server from "../../services/server.js";
import toastService from "../../services/toast.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { closeActiveDialog, openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -104,7 +104,7 @@ export default class BulkActionsDialog extends BasicWidget {
});
toastService.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
- utils.closeActiveDialog();
+ closeActiveDialog();
});
}
@@ -170,6 +170,6 @@ export default class BulkActionsDialog extends BasicWidget {
this.$includeDescendants.prop("checked", false);
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/clone_to.ts b/apps/client/src/widgets/dialogs/clone_to.ts
index 08ee3108b1..7c3a530719 100644
--- a/apps/client/src/widgets/dialogs/clone_to.ts
+++ b/apps/client/src/widgets/dialogs/clone_to.ts
@@ -1,5 +1,4 @@
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import treeService from "../../services/tree.js";
import toastService from "../../services/toast.js";
import froca from "../../services/froca.js";
@@ -8,6 +7,7 @@ import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -94,7 +94,7 @@ export default class CloneToDialog extends BasicWidget {
}
}
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$noteAutoComplete.val("").trigger("focus");
this.$noteList.empty();
diff --git a/apps/client/src/widgets/dialogs/delete_notes.ts b/apps/client/src/widgets/dialogs/delete_notes.ts
index 52a0d99416..b9f7f89cd4 100644
--- a/apps/client/src/widgets/dialogs/delete_notes.ts
+++ b/apps/client/src/widgets/dialogs/delete_notes.ts
@@ -1,10 +1,10 @@
import server from "../../services/server.js";
import froca from "../../services/froca.js";
import linkService from "../../services/link.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { FAttributeRow } from "../../entities/fattribute.js";
+import { closeActiveDialog, openDialog } from "../../services/dialog.js";
// TODO: Use common with server.
interface Response {
@@ -119,13 +119,13 @@ export default class DeleteNotesDialog extends BasicWidget {
this.$widget.on("shown.bs.modal", () => this.$okButton.trigger("focus"));
this.$cancelButton.on("click", () => {
- utils.closeActiveDialog();
+ closeActiveDialog();
this.resolve({ proceed: false });
});
this.$okButton.on("click", () => {
- utils.closeActiveDialog();
+ closeActiveDialog();
this.resolve({
proceed: true,
@@ -179,7 +179,7 @@ export default class DeleteNotesDialog extends BasicWidget {
await this.renderDeletePreview();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$deleteAllClones.prop("checked", !!forceDeleteAllClones).prop("disabled", !!forceDeleteAllClones);
diff --git a/apps/client/src/widgets/dialogs/export.ts b/apps/client/src/widgets/dialogs/export.ts
index d8fcd670db..d9b13f4edc 100644
--- a/apps/client/src/widgets/dialogs/export.ts
+++ b/apps/client/src/widgets/dialogs/export.ts
@@ -8,6 +8,7 @@ import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -214,7 +215,7 @@ export default class ExportDialog extends BasicWidget {
this.$widget.find(".opml-v2").prop("checked", true); // setting default
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
diff --git a/apps/client/src/widgets/dialogs/help.ts b/apps/client/src/widgets/dialogs/help.ts
index 747d01b021..ad8961d0c8 100644
--- a/apps/client/src/widgets/dialogs/help.ts
+++ b/apps/client/src/widgets/dialogs/help.ts
@@ -1,6 +1,6 @@
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -155,6 +155,6 @@ export default class HelpDialog extends BasicWidget {
}
showCheatsheetEvent() {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/import.ts b/apps/client/src/widgets/dialogs/import.ts
index f1ac2663d8..c8cd66a273 100644
--- a/apps/client/src/widgets/dialogs/import.ts
+++ b/apps/client/src/widgets/dialogs/import.ts
@@ -1,4 +1,4 @@
-import utils, { escapeQuotes } from "../../services/utils.js";
+import { escapeQuotes } from "../../services/utils.js";
import treeService from "../../services/tree.js";
import importService, { type UploadFilesOptions } from "../../services/import.js";
import options from "../../services/options.js";
@@ -6,6 +6,7 @@ import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import { Modal, Tooltip } from "bootstrap";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -155,7 +156,7 @@ export default class ImportDialog extends BasicWidget {
this.$noteTitle.text(await treeService.getNoteTitle(this.parentNoteId));
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
async importIntoNote(parentNoteId: string) {
diff --git a/apps/client/src/widgets/dialogs/include_note.ts b/apps/client/src/widgets/dialogs/include_note.ts
index 06375aa486..61b22a35be 100644
--- a/apps/client/src/widgets/dialogs/include_note.ts
+++ b/apps/client/src/widgets/dialogs/include_note.ts
@@ -1,12 +1,12 @@
import { t } from "../../services/i18n.js";
import treeService from "../../services/tree.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import froca from "../../services/froca.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
import type { EventData } from "../../components/app_context.js";
import type EditableTextTypeWidget from "../type_widgets/editable_text.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -83,7 +83,7 @@ export default class IncludeNoteDialog extends BasicWidget {
async showIncludeNoteDialogEvent({ textTypeWidget }: EventData<"showIncludeDialog">) {
this.textTypeWidget = textTypeWidget;
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$autoComplete.trigger("focus").trigger("select"); // to be able to quickly remove entered text
}
diff --git a/apps/client/src/widgets/dialogs/info.ts b/apps/client/src/widgets/dialogs/info.ts
index 508599912d..34015dc7d8 100644
--- a/apps/client/src/widgets/dialogs/info.ts
+++ b/apps/client/src/widgets/dialogs/info.ts
@@ -1,9 +1,9 @@
import type { EventData } from "../../components/app_context.js";
import { t } from "../../services/i18n.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
import type { ConfirmDialogCallback } from "./confirm.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -72,7 +72,7 @@ export default class InfoDialog extends BasicWidget {
}
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.resolve = callback;
}
diff --git a/apps/client/src/widgets/dialogs/jump_to_note.ts b/apps/client/src/widgets/dialogs/jump_to_note.ts
index 54428b3b67..98ee6e0e44 100644
--- a/apps/client/src/widgets/dialogs/jump_to_note.ts
+++ b/apps/client/src/widgets/dialogs/jump_to_note.ts
@@ -5,6 +5,7 @@ import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -54,7 +55,7 @@ export default class JumpToNoteDialog extends BasicWidget {
}
async jumpToNoteEvent() {
- const dialogPromise = utils.openDialog(this.$widget);
+ const dialogPromise = openDialog(this.$widget);
if (utils.isMobile()) {
dialogPromise.then(($dialog) => {
const el = $dialog.find(">.modal-dialog")[0];
diff --git a/apps/client/src/widgets/dialogs/markdown_import.ts b/apps/client/src/widgets/dialogs/markdown_import.ts
index 2f7c2bdf4b..40af0c84a6 100644
--- a/apps/client/src/widgets/dialogs/markdown_import.ts
+++ b/apps/client/src/widgets/dialogs/markdown_import.ts
@@ -6,6 +6,7 @@ import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
import server from "../../services/server.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -89,7 +90,7 @@ export default class MarkdownImportDialog extends BasicWidget {
this.convertMarkdownToHtml(text);
} else {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/move_to.ts b/apps/client/src/widgets/dialogs/move_to.ts
index 91ffcfd71e..49e016f155 100644
--- a/apps/client/src/widgets/dialogs/move_to.ts
+++ b/apps/client/src/widgets/dialogs/move_to.ts
@@ -1,5 +1,4 @@
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import toastService from "../../services/toast.js";
import froca from "../../services/froca.js";
import branchService from "../../services/branches.js";
@@ -7,6 +6,7 @@ import treeService from "../../services/tree.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -83,7 +83,7 @@ export default class MoveToDialog extends BasicWidget {
async moveBranchIdsToEvent({ branchIds }: EventData<"moveBranchIdsTo">) {
this.movedBranchIds = branchIds;
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$noteAutoComplete.val("").trigger("focus");
diff --git a/apps/client/src/widgets/dialogs/password_not_set.ts b/apps/client/src/widgets/dialogs/password_not_set.ts
index 03a944ab07..bc667f14f9 100644
--- a/apps/client/src/widgets/dialogs/password_not_set.ts
+++ b/apps/client/src/widgets/dialogs/password_not_set.ts
@@ -1,5 +1,5 @@
+import { openDialog } from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
@@ -37,6 +37,6 @@ export default class PasswordNoteSetDialog extends BasicWidget {
}
showPasswordNotSetEvent() {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/prompt.ts b/apps/client/src/widgets/dialogs/prompt.ts
index e33667a1de..f780fc4f5c 100644
--- a/apps/client/src/widgets/dialogs/prompt.ts
+++ b/apps/client/src/widgets/dialogs/prompt.ts
@@ -1,5 +1,5 @@
+import { openDialog } from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
@@ -110,6 +110,6 @@ export default class PromptDialog extends BasicWidget {
this.$dialogBody.empty().append($("
").addClass("form-group").append(this.$question).append(this.$answer));
- utils.openDialog(this.$widget, false);
+ openDialog(this.$widget, false);
}
}
diff --git a/apps/client/src/widgets/dialogs/protected_session_password.ts b/apps/client/src/widgets/dialogs/protected_session_password.ts
index d839aac3b8..75f15684f2 100644
--- a/apps/client/src/widgets/dialogs/protected_session_password.ts
+++ b/apps/client/src/widgets/dialogs/protected_session_password.ts
@@ -1,6 +1,6 @@
+import { openDialog } from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
import protectedSessionService from "../../services/protected_session.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
@@ -49,7 +49,7 @@ export default class ProtectedSessionPasswordDialog extends BasicWidget {
}
showProtectedSessionPasswordDialogEvent() {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$passwordInput.trigger("focus");
}
diff --git a/apps/client/src/widgets/dialogs/recent_changes.ts b/apps/client/src/widgets/dialogs/recent_changes.ts
index 59949d0598..280d716d03 100644
--- a/apps/client/src/widgets/dialogs/recent_changes.ts
+++ b/apps/client/src/widgets/dialogs/recent_changes.ts
@@ -2,13 +2,12 @@ import { formatDateTime } from "../../utils/formatters.js";
import { t } from "../../services/i18n.js";
import appContext, { type EventData } from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
-import dialogService from "../../services/dialog.js";
+import dialogService, { openDialog } from "../../services/dialog.js";
import froca from "../../services/froca.js";
import hoistedNoteService from "../../services/hoisted_note.js";
import linkService from "../../services/link.js";
import server from "../../services/server.js";
import toastService from "../../services/toast.js";
-import utils from "../../services/utils.js";
import ws from "../../services/ws.js";
import { Modal } from "bootstrap";
@@ -62,7 +61,7 @@ export default class RecentChangesDialog extends BasicWidget {
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
async refresh() {
diff --git a/apps/client/src/widgets/dialogs/revisions.ts b/apps/client/src/widgets/dialogs/revisions.ts
index 8083dd9358..39885d3286 100644
--- a/apps/client/src/widgets/dialogs/revisions.ts
+++ b/apps/client/src/widgets/dialogs/revisions.ts
@@ -6,7 +6,7 @@ import appContext from "../../components/app_context.js";
import openService from "../../services/open.js";
import protectedSessionHolder from "../../services/protected_session_holder.js";
import BasicWidget from "../basic_widget.js";
-import dialogService from "../../services/dialog.js";
+import dialogService, { openDialog } from "../../services/dialog.js";
import options from "../../services/options.js";
import type FNote from "../../entities/fnote.js";
import type { NoteType } from "../../entities/fnote.js";
@@ -182,7 +182,7 @@ export default class RevisionsDialog extends BasicWidget {
return;
}
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
await this.loadRevisions(noteId);
}
diff --git a/apps/client/src/widgets/dialogs/sort_child_notes.ts b/apps/client/src/widgets/dialogs/sort_child_notes.ts
index d2bad6b87f..7560476c56 100644
--- a/apps/client/src/widgets/dialogs/sort_child_notes.ts
+++ b/apps/client/src/widgets/dialogs/sort_child_notes.ts
@@ -1,7 +1,7 @@
import type { EventData } from "../../components/app_context.js";
+import { closeActiveDialog, openDialog } from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
import server from "../../services/server.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
const TPL = /*html*/`
@@ -97,14 +97,14 @@ export default class SortChildNotesDialog extends BasicWidget {
await server.put(`notes/${this.parentNoteId}/sort-children`, { sortBy, sortDirection, foldersFirst, sortNatural, sortLocale });
- utils.closeActiveDialog();
+ closeActiveDialog();
});
}
async sortChildNotesEvent({ node }: EventData<"sortChildNotes">) {
this.parentNoteId = node.data.noteId;
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$form.find("input:first").focus();
}
diff --git a/apps/client/src/widgets/dialogs/upload_attachments.ts b/apps/client/src/widgets/dialogs/upload_attachments.ts
index b85b12b9c2..9b056db3e3 100644
--- a/apps/client/src/widgets/dialogs/upload_attachments.ts
+++ b/apps/client/src/widgets/dialogs/upload_attachments.ts
@@ -1,11 +1,12 @@
import { t } from "../../services/i18n.js";
-import utils, { escapeQuotes } from "../../services/utils.js";
+import { escapeQuotes } from "../../services/utils.js";
import treeService from "../../services/tree.js";
import importService from "../../services/import.js";
import options from "../../services/options.js";
import BasicWidget from "../basic_widget.js";
import { Modal, Tooltip } from "bootstrap";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`