Skip to content

Commit 0ccc350

Browse files
authored
Port type widgets to React (#7044)
2 parents 06eb30c + efa7fd0 commit 0ccc350

File tree

164 files changed

+6136
-6884
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+6136
-6884
lines changed

apps/client/src/components/app_context.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,13 @@ import MainTreeExecutors from "./main_tree_executors.js";
1313
import toast from "../services/toast.js";
1414
import ShortcutComponent from "./shortcut_component.js";
1515
import { t, initLocale } from "../services/i18n.js";
16-
import type NoteDetailWidget from "../widgets/note_detail.js";
1716
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
1817
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
1918
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
2019
import type LoadResults from "../services/load_results.js";
2120
import type { Attribute } from "../services/attribute_parser.js";
2221
import type NoteTreeWidget from "../widgets/note_tree.js";
2322
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
24-
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
25-
import type EditableTextTypeWidget from "../widgets/type_widgets/editable_text.js";
2623
import type { NativeImage, TouchBar } from "electron";
2724
import TouchBarComponent from "./touch_bar.js";
2825
import type { CKTextEditor } from "@triliumnext/ckeditor5";
@@ -33,6 +30,10 @@ import { ColumnComponent } from "tabulator-tables";
3330
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
3431
import type RootContainer from "../widgets/containers/root_container.js";
3532
import { SqlExecuteResults } from "@triliumnext/commons";
33+
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
34+
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
35+
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
36+
import type { MarkdownImportOpts } from "../widgets/dialogs/markdown_import.jsx";
3637

3738
interface Layout {
3839
getRootWidget: (appContext: AppContext) => RootContainer;
@@ -199,7 +200,7 @@ export type CommandMappings = {
199200
resetLauncher: ContextMenuCommandData;
200201

201202
executeInActiveNoteDetailWidget: CommandData & {
202-
callback: (value: NoteDetailWidget | PromiseLike<NoteDetailWidget>) => void;
203+
callback: (value: ReactWrappedWidget) => void;
203204
};
204205
executeWithTextEditor: CommandData &
205206
ExecuteCommandData<CKTextEditor> & {
@@ -211,7 +212,7 @@ export type CommandMappings = {
211212
* Generally should not be invoked manually, as it is used by {@link NoteContext.getContentElement}.
212213
*/
213214
executeWithContentElement: CommandData & ExecuteCommandData<JQuery<HTMLElement>>;
214-
executeWithTypeWidget: CommandData & ExecuteCommandData<TypeWidget | null>;
215+
executeWithTypeWidget: CommandData & ExecuteCommandData<ReactWrappedWidget | null>;
215216
addTextToActiveEditor: CommandData & {
216217
text: string;
217218
};
@@ -221,9 +222,9 @@ export type CommandMappings = {
221222
showPasswordNotSet: CommandData;
222223
showProtectedSessionPasswordDialog: CommandData;
223224
showUploadAttachmentsDialog: CommandData & { noteId: string };
224-
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
225-
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
226-
showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
225+
showIncludeNoteDialog: CommandData & IncludeNoteOpts;
226+
showAddLinkDialog: CommandData & AddLinkOpts;
227+
showPasteMarkdownDialog: CommandData & MarkdownImportOpts;
227228
closeProtectedSessionPasswordDialog: CommandData;
228229
copyImageReferenceToClipboard: CommandData;
229230
copyImageToClipboard: CommandData;
@@ -485,13 +486,8 @@ type EventMappings = {
485486
relationMapResetZoomIn: { ntxId: string | null | undefined };
486487
relationMapResetZoomOut: { ntxId: string | null | undefined };
487488
activeNoteChanged: {};
488-
showAddLinkDialog: {
489-
textTypeWidget: EditableTextTypeWidget;
490-
text: string;
491-
};
492-
showIncludeDialog: {
493-
textTypeWidget: EditableTextTypeWidget;
494-
};
489+
showAddLinkDialog: AddLinkOpts;
490+
showIncludeDialog: IncludeNoteOpts;
495491
openBulkActionsDialog: {
496492
selectedOrActiveNoteIds: string[];
497493
};
@@ -670,6 +666,10 @@ export class AppContext extends Component {
670666
this.beforeUnloadListeners.push(obj);
671667
}
672668
}
669+
670+
removeBeforeUnloadListener(listener: (() => boolean)) {
671+
this.beforeUnloadListeners = this.beforeUnloadListeners.filter(l => l !== listener);
672+
}
673673
}
674674

675675
const appContext = new AppContext(window.glob.isMainWindow);

apps/client/src/components/note_context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import hoistedNoteService from "../services/hoisted_note.js";
99
import options from "../services/options.js";
1010
import type { ViewScope } from "../services/link.js";
1111
import type FNote from "../entities/fnote.js";
12-
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
1312
import type { CKTextEditor } from "@triliumnext/ckeditor5";
1413
import type CodeMirror from "@triliumnext/codemirror";
1514
import { closeActiveDialog } from "../services/dialog.js";
15+
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
1616

1717
export interface SetNoteOpts {
1818
triggerSwitchEvent?: unknown;
@@ -397,7 +397,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
397397

398398
async getTypeWidget() {
399399
return this.timeout(
400-
new Promise<TypeWidget | null>((resolve) =>
400+
new Promise<ReactWrappedWidget | null>((resolve) =>
401401
appContext.triggerCommand("executeWithTypeWidget", {
402402
resolve,
403403
ntxId: this.ntxId

apps/client/src/components/tab_manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ export default class TabManager extends Component {
265265
mainNtxId: string | null = null
266266
): Promise<NoteContext> {
267267
const noteContext = new NoteContext(ntxId, hoistedNoteId, mainNtxId);
268+
noteContext.setEmpty();
268269

269270
const existingNoteContext = this.children.find((nc) => nc.ntxId === noteContext.ntxId);
270271

apps/client/src/layouts/desktop_layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import LauncherContainer from "../widgets/containers/launcher_container.js";
1414
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
1515
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
1616
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
17-
import NoteDetailWidget from "../widgets/note_detail.js";
1817
import NoteIconWidget from "../widgets/note_icon.jsx";
1918
import NoteList from "../widgets/collections/NoteList.jsx";
2019
import NoteTitleWidget from "../widgets/note_title.jsx";
@@ -44,6 +43,7 @@ import type { WidgetsByParent } from "../services/bundle.js";
4443
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
4544
import utils from "../services/utils.js";
4645
import WatchedFileUpdateStatusWidget from "../widgets/watched_file_update_status.js";
46+
import NoteDetail from "../widgets/NoteDetail.jsx";
4747

4848
export default class DesktopLayout {
4949

@@ -142,7 +142,7 @@ export default class DesktopLayout {
142142
)
143143
.child(new PromotedAttributesWidget())
144144
.child(<SqlTableSchemas />)
145-
.child(new NoteDetailWidget())
145+
.child(<NoteDetail />)
146146
.child(<NoteList media="screen" />)
147147
.child(<SearchResult />)
148148
.child(<SqlResults />)

apps/client/src/layouts/layout_commons.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ import PopupEditorDialog from "../widgets/dialogs/popup_editor.js";
2626
import FlexContainer from "../widgets/containers/flex_container.js";
2727
import NoteIconWidget from "../widgets/note_icon";
2828
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
29-
import NoteDetailWidget from "../widgets/note_detail.js";
3029
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
3130
import NoteTitleWidget from "../widgets/note_title.jsx";
3231
import FormattingToolbar from "../widgets/ribbon/FormattingToolbar.js";
3332
import NoteList from "../widgets/collections/NoteList.jsx";
33+
import NoteDetail from "../widgets/NoteDetail.jsx";
3434
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
3535

3636
export function applyModals(rootContainer: RootContainer) {
@@ -66,7 +66,7 @@ export function applyModals(rootContainer: RootContainer) {
6666
.child(<NoteTitleWidget />))
6767
.child(<StandaloneRibbonAdapter component={FormattingToolbar} />)
6868
.child(new PromotedAttributesWidget())
69-
.child(new NoteDetailWidget())
69+
.child(<NoteDetail />)
7070
.child(<NoteList media="screen" displayOnlyCollections />))
7171
.child(<CallToActionDialog />);
7272
}

apps/client/src/layouts/mobile_layout.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import FloatingButtons from "../widgets/FloatingButtons.jsx";
88
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
99
import LauncherContainer from "../widgets/containers/launcher_container.js";
1010
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
11-
import MobileEditorToolbar from "../widgets/type_widgets/ckeditor/mobile_editor_toolbar.js";
12-
import NoteDetailWidget from "../widgets/note_detail.js";
1311
import NoteList from "../widgets/collections/NoteList.jsx";
1412
import NoteTitleWidget from "../widgets/note_title.js";
1513
import ContentHeader from "../widgets/containers/content-header.js";
@@ -29,6 +27,8 @@ import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibb
2927
import TabRowWidget from "../widgets/tab_row.js";
3028
import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx";
3129
import type AppContext from "../components/app_context.js";
30+
import NoteDetail from "../widgets/NoteDetail.jsx";
31+
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
3232

3333
const MOBILE_CSS = `
3434
<style>
@@ -161,7 +161,7 @@ export default class MobileLayout {
161161
.child(<ReadOnlyNoteInfoBar />)
162162
.child(<SharedInfoWidget />)
163163
)
164-
.child(new NoteDetailWidget())
164+
.child(<NoteDetail />)
165165
.child(<NoteList media="screen" />)
166166
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
167167
.child(<SearchResult />)

apps/client/src/services/frontend_script_api.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import RightPanelWidget from "../widgets/right_panel_widget.js";
1111
import ws from "./ws.js";
1212
import appContext from "../components/app_context.js";
1313
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
14-
import BasicWidget from "../widgets/basic_widget.js";
14+
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
1515
import SpacedUpdate from "./spaced_update.js";
1616
import shortcutService from "./shortcuts.js";
1717
import dialogService from "./dialog.js";
1818
import type FNote from "../entities/fnote.js";
1919
import { t } from "./i18n.js";
2020
import dayjs from "dayjs";
2121
import type NoteContext from "../components/note_context.js";
22-
import type NoteDetailWidget from "../widgets/note_detail.js";
2322
import type Component from "../components/component.js";
2423
import { formatLogMessage } from "@triliumnext/commons";
2524

@@ -317,7 +316,7 @@ export interface Api {
317316
* Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the
318317
* implementation of actual widget type.
319318
*/
320-
getActiveNoteDetailWidget(): Promise<NoteDetailWidget>;
319+
getActiveNoteDetailWidget(): Promise<ReactWrappedWidget>;
321320
/**
322321
* @returns returns a note path of active note or null if there isn't active note
323322
*/

apps/client/src/services/keyboard_actions.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import server from "./server.js";
2-
import appContext, { type CommandNames } from "../components/app_context.js";
3-
import shortcutService from "./shortcuts.js";
2+
import appContext from "../components/app_context.js";
3+
import shortcutService, { ShortcutBinding } from "./shortcuts.js";
44
import type Component from "../components/component.js";
55
import type { ActionKeyboardShortcut } from "@triliumnext/commons";
66

@@ -30,12 +30,18 @@ async function getActionsForScope(scope: string) {
3030

3131
async function setupActionsForElement(scope: string, $el: JQuery<HTMLElement>, component: Component) {
3232
const actions = await getActionsForScope(scope);
33+
const bindings: ShortcutBinding[] = [];
3334

3435
for (const action of actions) {
3536
for (const shortcut of action.effectiveShortcuts ?? []) {
36-
shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, { ntxId: appContext.tabManager.activeNtxId }));
37+
const binding = shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, { ntxId: appContext.tabManager.activeNtxId }));
38+
if (binding) {
39+
bindings.push(binding);
40+
}
3741
}
3842
}
43+
44+
return bindings;
3945
}
4046

4147
getActionsForScope("window").then((actions) => {

apps/client/src/services/link.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ function goToLink(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent) {
280280
* @param $link the jQuery element of the link that was clicked, used to determine if the link is an anchor link (e.g., `#fn1` or `#fnref1`) and to handle it accordingly.
281281
* @returns `true` if the link was handled (i.e., the element was found and scrolled to), or a falsy value otherwise.
282282
*/
283-
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
283+
export function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
284284
if (hrefLink?.startsWith("data:")) {
285285
return true;
286286
}

apps/client/src/services/open.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ function downloadRevision(noteId: string, revisionId: string) {
126126
/**
127127
* @param url - should be without initial slash!!!
128128
*/
129-
function getUrlForDownload(url: string) {
129+
export function getUrlForDownload(url: string) {
130130
if (utils.isElectron()) {
131131
// electron needs absolute URL, so we extract current host, port, protocol
132132
return `${getHost()}/${url}`;

0 commit comments

Comments
 (0)