From caa842cd55065a1c4465da4c41002983077f481e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Mon, 14 Jul 2025 16:16:55 +0300 Subject: [PATCH] fix(views/table): unable to update state for newly created rows --- .../client/src/services/note_list_renderer.ts | 14 ++------- apps/client/src/widgets/note_list.ts | 6 ---- .../src/widgets/view_widgets/calendar_view.ts | 2 -- .../widgets/view_widgets/list_or_grid_view.ts | 25 ++++++++-------- .../widgets/view_widgets/table_view/index.ts | 8 ++--- .../src/widgets/view_widgets/view_mode.ts | 30 ++++++++++++++++++- 6 files changed, 46 insertions(+), 39 deletions(-) diff --git a/apps/client/src/services/note_list_renderer.ts b/apps/client/src/services/note_list_renderer.ts index 8e4a6312e..08af048f0 100644 --- a/apps/client/src/services/note_list_renderer.ts +++ b/apps/client/src/services/note_list_renderer.ts @@ -43,19 +43,9 @@ export default class NoteListRenderer { async renderList() { const args = this.args; - - let noteIds: string[]; - if (this.viewType === "list" || this.viewType === "grid") { - noteIds = args.parentNote.getChildNoteIds(); - } else { - noteIds = await args.parentNote.getSubtreeNoteIds(); - } - - const viewMode = this.#buildViewMode({ - ...args, - noteIds - }); + const viewMode = this.#buildViewMode(args); this.viewMode = viewMode; + await viewMode.beforeRender(); return await viewMode.renderList(); } diff --git a/apps/client/src/widgets/note_list.ts b/apps/client/src/widgets/note_list.ts index 65015039a..1b00bd8c2 100644 --- a/apps/client/src/widgets/note_list.ts +++ b/apps/client/src/widgets/note_list.ts @@ -168,12 +168,6 @@ export default class NoteListWidget extends NoteContextAwareWidget { this.refresh(); this.checkRenderStatus(); } - - // Inform the view mode of changes and refresh if needed. - if (this.viewMode && this.viewMode.onEntitiesReloaded(e)) { - this.refresh(); - this.checkRenderStatus(); - } } buildTouchBarCommand(data: CommandListenerData<"buildTouchBar">) { diff --git a/apps/client/src/widgets/view_widgets/calendar_view.ts b/apps/client/src/widgets/view_widgets/calendar_view.ts index 3fb304e3d..d3f20d565 100644 --- a/apps/client/src/widgets/view_widgets/calendar_view.ts +++ b/apps/client/src/widgets/view_widgets/calendar_view.ts @@ -113,7 +113,6 @@ export default class CalendarView extends ViewMode<{}> { private $root: JQuery; private $calendarContainer: JQuery; - private noteIds: string[]; private calendar?: Calendar; private isCalendarRoot: boolean; private lastView?: string; @@ -124,7 +123,6 @@ export default class CalendarView extends ViewMode<{}> { this.$root = $(TPL); this.$calendarContainer = this.$root.find(".calendar-container"); - this.noteIds = args.noteIds; this.isCalendarRoot = false; args.$parent.append(this.$root); } diff --git a/apps/client/src/widgets/view_widgets/list_or_grid_view.ts b/apps/client/src/widgets/view_widgets/list_or_grid_view.ts index c8236b053..1bfc029ab 100644 --- a/apps/client/src/widgets/view_widgets/list_or_grid_view.ts +++ b/apps/client/src/widgets/view_widgets/list_or_grid_view.ts @@ -161,7 +161,7 @@ const TPL = /*html*/` class ListOrGridView extends ViewMode<{}> { private $noteList: JQuery; - private noteIds: string[]; + private filteredNoteIds!: string[]; private page?: number; private pageSize?: number; private showNotePath?: boolean; @@ -174,13 +174,6 @@ class ListOrGridView extends ViewMode<{}> { super(args, viewType); this.$noteList = $(TPL); - const includedNoteIds = this.getIncludedNoteIds(); - - this.noteIds = args.noteIds.filter((noteId) => !includedNoteIds.has(noteId) && noteId !== "_hidden"); - - if (this.noteIds.length === 0) { - return; - } args.$parent.append(this.$noteList); @@ -204,8 +197,14 @@ class ListOrGridView extends ViewMode<{}> { return new Set(includedLinks.map((rel) => rel.value)); } + async beforeRender() { + super.beforeRender(); + const includedNoteIds = this.getIncludedNoteIds(); + this.filteredNoteIds = this.noteIds.filter((noteId) => !includedNoteIds.has(noteId) && noteId !== "_hidden"); + } + async renderList() { - if (this.noteIds.length === 0 || !this.page || !this.pageSize) { + if (this.filteredNoteIds.length === 0 || !this.page || !this.pageSize) { this.$noteList.hide(); return; } @@ -226,7 +225,7 @@ class ListOrGridView extends ViewMode<{}> { const startIdx = (this.page - 1) * this.pageSize; const endIdx = startIdx + this.pageSize; - const pageNoteIds = this.noteIds.slice(startIdx, Math.min(endIdx, this.noteIds.length)); + const pageNoteIds = this.filteredNoteIds.slice(startIdx, Math.min(endIdx, this.filteredNoteIds.length)); const pageNotes = await froca.getNotes(pageNoteIds); for (const note of pageNotes) { @@ -246,7 +245,7 @@ class ListOrGridView extends ViewMode<{}> { return; } - const pageCount = Math.ceil(this.noteIds.length / this.pageSize); + const pageCount = Math.ceil(this.filteredNoteIds.length / this.pageSize); $pager.toggle(pageCount > 1); @@ -257,7 +256,7 @@ class ListOrGridView extends ViewMode<{}> { lastPrinted = true; const startIndex = (i - 1) * this.pageSize + 1; - const endIndex = Math.min(this.noteIds.length, i * this.pageSize); + const endIndex = Math.min(this.filteredNoteIds.length, i * this.pageSize); $pager.append( i === this.page @@ -279,7 +278,7 @@ class ListOrGridView extends ViewMode<{}> { } // no need to distinguish "note" vs "notes" since in case of one result, there's no paging at all - $pager.append(`(${this.noteIds.length} notes)`); + $pager.append(`(${this.filteredNoteIds.length} notes)`); } async renderNote(note: FNote, expand: boolean = false) { diff --git a/apps/client/src/widgets/view_widgets/table_view/index.ts b/apps/client/src/widgets/view_widgets/table_view/index.ts index 4ab836685..dac44fd3f 100644 --- a/apps/client/src/widgets/view_widgets/table_view/index.ts +++ b/apps/client/src/widgets/view_widgets/table_view/index.ts @@ -101,7 +101,6 @@ export default class TableView extends ViewMode { private $root: JQuery; private $container: JQuery; - private args: ViewModeArgs; private spacedUpdate: SpacedUpdate; private api?: Tabulator; private newAttribute?: Attribute; @@ -112,7 +111,6 @@ export default class TableView extends ViewMode { this.$root = $(TPL); this.$container = this.$root.find(".table-view-container"); - this.args = args; this.spacedUpdate = new SpacedUpdate(() => this.onSave(), 5_000); this.persistentData = {}; args.$parent.append(this.$root); @@ -257,9 +255,9 @@ export default class TableView extends ViewMode { this.#manageColumnUpdate(); } - if (loadResults.getBranchRows().some(branch => branch.parentNoteId === this.parentNote.noteId || this.args.noteIds.includes(branch.parentNoteId ?? "")) - || loadResults.getNoteIds().some(noteId => this.args.noteIds.includes(noteId) - || loadResults.getAttributeRows().some(attr => this.args.noteIds.includes(attr.noteId!)))) { + if (loadResults.getBranchRows().some(branch => branch.parentNoteId === this.parentNote.noteId || this.noteIds.includes(branch.parentNoteId ?? "")) + || loadResults.getNoteIds().some(noteId => this.noteIds.includes(noteId) + || loadResults.getAttributeRows().some(attr => this.noteIds.includes(attr.noteId!)))) { this.#manageRowsUpdate(); } diff --git a/apps/client/src/widgets/view_widgets/view_mode.ts b/apps/client/src/widgets/view_widgets/view_mode.ts index 3115454db..4d04130f7 100644 --- a/apps/client/src/widgets/view_widgets/view_mode.ts +++ b/apps/client/src/widgets/view_widgets/view_mode.ts @@ -1,4 +1,5 @@ import type { EventData } from "../../components/app_context.js"; +import appContext from "../../components/app_context.js"; import Component from "../../components/component.js"; import type FNote from "../../entities/fnote.js"; import type { ViewTypeOptions } from "../../services/note_list_renderer.js"; @@ -8,7 +9,6 @@ export interface ViewModeArgs { $parent: JQuery; parentNote: FNote; parentNotePath?: string | null; - noteIds: string[]; showNotePath?: boolean; } @@ -17,6 +17,8 @@ export default abstract class ViewMode extends Component { private _viewStorage: ViewModeStorage | null; protected parentNote: FNote; protected viewType: ViewTypeOptions; + protected noteIds: string[]; + protected args: ViewModeArgs; constructor(args: ViewModeArgs, viewType: ViewTypeOptions) { super(); @@ -25,6 +27,12 @@ export default abstract class ViewMode extends Component { // note list must be added to the DOM immediately, otherwise some functionality scripting (canvas) won't work args.$parent.empty(); this.viewType = viewType; + this.args = args; + this.noteIds = []; + } + + async beforeRender() { + await this.#refreshNoteIds(); } abstract renderList(): Promise | undefined>; @@ -39,6 +47,16 @@ export default abstract class ViewMode extends Component { // Do nothing by default. } + entitiesReloadedEvent(e: EventData<"entitiesReloaded">) { + if (e.loadResults.getBranchRows().some(branch => branch.parentNoteId === this.parentNote.noteId || this.noteIds.includes(branch.parentNoteId ?? ""))) { + this.#refreshNoteIds(); + } + + if (this.onEntitiesReloaded(e)) { + appContext.triggerEvent("refreshNoteList", { noteId: this.parentNote.noteId }); + } + } + get isReadOnly() { return this.parentNote.hasLabel("readOnly"); } @@ -52,4 +70,14 @@ export default abstract class ViewMode extends Component { return this._viewStorage; } + async #refreshNoteIds() { + let noteIds: string[]; + if (this.viewType === "list" || this.viewType === "grid") { + noteIds = this.args.parentNote.getChildNoteIds(); + } else { + noteIds = await this.args.parentNote.getSubtreeNoteIds(); + } + this.noteIds = noteIds; + } + }