diff --git a/components/MyIcon.tsx b/components/MyIcon.tsx deleted file mode 100644 index c77aa98..0000000 --- a/components/MyIcon.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Component } from "preact"; -import Icon from "preact-material-components/Icon"; - -type Props = { - show: boolean; - icon: string; -}; - -export default class MyIcon extends Component { - render() { - if (!this.props.show) return; - return {this.props.icon}; - } -} diff --git a/islands/Container.tsx b/islands/Container.tsx index 6aff8c6..0ea5b6b 100644 --- a/islands/Container.tsx +++ b/islands/Container.tsx @@ -1,6 +1,6 @@ import { Head } from "$fresh/runtime.ts"; import { Component, ContextType } from "preact"; -import { useEffect, useState } from "preact/hooks"; +import { StateUpdater, useEffect, useState } from "preact/hooks"; import Icon from "preact-material-components/Icon"; import List from "preact-material-components/List"; import TopAppBar from "preact-material-components/TopAppBar"; @@ -11,7 +11,8 @@ import t, { i18n_map, I18NMap } from "../server/i18n.ts"; import TaskManager from "./TaskManager.tsx"; import { initState, set_state } from "../server/state.ts"; import NewTask from "../components/NewTask.tsx"; -import MyIcon from "../components/MyIcon.tsx"; +import { parse_bool } from "../server/parse.ts"; +import Switch from "preact-material-components/Switch"; export type ContainerProps = { i18n: I18NMap; @@ -24,9 +25,24 @@ export default class Container extends Component { i18n_map.value = this.props.i18n; const [display, set_display] = useState(false); const [state, set_state1] = useState("#/"); - const [darkmode, set_darkmode] = useState(false); + const [darkmode, set_darkmode1] = useState(false); + const set_darkmode: StateUpdater = (u) => { + const v = typeof u === "function" ? u(darkmode) : u; + set_darkmode1(v); + localStorage.setItem("darkmode", JSON.stringify(v)); + if (v) { + document.body.classList.add("dark-scheme"); + } else { + document.body.classList.remove("dark-scheme"); + } + }; useEffect(() => { initState(set_state1); + const dm = parse_bool(localStorage.getItem("darkmode"), false); + set_darkmode1(dm); + if (dm) { + document.body.classList.add("dark-scheme"); + } }, []); return (
@@ -47,6 +63,14 @@ export default class Container extends Component { + { + set_darkmode(!darkmode); + }} + /> + {darkmode ? "dark_mode" : "light_mode"} more_vert diff --git a/server/parse.ts b/server/parse.ts new file mode 100644 index 0000000..a1da6e0 --- /dev/null +++ b/server/parse.ts @@ -0,0 +1,13 @@ +export function parse_bool( + value: string | null, + def: T, +): boolean | T { + if (value === null) return def; + const v = value.toLowerCase(); + const n = parseInt(v); + if (isNaN(n)) { + return v === "true"; + } else { + return n !== 0; + } +} diff --git a/static/common.css b/static/common.css index b004239..8876ae0 100644 --- a/static/common.css +++ b/static/common.css @@ -201,3 +201,7 @@ body { .dark-scheme .mdc-notched-outline__idle{ color: white!important; } + +.mdc-top-app-bar__section--align-end > * { + margin: 0 5px; +} diff --git a/translation/en/common.jsonc b/translation/en/common.jsonc index a7dae35..802df9e 100644 --- a/translation/en/common.jsonc +++ b/translation/en/common.jsonc @@ -4,5 +4,6 @@ "reload": "Reload", "save": "Save", "yes": "Yes", - "no": "No" + "no": "No", + "darkmode": "Dark mode" } diff --git a/translation/zh-cn/common.jsonc b/translation/zh-cn/common.jsonc index ade2b6f..2687268 100644 --- a/translation/zh-cn/common.jsonc +++ b/translation/zh-cn/common.jsonc @@ -4,5 +4,6 @@ "reload": "重新加载", "save": "保存", "yes": "是", - "no": "否" + "no": "否", + "darkmode": "夜间模式" }