Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit cca8504

Browse files
committed
refactor(client): circular dep in utils
1 parent 09391a9 commit cca8504

26 files changed

+118
-115
lines changed

apps/client/src/components/note_context.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type FNote from "../entities/fnote.js";
1212
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
1313
import type { CKTextEditor } from "@triliumnext/ckeditor5";
1414
import type CodeMirror from "@triliumnext/codemirror";
15+
import { closeActiveDialog } from "../services/dialog.js";
1516

1617
export interface SetNoteOpts {
1718
triggerSwitchEvent?: unknown;
@@ -83,7 +84,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
8384

8485
await this.triggerEvent("beforeNoteSwitch", { noteContext: this });
8586

86-
utils.closeActiveDialog();
87+
closeActiveDialog();
8788

8889
this.notePath = resolvedNotePath;
8990
this.viewScope = opts.viewScope;

apps/client/src/services/dialog.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,41 @@
1+
import { Modal } from "bootstrap";
12
import appContext from "../components/app_context.js";
23
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js";
34
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
5+
import { focusSavedElement, saveFocusedElement } from "./focus.js";
6+
7+
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true) {
8+
if (closeActDialog) {
9+
closeActiveDialog();
10+
glob.activeDialog = $dialog;
11+
}
12+
13+
saveFocusedElement();
14+
Modal.getOrCreateInstance($dialog[0]).show();
15+
16+
$dialog.on("hidden.bs.modal", () => {
17+
const $autocompleteEl = $(".aa-input");
18+
if ("autocomplete" in $autocompleteEl) {
19+
$autocompleteEl.autocomplete("close");
20+
}
21+
22+
if (!glob.activeDialog || glob.activeDialog === $dialog) {
23+
focusSavedElement();
24+
}
25+
});
26+
27+
const keyboardActionsService = (await import("./keyboard_actions.js")).default;
28+
keyboardActionsService.updateDisplayedShortcuts($dialog);
29+
30+
return $dialog;
31+
}
32+
33+
export function closeActiveDialog() {
34+
if (glob.activeDialog) {
35+
Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
36+
glob.activeDialog = null;
37+
}
38+
}
439

540
async function info(message: string) {
641
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));

apps/client/src/services/focus.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
let $lastFocusedElement: JQuery<HTMLElement> | null;
2+
3+
// perhaps there should be saved focused element per tab?
4+
export function saveFocusedElement() {
5+
$lastFocusedElement = $(":focus");
6+
}
7+
8+
export function focusSavedElement() {
9+
if (!$lastFocusedElement) {
10+
return;
11+
}
12+
13+
if ($lastFocusedElement.hasClass("ck")) {
14+
// must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
15+
// the bug manifests itself in resetting the cursor position to the first character - jumping above
16+
17+
const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
18+
19+
if (editor) {
20+
editor.editing.view.focus();
21+
} else {
22+
console.log("Could not find CKEditor instance to focus last element");
23+
}
24+
} else {
25+
$lastFocusedElement.focus();
26+
}
27+
28+
$lastFocusedElement = null;
29+
}

apps/client/src/services/utils.ts

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import dayjs from "dayjs";
2-
import { Modal } from "bootstrap";
32
import type { ViewScope } from "./link.js";
43

54
const SVG_MIME = "image/svg+xml";
@@ -275,69 +274,6 @@ function getMimeTypeClass(mime: string) {
275274
return `mime-${mime.toLowerCase().replace(/[\W_]+/g, "-")}`;
276275
}
277276

