From 19b4d51974676c138c19434ea85c61980a782843 Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Mon, 13 Apr 2026 22:11:49 +0000 Subject: [PATCH] implement view persistence class to prevent junk subscriptions --- dist/index.js | 75 ++++++++++++++++++------ src/View/ChatPages/boardPage.tsx | 8 ++- src/View/ChatPages/taskPage.tsx | 9 ++- src/View/chatPage.tsx | 5 +- src/View/viewPersistence.ts | 35 +++++++++++ src/ViewModel/Global/coreViewModel.ts | 3 +- src/ViewModel/Pages/boardViewModel.ts | 2 +- src/ViewModel/Pages/taskPageViewModel.ts | 1 - 8 files changed, 108 insertions(+), 30 deletions(-) create mode 100644 src/View/viewPersistence.ts diff --git a/dist/index.js b/dist/index.js index 76296fa9..3c209085 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,10 +1,9 @@ (() => { - // node_modules/bloatless-react/index.ts + // ../../bloatless-react/index.ts var State = class { - _value; - _bindings = /* @__PURE__ */ new Set(); // init constructor(initialValue) { + this._bindings = /* @__PURE__ */ new Set(); this._value = initialValue; } // value @@ -32,15 +31,16 @@ } }; var ListState = class extends State { - additionHandlers = /* @__PURE__ */ new Set(); - removalHandlers = /* @__PURE__ */ new Map(); // init constructor(initialItems) { super(new Set(initialItems)); + this.additionHandlers = /* @__PURE__ */ new Set(); + this.removalHandlers = /* @__PURE__ */ new Map(); } // list add(...items) { items.forEach((item) => { + if (this.value.has(item)) return; this.value.add(item); this.additionHandlers.forEach((handler) => handler(item)); }); @@ -76,11 +76,11 @@ } }; var MapState = class extends State { - additionHandlers = /* @__PURE__ */ new Set(); - removalHandlers = /* @__PURE__ */ new Map(); // init constructor(initialItems) { super(new Map(initialItems)); + this.additionHandlers = /* @__PURE__ */ new Set(); + this.removalHandlers = /* @__PURE__ */ new Map(); } // list set(key, item) { @@ -350,7 +350,6 @@ // manage this.setHandler = (id, handler) => { this.handlers.set(id, handler); - console.log(this.handlers.size); }; this.deleteHandler = (id) => { this.handlers.delete(id); @@ -3301,7 +3300,7 @@ this.boardInfo.fileId ); for (const taskId of taskIds) { - if (this.taskViewModels.value.has(taskId)) return; + if (this.taskViewModels.value.has(taskId)) continue; const taskFileContent = this.boardsAndTasksModel.getLatestTaskFileContent(taskId); if (taskFileContent == null) continue; const taskViewModel = new TaskViewModel( @@ -3481,7 +3480,6 @@ }; // load this.loadData = () => { - console.log("LOADING TASK PAGE DATA"); this.closeContext(); this.boardViewModels.clear(); const boardIds = this.boardsAndTasksModel.listBoardIds(); @@ -5189,10 +5187,49 @@ )), /* @__PURE__ */ createElement("button", { "on:click": close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))); } + // src/View/viewPersistence.ts + var PageTracker = class { + }; + var PageTrackerMap = class { + constructor() { + this.trackers = /* @__PURE__ */ new Map(); + this.register = (key) => { + if (this.trackers.has(key)) { + return this.trackers.get(key); + } + ; + const tracker = new PageTracker(); + this.trackers.set(key, tracker); + return tracker; + }; + this.setPages = (key, pages) => { + const tracker = this.register(key); + if (tracker.pages != void 0) { + return tracker.pages; + } else { + tracker.pages = pages(); + return tracker.pages; + } + }; + } + }; + var ViewPersistence = class { + static { + this.chatPages = new PageTracker(); + } + static { + this.taskPages = new PageTrackerMap(); + } + static { + this.boardPages = new PageTrackerMap(); + } + }; + // src/View/ChatPages/boardPage.tsx function BoardPage(coreViewModel2, boardViewModel) { boardViewModel.loadData(); - const mainContent = createProxyState( + const persistenceId = boardViewModel.boardInfo.fileId; + const pages = ViewPersistence.boardPages.setPages(persistenceId, () => createProxyState( [boardViewModel.selectedPage], () => { switch (boardViewModel.selectedPage.value) { @@ -5216,7 +5253,7 @@ } } } - ); + )); const taskSettingsModal = createProxyState( [boardViewModel.selectedTaskViewModel], () => { @@ -5288,7 +5325,7 @@ "on:click": boardViewModel.createTask }, /* @__PURE__ */ createElement("span", { class: "icon" }, "add") - ))), /* @__PURE__ */ createElement("div", { class: "content main-content", "children:set": mainContent }), BoardSettingsModal(coreViewModel2, boardViewModel), SearchModal( + ))), /* @__PURE__ */ createElement("div", { class: "content main-content", "children:set": pages }), BoardSettingsModal(coreViewModel2, boardViewModel), SearchModal( coreViewModel2, boardViewModel.searchViewModel, coreViewModel2.translations.chatPage.task.filterTasksHeadline, @@ -5334,7 +5371,8 @@ [taskPageViewModel.selectedBoardId], () => taskPageViewModel.selectedBoardId.value != void 0 ); - const paneContent = createProxyState( + const persistenceId = taskPageViewModel.chatViewModel.chatModel.id; + const pages = ViewPersistence.taskPages.setPages(persistenceId, () => createProxyState( [taskPageViewModel.selectedBoardId], () => { const selectedBoardId = taskPageViewModel.selectedBoardId.value; @@ -5347,9 +5385,10 @@ if (selectedBoard == void 0) { return /* @__PURE__ */ createElement("div", { class: "pane align-center justify-center" }, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.chatPage.task.boardNotFound)); } + console.log("BOARD PAGE"); return BoardPage(coreViewModel2, selectedBoard); } - ); + )); return /* @__PURE__ */ createElement( "div", { @@ -5398,7 +5437,7 @@ { id: "board-content", class: "pane-wrapper", - "children:set": paneContent + "children:set": pages } ) ); @@ -5406,7 +5445,7 @@ // src/View/chatPage.tsx function ChatPage(coreViewModel2, chatViewModel) { - const mainContent = createProxyState( + ViewPersistence.chatPages.pages = createProxyState( [chatViewModel.selectedPage], () => { switch (chatViewModel.selectedPage.value) { @@ -5497,7 +5536,7 @@ "settings", "settings" /* Settings */, chatViewModel - ))), /* @__PURE__ */ createElement("div", { id: "main", "children:set": mainContent })) + ))), /* @__PURE__ */ createElement("div", { id: "main", "children:set": ViewPersistence.chatPages.pages })) ); } diff --git a/src/View/ChatPages/boardPage.tsx b/src/View/ChatPages/boardPage.tsx index fb4edfb8..51b74979 100644 --- a/src/View/ChatPages/boardPage.tsx +++ b/src/View/ChatPages/boardPage.tsx @@ -13,6 +13,7 @@ import { TaskSettingsModal } from "../Modals/taskSettingsModal"; import { TaskViewModelToEntry } from "../Components/taskEntry"; import { setFocusWithDelay } from "../utility"; import CoreViewModel from "../../ViewModel/Global/coreViewModel"; +import { ViewPersistence } from "../viewPersistence"; export function BoardPage( coreViewModel: CoreViewModel, @@ -21,7 +22,8 @@ export function BoardPage( boardViewModel.loadData(); // main content - const mainContent = React.createProxyState( + const persistenceId = boardViewModel.boardInfo.fileId; + const pages = ViewPersistence.boardPages.setPages(persistenceId, ()=>React.createProxyState( [boardViewModel.selectedPage], () => { switch (boardViewModel.selectedPage.value) { @@ -44,7 +46,7 @@ export function BoardPage( } } }, - ); + )); // task modal const taskSettingsModal = React.createProxyState( @@ -150,7 +152,7 @@ export function BoardPage( -
+
{BoardSettingsModal(coreViewModel, boardViewModel)} {SearchModal( diff --git a/src/View/ChatPages/taskPage.tsx b/src/View/ChatPages/taskPage.tsx index 2387098f..b04e9cc7 100644 --- a/src/View/ChatPages/taskPage.tsx +++ b/src/View/ChatPages/taskPage.tsx @@ -7,6 +7,8 @@ import { BoardViewModelToEntry } from "../Components/boardEntry"; import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel"; import CoreViewModel from "../../ViewModel/Global/coreViewModel"; import { PlaceholderView } from "../Components/placeholderView"; +import { v4 } from "uuid"; +import { ViewPersistence } from "../viewPersistence"; export function TaskPage( coreViewModel: CoreViewModel, @@ -19,7 +21,8 @@ export function TaskPage( () => taskPageViewModel.selectedBoardId.value != undefined, ); - const paneContent = React.createProxyState( + const persistenceId = taskPageViewModel.chatViewModel.chatModel.id; + const pages = ViewPersistence.taskPages.setPages(persistenceId, ()=>React.createProxyState( [taskPageViewModel.selectedBoardId], () => { const selectedBoardId = taskPageViewModel.selectedBoardId.value; @@ -45,7 +48,7 @@ export function TaskPage( return BoardPage(coreViewModel, selectedBoard); }, - ); + )); return (
); diff --git a/src/View/chatPage.tsx b/src/View/chatPage.tsx index 8aebe653..2920ecd1 100644 --- a/src/View/chatPage.tsx +++ b/src/View/chatPage.tsx @@ -10,12 +10,13 @@ import { MessagePage } from "./ChatPages/messagePage"; import { SettingsPage } from "./ChatPages/settingsPage"; import { TaskPage } from "./ChatPages/taskPage"; import CoreViewModel from "../ViewModel/Global/coreViewModel"; +import { ViewPersistence } from "./viewPersistence"; export function ChatPage( coreViewModel: CoreViewModel, chatViewModel: ChatViewModel, ) { - const mainContent = React.createProxyState( + ViewPersistence.chatPages.pages = React.createProxyState( [chatViewModel.selectedPage], () => { switch (chatViewModel.selectedPage.value) { @@ -129,7 +130,7 @@ export function ChatPage( )} -
+
); diff --git a/src/View/viewPersistence.ts b/src/View/viewPersistence.ts new file mode 100644 index 00000000..8cbe8d22 --- /dev/null +++ b/src/View/viewPersistence.ts @@ -0,0 +1,35 @@ +import * as React from "bloatless-react"; + +class PageTracker { + pages: React.State | undefined; +} + +class PageTrackerMap { + trackers = new Map(); + + private register = (key: string): PageTracker => { + if (this.trackers.has(key)) { + return this.trackers.get(key); + }; + const tracker = new PageTracker(); + this.trackers.set(key, tracker); + return tracker + } + + setPages = (key: string, pages: () => React.State): React.State | undefined => { + const tracker: PageTracker = this.register(key); + + if (tracker.pages != undefined) { + return tracker.pages; + } else { + tracker.pages = pages(); + return tracker.pages; + } + } +} + +export class ViewPersistence { + static readonly chatPages = new PageTracker(); + static readonly taskPages = new PageTrackerMap(); + static readonly boardPages = new PageTrackerMap(); +} \ No newline at end of file diff --git a/src/ViewModel/Global/coreViewModel.ts b/src/ViewModel/Global/coreViewModel.ts index a79767e2..00f7d0b9 100644 --- a/src/ViewModel/Global/coreViewModel.ts +++ b/src/ViewModel/Global/coreViewModel.ts @@ -100,8 +100,7 @@ export class Context { this.keystrokes.set(key, fn); }; - constructor(public contextDebugDescription: string) { - } + constructor(public contextDebugDescription: string) {} } export class ContextHost extends Context { diff --git a/src/ViewModel/Pages/boardViewModel.ts b/src/ViewModel/Pages/boardViewModel.ts index fb661916..3c4297fd 100644 --- a/src/ViewModel/Pages/boardViewModel.ts +++ b/src/ViewModel/Pages/boardViewModel.ts @@ -204,7 +204,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel { this.boardInfo.fileId, ); for (const taskId of taskIds) { - if (this.taskViewModels.value.has(taskId)) return; + if (this.taskViewModels.value.has(taskId)) continue; const taskFileContent: TaskFileContent | null = this.boardsAndTasksModel.getLatestTaskFileContent(taskId); diff --git a/src/ViewModel/Pages/taskPageViewModel.ts b/src/ViewModel/Pages/taskPageViewModel.ts index 80d3f8de..fb592521 100644 --- a/src/ViewModel/Pages/taskPageViewModel.ts +++ b/src/ViewModel/Pages/taskPageViewModel.ts @@ -143,7 +143,6 @@ export default class TaskPageViewModel extends ContextHost { // load loadData = (): void => { - console.log("LOADING TASK PAGE DATA"); this.closeContext(); this.boardViewModels.clear();