integrate context with window.history API

This commit is contained in:
marlon-erler
2026-04-14 17:19:35 +00:00
parent 77fac64879
commit 9e9ede570d
13 changed files with 150 additions and 90 deletions
-2
View File
@@ -1,12 +1,10 @@
import * as React from "bloatless-react";
import ChatListModel from "../../Model/Chat/chatListModel";
import ChatModel from "../../Model/Chat/chatModel";
import ChatViewModel from "./chatViewModel";
import CoreViewModel from "../Global/coreViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import SettingsViewModel from "../Global/settingsViewModel";
import StorageModel from "../../Model/Global/storageModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import NotificationViewModel from "../Global/notificationViewModel";
+11 -7
View File
@@ -58,14 +58,9 @@ export default class ChatViewModel extends ContextHost<ChatPageTypes> {
this.chatListViewModel.openChat(this);
//this.selectedPage.callSubscriptions();
};
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
this.chatListViewModel.closeChat();
};
openPage = (page: ChatPageTypes): void => {
this.closeContext();
this.closeCurrentContext();
this.selectedPage.value = page;
};
@@ -140,6 +135,15 @@ export default class ChatViewModel extends ContextHost<ChatPageTypes> {
);
};
// exit
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
};
handleContextClose = (): void => {
this.chatListViewModel.closeChat();
}
// init
constructor(
public readonly coreViewModel: CoreViewModel,
+15 -5
View File
@@ -14,6 +14,7 @@ export default class CoreViewModel {
// CONTEXT
private contextStack = new Map<string, Context>();
get contexts(): Context[] {
return [...this.contextStack.values()];
}
@@ -23,16 +24,20 @@ export default class CoreViewModel {
set context(context: Context) {
if (this.contextStack.has(context.contextId)) return;
this.contextStack.set(context.contextId, context);
history.pushState({ id: context.contextId }, "");
}
closeContext = (contextId: string): void => {
closeContext = (contextId: string, fromHistoryEvent: boolean = false): void => {
if (
!this.contexts
.map((context) => context.contextId)
.includes(contextId)
)
return;
while (this.contexts.length > 0) {
const currentContext: Context = this.context;
currentContext.handleContextClose(fromHistoryEvent);
this.contextStack.delete(currentContext.contextId);
if (currentContext.contextId == contextId) break;
}
@@ -73,6 +78,10 @@ export default class CoreViewModel {
allTranslations[settingsModel.language] || allTranslations.en;
document.body.addEventListener("keydown", this.handleKeyDown);
window.onpopstate = () => {
this.closeContext(this.context.contextId, true);
}
}
// util
@@ -94,13 +103,14 @@ export class Context {
return true;
};
close: () => void;
close = (): void => {};
handleContextClose = (fromHistoryEvent: boolean): void => {};
registerKeyStroke = (key: string, fn: () => void): void => {
this.keystrokes.set(key, fn);
};
constructor(public contextDebugDescription: string) {}
constructor(public contextDebugDescription: string) { }
}
export class ContextHost<T> extends Context {
@@ -119,7 +129,7 @@ export class ContextHost<T> extends Context {
this.contexts.set(key, context);
};
closeContext = (): void => {
closeCurrentContext = (): void => {
if (this.currentContext.value) {
this.coreViewModel.closeContext(
this.currentContext.value.contextId,
@@ -136,7 +146,7 @@ export class ContextHost<T> extends Context {
);
if (!selectedContext) return;
if (selectedContext != this.currentContext.value) {
this.closeContext();
this.closeCurrentContext();
}
this.coreViewModel.context = selectedContext;
@@ -164,11 +164,15 @@ export default class FileTransferViewModel extends Context {
this.coreViewModel.fileTransferModel.prepareToReceive(transferData);
};
hideModal = (): void => {
// exit
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
this.presentedModal.value = undefined;
};
handleContextClose = (): void => {
this.presentedModal.value = undefined;
}
// init
constructor(public readonly coreViewModel: CoreViewModel) {
super("file-transfer");
@@ -184,7 +188,7 @@ export default class FileTransferViewModel extends Context {
);
// keystrokes
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.hideModal);
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.close);
}
}
+13 -9
View File
@@ -48,14 +48,6 @@ export default class SettingsViewModel extends Context {
this.isShowingSettingsModal.value = true;
};
hideSettingsModal = (): void => {
this.coreViewModel.closeContext(this.contextId);
this.isShowingSettingsModal.value = false;
if (this.requiresReload.value == true) {
window.location.reload();
}
};
showModalPage = (page: SettingsModalPages): void => {
this.selectedModalPage.value = page;
};
@@ -69,6 +61,18 @@ export default class SettingsViewModel extends Context {
document.body.setAttribute("theme", theme);
};
// exit
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
};
handleContextClose = (): void => {
this.isShowingSettingsModal.value = false;
if (this.requiresReload.value == true) {
window.location.reload();
}
}
// init
constructor(public readonly coreViewModel: CoreViewModel) {
super("settings");
@@ -100,7 +104,7 @@ export default class SettingsViewModel extends Context {
// keystrokes
this.registerKeyStroke(
CommonKeys.CloseOrCancel,
this.hideSettingsModal,
this.close,
);
}
+7 -3
View File
@@ -54,14 +54,18 @@ export default class StorageViewModel extends Context {
this.isShowingStorageModal.value = true;
};
hideStorageModal = (): void => {
// exit
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
};
handleContextClose = (): void => {
if (this.didMakeChanges.value == true) {
window.location.reload();
return;
}
this.isShowingStorageModal.value = false;
};
}
// init
constructor(public readonly coreViewModel: CoreViewModel) {
@@ -77,6 +81,6 @@ export default class StorageViewModel extends Context {
);
// keystrokes
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.hideStorageModal);
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.close);
}
}
+9 -6
View File
@@ -9,7 +9,6 @@ import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { Colors } from "../../colors";
import CoreViewModel from "../Global/coreViewModel";
import SearchViewModel from "../Utility/searchViewModel";
import StorageModel from "../../Model/Global/storageModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import TaskPageViewModel from "./taskPageViewModel";
import TaskViewModel from "./taskViewModel";
@@ -164,6 +163,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
close = (): void => {
this.taskPageViewModel.closeBoard();
this.taskPageViewModel.storeLastUsedBoard();
this.taskViewModels.clear();
};
@@ -246,6 +246,14 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
this.loadSearchSuggestions();
};
// exit
handleContextClose = (fromHistoryEvent: boolean): void => {
this.taskPageViewModel.handleBoardClosed(this);
if (!fromHistoryEvent) return;
this.taskPageViewModel.storeLastUsedBoard();
}
// init
constructor(
public readonly coreViewModel: CoreViewModel,
@@ -276,11 +284,6 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
this.selectedPage.subscribeSilent(() => {
this.storeLastUsedView();
console.log(
"SELECTED PAGE",
this.selectedPage.value,
this.contextId,
);
});
// handlers
+8 -5
View File
@@ -104,7 +104,8 @@ export default class TaskPageViewModel extends ContextHost<string> {
this.chatViewModel.displayedColor.value = boardViewModel.color.value;
if (this.selectedBoardId.value == boardViewModel.boardInfo.fileId) {
return this.updateContexts();
this.updateContexts();
return;
}
this.selectedBoardId.value = boardViewModel.boardInfo.fileId;
@@ -112,12 +113,14 @@ export default class TaskPageViewModel extends ContextHost<string> {
};
closeBoard = (): void => {
this.closeContext();
this.closeCurrentContext();
}
handleBoardClosed = (boardViewModel: BoardViewModel): void => {
if (boardViewModel.boardInfo.fileId != this.selectedBoardId.value) return;
this.selectedBoardId.value = undefined;
this.chatViewModel.resetColor();
this.storeLastUsedBoard();
};
updateBoardIndices = (): void => {
@@ -149,7 +152,7 @@ export default class TaskPageViewModel extends ContextHost<string> {
// load
loadData = (): void => {
this.closeContext();
this.closeCurrentContext();
const boardIds: string[] = this.boardsAndTasksModel.listBoardIds();
for (const boardId of boardIds) {
+9 -7
View File
@@ -89,11 +89,6 @@ export default class TaskViewModel extends Context {
this.containingViewModel.selectTask(this);
};
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
this.containingViewModel.closeTask();
};
closeAndDiscard = (): void => {
this.close();
this.loadTaskData();
@@ -203,11 +198,18 @@ export default class TaskViewModel extends Context {
this.date.value = this.task.date ?? "";
this.time.value = this.task.time ?? "";
this.selectedVersionId.value = this.task.fileContentId;
this.updateSuggestions();
};
// exit
close = (): void => {
this.coreViewModel.closeContext(this.contextId);
};
handleContextClose = (): void => {
this.containingViewModel.closeTask();
};
// init
constructor(
public readonly coreViewModel: CoreViewModel,