278-
function closeActiveDialog() {
279-
if (glob.activeDialog) {
280-
Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
281-
glob.activeDialog = null;
282-
}
283-
}
284-
285-
let $lastFocusedElement: JQuery<HTMLElement> | null;
286-
287-
// perhaps there should be saved focused element per tab?
288-
function saveFocusedElement() {
289-
$lastFocusedElement = $(":focus");
290-
}
291-
292-
function focusSavedElement() {
293-
if (!$lastFocusedElement) {
294-
return;
295-
}
296-
297-
if ($lastFocusedElement.hasClass("ck")) {
298-
// must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
299-
// the bug manifests itself in resetting the cursor position to the first character - jumping above
300-
301-
const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
302-
303-
if (editor) {
304-
editor.editing.view.focus();
305-
} else {
306-
console.log("Could not find CKEditor instance to focus last element");
307-
}
308-
} else {
309-
$lastFocusedElement.focus();
310-
}
311-
312-
$lastFocusedElement = null;
313-
}
314-
315-
async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true) {
316-
if (closeActDialog) {
317-
closeActiveDialog();
318-
glob.activeDialog = $dialog;
319-
}
320-
321-
saveFocusedElement();
322-
Modal.getOrCreateInstance($dialog[0]).show();
323-
324-
$dialog.on("hidden.bs.modal", () => {
325-
const $autocompleteEl = $(".aa-input");
326-
if ("autocomplete" in $autocompleteEl) {
327-
$autocompleteEl.autocomplete("close");
328-
}
329-
330-
if (!glob.activeDialog || glob.activeDialog === $dialog) {
331-
focusSavedElement();
332-
}
333-
});
334-
335-
const keyboardActionsService = (await import("./keyboard_actions.js")).default;
336-
keyboardActionsService.updateDisplayedShortcuts($dialog);
337-
338-
return $dialog;
339-
}
340-
341277
function isHtmlEmpty(html: string) {
342278
if (!html) {
343279
return true;
@@ -823,10 +759,6 @@ export default {
823759
setCookie,
824760
getNoteTypeClass,
825761
getMimeTypeClass,
826-
closeActiveDialog,
827-
openDialog,
828-
saveFocusedElement,
829-
focusSavedElement,
830762
isHtmlEmpty,
831763
clearBrowserCache,
832764
copySelectionToClipboard,

apps/client/src/widgets/attribute_widgets/attribute_detail.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import utils from "../../services/utils.js";
1111
import shortcutService from "../../services/shortcuts.js";
1212
import appContext from "../../components/app_context.js";
1313
import type { Attribute } from "../../services/attribute_parser.js";
14+
import { focusSavedElement, saveFocusedElement } from "../../services/focus.js";
1415

1516
const TPL = /*html*/`
1617
<div class="attr-detail tn-tool-dialog">
@@ -483,7 +484,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
483484
return;
484485
}
485486

486-
utils.saveFocusedElement();
487+
saveFocusedElement();
487488

488489
this.attrType = this.getAttrType(attribute);
489490

@@ -605,15 +606,15 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
605606

606607
this.hide();
607608

608-
utils.focusSavedElement();
609+
focusSavedElement();
609610
}
610611

611612
async cancelAndClose() {
612613
await this.triggerCommand("reloadAttributes");
613614

614615
this.hide();
615616

616-
utils.focusSavedElement();
617+
focusSavedElement();
617618
}
618619

619620
userEditedAttribute() {

apps/client/src/widgets/dialogs/about.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import BasicWidget from "../basic_widget.js";
44
import openService from "../../services/open.js";
55
import server from "../../services/server.js";
66
import utils from "../../services/utils.js";
7+
import { openDialog } from "../../services/dialog.js";
78

89
interface AppInfo {
910
appVersion: string;
@@ -111,6 +112,6 @@ export default class AboutDialog extends BasicWidget {
111112

112113
async openAboutDialogEvent() {
113114
await this.refresh();
114-
utils.openDialog(this.$widget);
115+
openDialog(this.$widget);
115116
}
116117
}

apps/client/src/widgets/dialogs/add_link.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { t } from "../../services/i18n.js";
22
import treeService from "../../services/tree.js";
33
import noteAutocompleteService from "../../services/note_autocomplete.js";
4-
import utils from "../../services/utils.js";
54
import BasicWidget from "../basic_widget.js";
65
import type { Suggestion } from "../../services/note_autocomplete.js";
76
import type { default as TextTypeWidget } from "../type_widgets/editable_text.js";
87
import type { EventData } from "../../components/app_context.js";
8+
import { openDialog } from "../../services/dialog.js";
99

1010
const TPL = /*html*/`
1111
<div class="add-link-dialog modal mx-auto" tabindex="-1" role="dialog">
@@ -111,7 +111,7 @@ export default class AddLinkDialog extends BasicWidget {
111111

112112
this.updateTitleSettingsVisibility();
113113

114-
await utils.openDialog(this.$widget);
114+
await openDialog(this.$widget);
115115

116116
this.$autoComplete.val("");
117117
this.$linkTitle.val("");

apps/client/src/widgets/dialogs/branch_prefix.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import treeService from "../../services/tree.js";
22
import server from "../../services/server.js";
33
import froca from "../../services/froca.js";
44
import toastService from "../../services/toast.js";
5-
import utils from "../../services/utils.js";
65
import BasicWidget from "../basic_widget.js";
76
import appContext from "../../components/app_context.js";
87
import { t } from "../../services/i18n.js";
98
import { Modal } from "bootstrap";
9+
import { openDialog } from "../../services/dialog.js";
1010

1111
const TPL = /*html*/`<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1" role="dialog">
1212
<div class="modal-dialog modal-lg" role="document">
@@ -93,7 +93,7 @@ export default class BranchPrefixDialog extends BasicWidget {
9393
}
9494

9595
await this.refresh(notePath);
96-
utils.openDialog(this.$widget);
96+
openDialog(this.$widget);
9797
}
9898

9999
async savePrefix() {

apps/client/src/widgets/dialogs/bulk_actions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import BasicWidget from "../basic_widget.js";
22
import froca from "../../services/froca.js";
33
import bulkActionService from "../../services/bulk_action.js";
4-
import utils from "../../services/utils.js";
54
import server from "../../services/server.js";
65
import toastService from "../../services/toast.js";
76
import { t } from "../../services/i18n.js";
87
import type { EventData } from "../../components/app_context.js";
8+
import { closeActiveDialog, openDialog } from "../../services/dialog.js";
99

1010

1111
const TPL = /*html*/`
@@ -104,7 +104,7 @@ export default class BulkActionsDialog extends BasicWidget {
104104
});
105105

106106
toastService.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
107-
utils.closeActiveDialog();
107+
closeActiveDialog();
108108
});
109109
}
110110

