Files
CT/src/ViewModel/Global/settingsViewModel.ts
T

122 lines
3.9 KiB
TypeScript
Raw Normal View History

import * as React from "bloatless-react";
2026-04-12 19:20:37 +00:00
import CoreViewModel, { Context } from "./coreViewModel";
2026-04-09 18:09:26 +00:00
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
2026-04-12 19:20:37 +00:00
import { CommonKeys } from "../../View/keystrokes";
export default class SettingsViewModel extends Context {
2026-04-01 08:29:39 +00:00
// state
username: React.State<string> = new React.State("");
usernameInput: React.State<string> = new React.State("");
2026-04-08 20:39:12 +00:00
isShowingSettingsModal: React.State<boolean> = new React.State(false);
2026-04-10 19:00:59 +00:00
selectedModalPage: React.State<SettingsModalPages | undefined> =
new React.State(undefined);
2026-04-09 17:14:33 +00:00
requiresReload = new React.State<boolean>(false);
2026-04-01 08:29:39 +00:00
firstDayOfWeek: React.State<string> = new React.State("0");
2026-04-09 18:09:26 +00:00
language: React.State<Languages | string> = new React.State(
Languages.English,
);
theme: React.State<ThemeSettings | string> = new React.State(
ThemeSettings.System,
);
2026-04-01 08:29:39 +00:00
// guards
cannotSetName: React.State<boolean> = React.createProxyState(
[this.usernameInput],
() =>
this.usernameInput.value == "" ||
this.usernameInput.value ==
this.coreViewModel.settingsModel.username,
2026-04-01 08:29:39 +00:00
);
// methods
setName = (): void => {
this.coreViewModel.settingsModel.setName(this.usernameInput.value);
this.username.value = this.coreViewModel.settingsModel.username;
2026-04-01 08:29:39 +00:00
this.usernameInput.callSubscriptions();
};
setFirstDayofWeek = (): void => {
this.coreViewModel.settingsModel.setFirstDayOfWeek(
this.firstDayOfWeek.value,
);
2026-04-01 08:29:39 +00:00
};
2026-04-08 20:39:12 +00:00
showSettingsModal = (): void => {
2026-04-12 19:20:37 +00:00
this.coreViewModel.context = this;
2026-04-08 20:39:12 +00:00
this.isShowingSettingsModal.value = true;
2026-04-08 21:03:36 +00:00
};
2026-04-08 20:39:12 +00:00
hideSettingsModal = (): void => {
2026-04-12 19:20:37 +00:00
this.coreViewModel.closeContext(this.contextId);
2026-04-08 20:39:12 +00:00
this.isShowingSettingsModal.value = false;
2026-04-09 17:14:33 +00:00
if (this.requiresReload.value == true) {
window.location.reload();
}
2026-04-08 21:03:36 +00:00
};
showModalPage = (page: SettingsModalPages): void => {
this.selectedModalPage.value = page;
};
2026-04-08 20:39:12 +00:00
2026-04-09 18:09:26 +00:00
// view
applyTheme = (): void => {
2026-04-13 11:23:17 +00:00
let theme: string = this.theme.value;
2026-04-09 18:09:26 +00:00
if (theme == ThemeSettings.System) {
theme = SettingsViewModel.getSystemTheme();
}
document.body.setAttribute("theme", theme);
};
2026-04-01 08:29:39 +00:00
// init
2026-04-13 10:58:21 +00:00
constructor(public readonly coreViewModel: CoreViewModel) {
2026-04-13 19:45:52 +00:00
super("settings");
2026-04-12 19:20:37 +00:00
this.username.value = coreViewModel.settingsModel.username;
this.usernameInput.value = coreViewModel.settingsModel.username;
this.firstDayOfWeek.value = coreViewModel.settingsModel.firstDayOfWeek;
2026-04-09 17:14:33 +00:00
this.language.value = coreViewModel.settingsModel.language;
2026-04-09 18:09:26 +00:00
this.theme.value = coreViewModel.settingsModel.theme;
2026-04-01 08:29:39 +00:00
// subscriptions
this.firstDayOfWeek.subscribe(this.setFirstDayofWeek);
2026-04-09 17:14:33 +00:00
this.language.subscribeSilent((newValue) => {
this.coreViewModel.settingsModel.setLanguage(newValue);
this.requiresReload.value = true;
2026-04-09 18:09:26 +00:00
});
this.theme.subscribeSilent((newValue) => {
this.coreViewModel.settingsModel.setTheme(newValue);
});
// set theme
this.theme.subscribe(() => {
this.applyTheme();
});
SettingsViewModel.generateThemeMedia().addEventListener("change", () =>
this.applyTheme(),
);
2026-04-12 19:20:37 +00:00
// keystrokes
2026-04-13 11:23:17 +00:00
this.registerKeyStroke(
CommonKeys.CloseOrCancel,
this.hideSettingsModal,
);
2026-04-09 18:09:26 +00:00
}
static generateThemeMedia(): MediaQueryList {
return window.matchMedia("(prefers-color-scheme: dark)");
}
static getSystemTheme(): string {
const media = SettingsViewModel.generateThemeMedia();
return media.matches == true ? ThemeSettings.Dark : ThemeSettings.Light;
2026-04-01 08:29:39 +00:00
}
}
2026-04-08 21:03:36 +00:00
export enum SettingsModalPages {
Appearance,
Regional,
2026-04-08 21:14:37 +00:00
Info,
2026-04-08 21:03:36 +00:00
}