Skip to content

Commit

Permalink
Smaller fixes after merging mode switch
Browse files Browse the repository at this point in the history
  • Loading branch information
forman committed Nov 29, 2024
1 parent 0871273 commit 5486b48
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 30 deletions.
10 changes: 5 additions & 5 deletions src/components/SettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
TimeSeriesChartType,
TimeAnimationInterval,
THEME_LABELS,
ThemeName,
ThemeMode,
} from "@/states/controlState";
import { GEOGRAPHIC_CRS, WEB_MERCATOR_CRS } from "@/model/proj";
import {
Expand Down Expand Up @@ -241,11 +241,11 @@ const SettingsDialog: React.FC<SettingsDialogProps> = ({
openDialog("userOverlays");
};

function handleApplicationThemeChange(
function handleThemeModeChange(
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) {
updateSettings({
themeMode: event.target.value as ThemeName,
themeMode: event.target.value as ThemeMode,
});
}
const overlayLayer = findLayer(overlayLayers, settings.selectedOverlayId);
Expand Down Expand Up @@ -294,8 +294,8 @@ const SettingsDialog: React.FC<SettingsDialogProps> = ({
variant="standard"
select
sx={styles.textField}
value={theme.palette.mode}
onChange={handleApplicationThemeChange}
value={settings.themeMode || theme.palette.mode}
onChange={handleThemeModeChange}
margin="normal"
>
{THEME_LABELS.map(([value, label]) => (
Expand Down
21 changes: 8 additions & 13 deletions src/connected/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import * as React from "react";
import { connect } from "react-redux";
import {
type PaletteMode,
createTheme,
CssBaseline,
StyledEngineProvider,
Expand All @@ -34,6 +35,7 @@ import {

import { Config } from "@/config";
import { AppState } from "@/states/appState";
import { getPaletteMode, ThemeMode } from "@/states/controlState";
import AuthWrapper from "@/components/AuthWrapper";
import AppBar from "./AppBar";
import AppPane from "./AppPane";
Expand All @@ -49,33 +51,26 @@ import UserVariablesDialog from "./UserVariablesDialog";

interface AppProps {
compact: boolean;
themeMode: string;
themeMode: ThemeMode;
}

// noinspection JSUnusedLocalSymbols
const mapStateToProps = (_state: AppState) => {
const mapStateToProps = (state: AppState) => {
return {
compact: Config.instance.branding.compact,
themeMode: _state.controlState.themeMode,
themeMode: state.controlState.themeMode,
};
};

const mapDispatchToProps = {};

const _App: React.FC<AppProps> = ({ compact, themeMode }) => {
const systemMode = useMediaQuery("(prefers-color-scheme: dark)")
const systemThemeMode = useMediaQuery("(prefers-color-scheme: dark)")
? "dark"
: "light";

// Validate and fallback for themeMode
const validatedThemeMode =
themeMode === "light" || themeMode === "dark" || themeMode === "system"
? themeMode
: "dark";

const theme = React.useMemo(() => {
const mode =
validatedThemeMode === "system" ? systemMode : validatedThemeMode;
const mode: PaletteMode = getPaletteMode(themeMode, systemThemeMode);

return createTheme({
typography: {
Expand All @@ -88,7 +83,7 @@ const _App: React.FC<AppProps> = ({ compact, themeMode }) => {
secondary: Config.instance.branding.secondaryColor,
},
});
}, [validatedThemeMode, systemMode]);
}, [themeMode, systemThemeMode]);

return (
<AuthWrapper>
Expand Down
7 changes: 7 additions & 0 deletions src/ext/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
selectedVariable2NameSelector,
selectedVariableNameSelector,
} from "@/selectors/controlSelectors";
import { getPaletteMode } from "@/states/controlState";

export interface DerivedStateProperty {
type: string;
Expand Down Expand Up @@ -51,6 +52,12 @@ export const derivedStateProperties: Record<string, DerivedStateProperty> = {
description: "The currently selected UTC time using ISO format.",
selector: selectedDatasetTimeLabelSelector,
},
themeMode: {
type: "str",
description: 'The appearance mode of the UI. Either "light" or "dark".',
selector: (appState: AppState) =>
getPaletteMode(appState.controlState.themeMode),
},
};

export function newDerivedStore(store: Store<AppState>): HostStore {
Expand Down
3 changes: 2 additions & 1 deletion src/resources/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
"appBarTitle": "xcube Viewer",
"windowTitle": "xcube Viewer",
"windowIcon": null,
"headerBackgroundColor": "DimGray",
"compact": false,
"themeName": "light",
"themeMode": "system",
"primaryColor": "blue",
"secondaryColor": "pink",
"organisationUrl": "https://xcube.readthedocs.io/",
Expand Down
4 changes: 2 additions & 2 deletions src/resources/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@
"type": ["string", "null"],
"examples": ["images/favicon.ico"]
},
"themeName": {
"themeMode": {
"type": "string",
"examples": ["light"],
"enum": ["dark", "light"]
"enum": ["dark", "light", "system"]
},
"primaryColor": { "$ref": "#/definitions/ColorSchema" },
"secondaryColor": { "$ref": "#/definitions/ColorSchema" },
Expand Down
32 changes: 24 additions & 8 deletions src/states/controlState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
} from "@/model/user-place/geojson";
import { defaultWktOptions, WktOptions } from "@/model/user-place/wkt";
import { loadUserSettings } from "./userSettings";
import { PaletteMode } from "@mui/material";

export type TimeAnimationInterval = 250 | 500 | 1000 | 2500;
export const TIME_ANIMATION_INTERVALS: TimeAnimationInterval[] = [
Expand Down Expand Up @@ -100,9 +101,9 @@ export const sidebarPanelIds: SidebarPanelId[] = [
"volume",
];

export const THEME_NAMES = ["light", "dark", "system"] as const;
export type ThemeName = (typeof THEME_NAMES)[number];
export const THEME_LABELS: [ThemeName, string][] = [
export type ThemeMode = PaletteMode | "system";
export const THEME_NAMES: ThemeMode[] = ["light", "dark", "system"];
export const THEME_LABELS: [ThemeMode, string][] = [
["light", "Light"],
["dark", "Dark"],
["system", "System"],
Expand Down Expand Up @@ -168,7 +169,7 @@ export interface ControlState {
exportPlacesAsCollection: boolean;
exportZipArchive: boolean;
exportFileName: string;
themeMode: "light" | "dark" | "system";
themeMode: ThemeMode;
}

export function newControlState(): ControlState {
Expand Down Expand Up @@ -249,14 +250,29 @@ export function newControlState(): ControlState {
return loadUserSettings(state);
}

function getInitialThemeMode() {
const themeName = Config.instance.branding.themeName;
if (themeName && ["light", "dark", "system"].includes(themeName)) {
return themeName;
function getInitialThemeMode(): ThemeMode {
const themeMode = Config.instance.branding.themeMode;
if (themeMode && THEME_NAMES.includes(themeMode)) {
return themeMode;
}
return "system";
}

export function getPaletteMode(
themeMode: ThemeMode,
defaultPaletteMode?: PaletteMode,
): PaletteMode {
if (!defaultPaletteMode) {
defaultPaletteMode = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";
}
return themeMode && THEME_NAMES.includes(themeMode) && themeMode !== "system"
? themeMode
: defaultPaletteMode;
}

// We cannot keep "MAP_OBJECTS" in control state object, because these
// objects are (1) not serializable and (2) logging actions will cause
// the browsers to crash
Expand Down
2 changes: 1 addition & 1 deletion src/util/branding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export interface Branding {
windowTitle: string;
windowIcon: string | null;
compact: boolean;
themeName?: PaletteMode | "system";
themeMode?: PaletteMode | "system";
primaryColor: PaletteColorOptions;
secondaryColor: PaletteColorOptions;
headerBackgroundColor?: string;
Expand Down

0 comments on commit 5486b48

Please sign in to comment.