@@ -170,6 +170,6 @@ export default class BulkActionsDialog extends BasicWidget {
170170
this.$includeDescendants.prop("checked", false);
171171

172172
await this.refresh();
173-
utils.openDialog(this.$widget);
173+
openDialog(this.$widget);
174174
}
175175
}

apps/client/src/widgets/dialogs/clone_to.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import noteAutocompleteService from "../../services/note_autocomplete.js";
2-
import utils from "../../services/utils.js";
32
import treeService from "../../services/tree.js";
43
import toastService from "../../services/toast.js";
54
import froca from "../../services/froca.js";
@@ -8,6 +7,7 @@ import appContext from "../../components/app_context.js";
87
import BasicWidget from "../basic_widget.js";
98
import { t } from "../../services/i18n.js";
109
import type { EventData } from "../../components/app_context.js";
10+
import { openDialog } from "../../services/dialog.js";
1111

1212

1313
const TPL = /*html*/`
@@ -94,7 +94,7 @@ export default class CloneToDialog extends BasicWidget {
9494
}
9595
}
9696

97-
utils.openDialog(this.$widget);
97+
openDialog(this.$widget);
9898
this.$noteAutoComplete.val("").trigger("focus");
9999
this.$noteList.empty();
100100

0 commit comments

Comments
 (0)