2026-04-08 20:39:12 +00:00
|
|
|
import * as React from "bloatless-react";
|
|
|
|
|
|
2026-04-09 17:32:17 +00:00
|
|
|
import { languageNames } from "../translations";
|
2026-04-08 21:03:36 +00:00
|
|
|
import SettingsViewModel, {
|
|
|
|
|
SettingsModalPages,
|
|
|
|
|
} from "../../ViewModel/Global/settingsViewModel";
|
|
|
|
|
import { SplitModal } from "../Components/splitModal";
|
2026-04-09 15:45:19 +00:00
|
|
|
import { InfoTile } from "../Components/infoTile";
|
2026-04-09 15:49:19 +00:00
|
|
|
import { Option } from "../Components/option";
|
2026-04-09 16:48:22 +00:00
|
|
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
2026-04-09 18:09:26 +00:00
|
|
|
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
|
|
|
|
|
import { OptionButtonList } from "../Components/optionButtonList";
|
|
|
|
|
import { stringify } from "../../Model/Utility/utility";
|
2026-04-08 20:39:12 +00:00
|
|
|
|
2026-04-09 16:48:22 +00:00
|
|
|
export function SettingsModal(
|
|
|
|
|
coreViewModel: CoreViewModel,
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
) {
|
2026-04-09 15:45:19 +00:00
|
|
|
const detailView = React.createProxyState(
|
|
|
|
|
[settingsViewModel.selectedModalPage],
|
|
|
|
|
() => {
|
|
|
|
|
switch (settingsViewModel.selectedModalPage.value) {
|
|
|
|
|
case SettingsModalPages.Appearance:
|
2026-04-09 18:09:26 +00:00
|
|
|
return SettingsAppearancePane(
|
|
|
|
|
coreViewModel,
|
|
|
|
|
settingsViewModel,
|
|
|
|
|
);
|
2026-04-09 15:45:19 +00:00
|
|
|
case SettingsModalPages.Regional:
|
2026-04-09 16:48:22 +00:00
|
|
|
return SettingsRegionalPane(
|
|
|
|
|
coreViewModel,
|
|
|
|
|
settingsViewModel,
|
|
|
|
|
);
|
2026-04-09 15:45:19 +00:00
|
|
|
case SettingsModalPages.Info:
|
2026-04-09 16:48:22 +00:00
|
|
|
return SettingsInfoPane(coreViewModel, settingsViewModel);
|
2026-04-09 15:45:19 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
2026-04-09 08:35:14 +00:00
|
|
|
|
2026-04-08 20:39:12 +00:00
|
|
|
return (
|
2026-04-08 21:03:36 +00:00
|
|
|
<div
|
|
|
|
|
class="modal"
|
|
|
|
|
toggle:open={settingsViewModel.isShowingSettingsModal}
|
|
|
|
|
>
|
2026-04-08 21:14:37 +00:00
|
|
|
<div>
|
2026-04-08 21:03:36 +00:00
|
|
|
<main class="padding-0">
|
|
|
|
|
{SplitModal(
|
2026-04-09 16:48:22 +00:00
|
|
|
new React.State(
|
|
|
|
|
SettingsLeftPane(coreViewModel, settingsViewModel),
|
|
|
|
|
),
|
2026-04-09 08:35:14 +00:00
|
|
|
detailView,
|
2026-04-09 21:45:56 +00:00
|
|
|
true,
|
2026-04-08 21:14:37 +00:00
|
|
|
settingsViewModel.selectedModalPage,
|
2026-04-08 21:03:36 +00:00
|
|
|
)}
|
|
|
|
|
</main>
|
2026-04-08 20:39:12 +00:00
|
|
|
<button on:click={settingsViewModel.hideSettingsModal}>
|
2026-04-09 16:48:22 +00:00
|
|
|
{coreViewModel.translations.general.closeButton}
|
2026-04-08 20:39:12 +00:00
|
|
|
<span class="icon">close</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-04-08 21:03:36 +00:00
|
|
|
|
2026-04-09 16:48:22 +00:00
|
|
|
function SettingsLeftPane(
|
|
|
|
|
coreViewModel: CoreViewModel,
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
) {
|
2026-04-08 21:03:36 +00:00
|
|
|
return (
|
2026-04-08 21:14:37 +00:00
|
|
|
<div class="flex-column gap">
|
2026-04-08 21:03:36 +00:00
|
|
|
{SettingsPaneButton(
|
|
|
|
|
settingsViewModel,
|
|
|
|
|
SettingsModalPages.Appearance,
|
2026-04-09 16:48:22 +00:00
|
|
|
coreViewModel.translations.settings.pages.appearance,
|
2026-04-08 21:03:36 +00:00
|
|
|
)}
|
|
|
|
|
{SettingsPaneButton(
|
|
|
|
|
settingsViewModel,
|
|
|
|
|
SettingsModalPages.Regional,
|
2026-04-09 16:48:22 +00:00
|
|
|
coreViewModel.translations.settings.pages.regional,
|
2026-04-08 21:03:36 +00:00
|
|
|
)}
|
2026-04-08 21:14:37 +00:00
|
|
|
{SettingsPaneButton(
|
|
|
|
|
settingsViewModel,
|
|
|
|
|
SettingsModalPages.Info,
|
2026-04-09 16:48:22 +00:00
|
|
|
coreViewModel.translations.settings.pages.info,
|
2026-04-08 21:14:37 +00:00
|
|
|
)}
|
2026-04-08 21:03:36 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SettingsPaneButton(
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
page: SettingsModalPages,
|
|
|
|
|
label: string,
|
|
|
|
|
) {
|
|
|
|
|
const isSelected = React.createProxyState(
|
|
|
|
|
[settingsViewModel.selectedModalPage],
|
|
|
|
|
() => settingsViewModel.selectedModalPage.value == page,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
toggle:selected={isSelected}
|
|
|
|
|
on:click={() => settingsViewModel.showModalPage(page)}
|
|
|
|
|
>
|
|
|
|
|
{label}
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-04-09 15:45:19 +00:00
|
|
|
|
2026-04-09 16:48:22 +00:00
|
|
|
function SettingsInfoPane(
|
|
|
|
|
coreViewModel: CoreViewModel,
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
) {
|
2026-04-09 15:45:19 +00:00
|
|
|
return (
|
|
|
|
|
<div class="slide-up">
|
2026-04-09 16:48:22 +00:00
|
|
|
<h2>{coreViewModel.translations.homePage.appName}</h2>
|
2026-04-09 15:45:19 +00:00
|
|
|
<hr></hr>
|
|
|
|
|
<div class="flex-column gap">
|
|
|
|
|
{InfoTile(
|
|
|
|
|
"build",
|
2026-04-09 16:48:22 +00:00
|
|
|
coreViewModel.translations.settings.version,
|
2026-04-09 15:45:19 +00:00
|
|
|
settingsViewModel.coreViewModel.BUILD,
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-04-09 15:49:19 +00:00
|
|
|
|
2026-04-09 16:48:22 +00:00
|
|
|
function SettingsRegionalPane(
|
|
|
|
|
coreViewModel: CoreViewModel,
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
) {
|
2026-04-09 15:49:19 +00:00
|
|
|
return (
|
|
|
|
|
<div class="slide-up">
|
2026-04-09 16:48:22 +00:00
|
|
|
<h2>{coreViewModel.translations.settings.pages.regional}</h2>
|
2026-04-09 21:45:56 +00:00
|
|
|
|
2026-04-09 15:49:19 +00:00
|
|
|
<hr></hr>
|
2026-04-09 21:45:56 +00:00
|
|
|
<h3>{coreViewModel.translations.settings.language}</h3>
|
|
|
|
|
{OptionButtonList(
|
|
|
|
|
new React.ListState<[string, string]>(
|
2026-04-10 18:17:16 +00:00
|
|
|
Object.values(Languages).map((x) => [languageNames[x], x]),
|
2026-04-09 21:45:56 +00:00
|
|
|
),
|
|
|
|
|
settingsViewModel.language,
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
<hr></hr>
|
|
|
|
|
<h3>{coreViewModel.translations.settings.firstDayOfWeekLabel}</h3>
|
|
|
|
|
{OptionButtonList(
|
|
|
|
|
new React.ListState<[string, string]>(
|
|
|
|
|
coreViewModel.translations.regional.weekdays.full.map(
|
|
|
|
|
(x, i) => [x, i.toString()],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
settingsViewModel.firstDayOfWeek,
|
|
|
|
|
)}
|
2026-04-09 15:49:19 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-04-09 18:09:26 +00:00
|
|
|
|
|
|
|
|
function SettingsAppearancePane(
|
|
|
|
|
coreViewModel: CoreViewModel,
|
|
|
|
|
settingsViewModel: SettingsViewModel,
|
|
|
|
|
) {
|
|
|
|
|
return (
|
|
|
|
|
<div class="slide-up">
|
|
|
|
|
<h2>{coreViewModel.translations.settings.pages.appearance}</h2>
|
|
|
|
|
<hr></hr>
|
|
|
|
|
{OptionButtonList(
|
|
|
|
|
new React.ListState<[string, ThemeSettings]>([
|
|
|
|
|
[
|
|
|
|
|
coreViewModel.translations.settings.themes.dark,
|
|
|
|
|
ThemeSettings.Dark,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
coreViewModel.translations.settings.themes.light,
|
|
|
|
|
ThemeSettings.Light,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
coreViewModel.translations.settings.themes.system,
|
|
|
|
|
ThemeSettings.System,
|
|
|
|
|
],
|
|
|
|
|
]),
|
|
|
|
|
settingsViewModel.theme,
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|