diff --git a/src/App.tsx b/src/App.tsx index cd6fe4f..69249b3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -26,8 +26,6 @@ const TimelineHome = lazy(() => import("./timelines/Home.js")); const Settings = lazy(() => import("./settings/Settings.js")); const TootBottomSheet = lazy(() => import("./timelines/TootBottomSheet.js")); const MotionSettings = lazy(() => import("./settings/Motions.js")); -const LanguageSettings = lazy(() => import("./settings/Language.js")); -const RegionSettings = lazy(() => import("./settings/Region.jsx")); const Routing: Component = () => { return ( @@ -36,8 +34,6 @@ const Routing: Component = () => { - - diff --git a/src/material/BottomSheet.module.css b/src/material/BottomSheet.module.css index 410858b..8f716e9 100644 --- a/src/material/BottomSheet.module.css +++ b/src/material/BottomSheet.module.css @@ -43,7 +43,7 @@ &.animated { position: absolute; - transform: translateY(-50%); + transform: none; overflow: hidden; will-change: width, height, top, left; @@ -54,12 +54,6 @@ & * { overflow: hidden; } - - @media (max-width: 560px) { - & { - transform: none; - } - } } &.bottom { diff --git a/src/material/BottomSheet.tsx b/src/material/BottomSheet.tsx index e753e20..92eabc9 100644 --- a/src/material/BottomSheet.tsx +++ b/src/material/BottomSheet.tsx @@ -36,7 +36,7 @@ function composeAnimationFrame( }; } -const MOVE_SPEED = 1200; +const MOVE_SPEED = 1400; // 1400px/s, bottom sheet is big and a bit heavier than small papers const BottomSheet: ParentComponent = (props) => { let element: HTMLDialogElement; @@ -62,17 +62,13 @@ const BottomSheet: ParentComponent = (props) => { }); const onClose = () => { - const srcElement = hero(); - if (srcElement) { - srcElement.style.visibility = "unset"; - } - + hero()!.style.visibility = 'unset' element.close(); setHero(); }; const animatedClose = () => { - const srcElement = hero(); + const srcElement = hero() const endRect = srcElement?.getBoundingClientRect(); if (endRect) { const startRect = element.getBoundingClientRect(); @@ -80,94 +76,19 @@ const BottomSheet: ParentComponent = (props) => { animation.addEventListener("finish", onClose); animation.addEventListener("cancel", onClose); } else { - if (window.innerWidth > 560 && !props.bottomUp) { - onClose(); - return; - } - const animation = props.bottomUp - ? animateSlideInFromBottom(element, true) - : animateSlideInFromRight(element, true); - animation.addEventListener("finish", onClose); - animation.addEventListener("cancel", onClose); + element.close(); + setHero(); } }; const animatedOpen = () => { element.showModal(); - const srcElement = hero(); + const srcElement = hero() const startRect = srcElement?.getBoundingClientRect(); - if (startRect) { - srcElement!.style.visibility = "hidden"; - const endRect = element.getBoundingClientRect(); - animateHero(startRect, endRect, element); - } else if (props.bottomUp) { - animateSlideInFromBottom(element); - } else if (window.innerWidth <= 560) { - animateSlideInFromRight(element); - } - }; - - const animateSlideInFromRight = (element: HTMLElement, reserve?: boolean) => { - const rect = element.getBoundingClientRect(); - const easing = "cubic-bezier(0.4, 0, 0.2, 1)"; - element.classList.add(styles.animated); - const oldOverflow = document.body.style.overflow; - document.body.style.overflow = "hidden"; - const distance = Math.abs(rect.left - window.innerWidth); - const duration = (distance / MOVE_SPEED) * 1000; - - animation = element.animate( - { - top: [rect.top, rect.top], - left: reserve - ? [`${rect.left}px`, `${window.innerWidth}px`] - : [`${window.innerWidth}px`, `${rect.left}px`], - width: [rect.width, rect.width], - height: [rect.height, rect.height], - }, - { easing, duration }, - ); - const onAnimationEnd = () => { - element.classList.remove(styles.animated); - document.body.style.overflow = oldOverflow; - animation = undefined; - }; - animation.addEventListener("cancel", onAnimationEnd); - animation.addEventListener("finish", onAnimationEnd); - return animation; - }; - - const animateSlideInFromBottom = ( - element: HTMLElement, - reserve?: boolean, - ) => { - const rect = element.getBoundingClientRect(); - const easing = "cubic-bezier(0.4, 0, 0.2, 1)"; - element.classList.add(styles.animated); - const oldOverflow = document.body.style.overflow; - document.body.style.overflow = "hidden"; - const distance = Math.abs(rect.top - window.innerHeight); - const duration = (distance / MOVE_SPEED) * 1000; - - animation = element.animate( - { - left: [rect.left, rect.left], - top: reserve - ? [`${rect.top}px`, `${window.innerHeight}px`] - : [`${window.innerHeight}px`, `${rect.top}px`], - width: [rect.width, rect.width], - height: [rect.height, rect.height], - }, - { easing, duration }, - ); - const onAnimationEnd = () => { - element.classList.remove(styles.animated); - document.body.style.overflow = oldOverflow; - animation = undefined; - }; - animation.addEventListener("cancel", onAnimationEnd); - animation.addEventListener("finish", onAnimationEnd); - return animation; + if (!startRect) return; + srcElement!.style.visibility = 'hidden' + const endRect = element.getBoundingClientRect(); + animateHero(startRect, endRect, element); }; const animateHero = ( diff --git a/src/settings/Language.tsx b/src/settings/ChooseLang.tsx similarity index 73% rename from src/settings/Language.tsx rename to src/settings/ChooseLang.tsx index f04d4b1..ac03c7b 100644 --- a/src/settings/Language.tsx +++ b/src/settings/ChooseLang.tsx @@ -13,7 +13,7 @@ import { Switch, Toolbar, } from "@suid/material"; -import { ArrowBack } from "@suid/icons-material"; +import { Close as CloseIcon } from "@suid/icons-material"; import iso639_1 from "iso-639-1"; import { autoMatchLangTag, @@ -22,12 +22,14 @@ import { } from "../platform/i18n"; import { Title } from "../material/typography"; import type { Template } from "@solid-primitives/i18n"; -import { useStore } from "@nanostores/solid"; -import { $settings } from "./stores"; -import { useNavigate } from "@solidjs/router"; -const ChooseLang: Component = () => { - const navigate = useNavigate() +type ChooseLangProps = { + code?: string; + onCodeChange: (ncode?: string) => void; + onClose?: JSX.EventHandlerUnion; +}; + +const ChooseLang: Component = (props) => { const [t] = createTranslator( () => import("./i18n/lang-names.json"), (code) => @@ -37,9 +39,6 @@ const ChooseLang: Component = () => { }; }>, ); - const settings = useStore($settings) - - const code = () => settings().language const unsupportedLangCodes = createMemo(() => { return iso639_1.getAllCodes().filter((x) => !["zh", "en"].includes(x)); @@ -47,10 +46,6 @@ const ChooseLang: Component = () => { const matchedLangCode = createMemo(() => autoMatchLangTag()); - const onCodeChange = (code?: string) => { - $settings.setKey("language", code) - } - return ( { variant="dense" sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }} > - - + + {t("Choose Language")} @@ -74,7 +69,7 @@ const ChooseLang: Component = () => { > { - onCodeChange(code() ? undefined : matchedLangCode()); + props.onCodeChange(props.code ? undefined : matchedLangCode()); }} > @@ -83,20 +78,20 @@ const ChooseLang: Component = () => { })} - + {t("Supported")}}> - {(c) => ( + {(code) => ( - {t(`lang.${c}`)} + {t(`lang.${code}`)} diff --git a/src/settings/Region.tsx b/src/settings/ChooseRegion.tsx similarity index 66% rename from src/settings/Region.tsx rename to src/settings/ChooseRegion.tsx index 1ae1a62..77a969e 100644 --- a/src/settings/Region.tsx +++ b/src/settings/ChooseRegion.tsx @@ -12,7 +12,8 @@ import { Switch, Toolbar, } from "@suid/material"; -import { ArrowBack } from "@suid/icons-material"; +import { Close as CloseIcon } from "@suid/icons-material"; +import iso639_1 from "iso-639-1"; import { autoMatchRegion, createTranslator, @@ -20,12 +21,14 @@ import { } from "../platform/i18n"; import { Title } from "../material/typography"; import type { Template } from "@solid-primitives/i18n"; -import { useNavigate } from "@solidjs/router"; -import { $settings } from "./stores"; -import { useStore } from "@nanostores/solid"; -const ChooseRegion: Component = () => { - const navigate = useNavigate(); +type ChooseRegionProps = { + code?: string; + onCodeChange: (ncode?: string) => void; + onClose?: JSX.EventHandlerUnion; +}; + +const ChooseRegion: Component = (props) => { const [t] = createTranslator( () => import("./i18n/lang-names.json"), (code) => @@ -36,16 +39,12 @@ const ChooseRegion: Component = () => { }>, ); - const settings = useStore($settings); - - const region = () => settings().region; + const unsupportedLangCodes = createMemo(() => { + return iso639_1.getAllCodes().filter((x) => !["zh", "en"].includes(x)); + }); const matchedRegionCode = createMemo(() => autoMatchRegion()); - const onCodeChange = (code?: string) => { - $settings.setKey("region", code); - }; - return ( { variant="dense" sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }} > - - + + {t("Choose Language")} @@ -69,17 +68,16 @@ const ChooseRegion: Component = () => { > { - onCodeChange(region() ? undefined : matchedRegionCode()); + props.onCodeChange(props.code ? undefined : matchedRegionCode()); }} > {t("region.auto", { - detected: - t(`region.${matchedRegionCode()}`) ?? matchedRegionCode(), + detected: t(`region.${matchedRegionCode()}`) ?? matchedRegionCode(), })} - + @@ -87,16 +85,13 @@ const ChooseRegion: Component = () => { {(code) => ( {t(`region.${code}`)} diff --git a/src/settings/Motions.tsx b/src/settings/Motions.tsx index a90bd44..2f111fd 100644 --- a/src/settings/Motions.tsx +++ b/src/settings/Motions.tsx @@ -14,7 +14,7 @@ import { } from "@suid/material"; import { Title } from "../material/typography"; import { useNavigate } from "@solidjs/router"; -import { ArrowBack } from "@suid/icons-material"; +import { Close as CloseIcon } from "@suid/icons-material"; import { createTranslator } from "../platform/i18n"; import { useStore } from "@nanostores/solid"; import { $settings } from "./stores"; @@ -37,7 +37,7 @@ const Motions: Component = () => { sx={{ paddingTop: "var(--safe-area-inset-top, 0px)" }} > - + {t("motions")} diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 826fea9..e27443a 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -41,10 +41,15 @@ import { autoMatchLangTag, autoMatchRegion, createTranslator, + SUPPORTED_LANGS, + SUPPORTED_REGIONS, useDateFnLocale, } from "../platform/i18n.jsx"; import { type Template } from "@solid-primitives/i18n"; import BottomSheet from "../material/BottomSheet.jsx"; +import ChooseLang from "./ChooseLang.jsx"; +import ChooseRegion from "./ChooseRegion.jsx"; +import { Portal } from "solid-js/web"; type Strings = { ["lang.auto"]: Template<{ detected: string }>; @@ -64,6 +69,8 @@ const Settings: ParentComponent = (props) => { needRefresh: [needRefresh], } = useRegisterSW(); const dateFnLocale = useDateFnLocale(); + const [langPickerOpen, setLangPickerOpen] = createSignal(false); + const [regionPickerOpen, setRegionPickerOpen] = createSignal(false); const [profiles] = useSignedInProfiles(); @@ -168,7 +175,7 @@ const Settings: ParentComponent = (props) => {
  • {t("This Application")} - + @@ -185,8 +192,15 @@ const Settings: ParentComponent = (props) => { {t("Language")} + + $settings.setKey("language", nval)} + onClose={[setLangPickerOpen, false]} + /> + - + @@ -203,6 +217,13 @@ const Settings: ParentComponent = (props) => { {t("Region")} + + $settings.setKey("region", nval)} + onClose={[setRegionPickerOpen, false]} + /> +