From bd4369cf29ebbf566a7987547ab91e783bfa0a5e Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Mon, 13 Dec 2021 17:27:06 +0000 Subject: [PATCH] feat(mobx): start implementing theme store --- src/components/common/UpdateIndicator.tsx | 13 ++-- src/components/common/user/UserIcon.tsx | 14 ++-- src/context/Theme.tsx | 48 ++++-------- src/context/index.tsx | 17 ++-- src/mobx/stores/Settings.ts | 61 +++++++++------ src/mobx/stores/helpers/STheme.ts | 94 +++++++++++++++++++++++ src/pages/login/Login.tsx | 14 ++-- src/pages/settings/GenericSettings.tsx | 8 +- src/pages/settings/panes/Appearance.tsx | 50 ++++++------ 9 files changed, 207 insertions(+), 112 deletions(-) create mode 100644 src/mobx/stores/helpers/STheme.ts diff --git a/src/components/common/UpdateIndicator.tsx b/src/components/common/UpdateIndicator.tsx index e4898b4e..cbd003dc 100644 --- a/src/components/common/UpdateIndicator.tsx +++ b/src/components/common/UpdateIndicator.tsx @@ -1,11 +1,11 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { Download, CloudDownload } from "@styled-icons/boxicons-regular"; -import { useContext, useEffect, useState } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; import { internalSubscribe } from "../../lib/eventEmitter"; -import { ThemeContext } from "../../context/Theme"; +import { useApplicationState } from "../../mobx/State"; import IconButton from "../ui/IconButton"; @@ -27,7 +27,7 @@ export default function UpdateIndicator({ style }: Props) { }); if (!pending) return null; - const theme = useContext(ThemeContext); + const theme = useApplicationState().settings.theme; if (style === "titlebar") { return ( @@ -36,7 +36,10 @@ export default function UpdateIndicator({ style }: Props) { content="A new update is available!" placement="bottom">
updateSW(true)}> - +
@@ -47,7 +50,7 @@ export default function UpdateIndicator({ style }: Props) { return ( updateSW(true)}> - + ); } diff --git a/src/components/common/user/UserIcon.tsx b/src/components/common/user/UserIcon.tsx index 13a4911e..595a6760 100644 --- a/src/components/common/user/UserIcon.tsx +++ b/src/components/common/user/UserIcon.tsx @@ -5,12 +5,10 @@ import { useParams } from "react-router-dom"; import { Masquerade } from "revolt-api/types/Channels"; import { Presence } from "revolt-api/types/Users"; import { User } from "revolt.js/dist/maps/Users"; -import { Nullable } from "revolt.js/dist/util/null"; import styled, { css } from "styled-components"; -import { useContext } from "preact/hooks"; +import { useApplicationState } from "../../../mobx/State"; -import { ThemeContext } from "../../../context/Theme"; import { useClient } from "../../../context/revoltjs/RevoltClient"; import fallback from "../assets/user.png"; @@ -26,15 +24,15 @@ interface Props extends IconBaseProps { } export function useStatusColour(user?: User) { - const theme = useContext(ThemeContext); + const theme = useApplicationState().settings.theme; return user?.online && user?.status?.presence !== Presence.Invisible ? user?.status?.presence === Presence.Idle - ? theme["status-away"] + ? theme.getVariable("status-away") : user?.status?.presence === Presence.Busy - ? theme["status-busy"] - : theme["status-online"] - : theme["status-invisible"]; + ? theme.getVariable("status-busy") + : theme.getVariable("status-online") + : theme.getVariable("status-invisible"); } const VoiceIndicator = styled.div<{ status: VoiceStatus }>` diff --git a/src/context/Theme.tsx b/src/context/Theme.tsx index 263d939d..cd6edfb7 100644 --- a/src/context/Theme.tsx +++ b/src/context/Theme.tsx @@ -6,9 +6,6 @@ import { useEffect } from "preact/hooks"; import { useApplicationState } from "../mobx/State"; import { getState } from "../redux"; -import { connectState } from "../redux/connector"; - -import { Children } from "../types/Preact"; export type Variables = | "accent" @@ -66,9 +63,11 @@ export type MonospaceFonts = | "Ubuntu Mono" | "JetBrains Mono"; -export type Theme = { +export type Overrides = { [variable in Variables]: string; -} & { +}; + +export type Theme = Overrides & { light?: boolean; font?: Fonts; css?: string; @@ -228,7 +227,6 @@ export const DEFAULT_MONO_FONT = "Fira Code"; // Generated from https://gitlab.insrt.uk/revolt/community/themes export const PRESETS: Record = { light: { - light: true, accent: "#FD6671", background: "#F6F6F6", foreground: "#000000", @@ -255,7 +253,6 @@ export const PRESETS: Record = { "status-invisible": "#A5A5A5", }, dark: { - light: false, accent: "#FD6671", background: "#191919", foreground: "#F6F6F6", @@ -319,33 +316,22 @@ export const generateVariables = (theme: Theme) => { }); }; -// Load the default default them and apply extras later -export const ThemeContext = createContext(PRESETS["dark"]); - -interface Props { - children: Children; -} - -export default function Theme({ children }: Props) { +export default function Theme() { const settings = useApplicationState().settings; - - const theme: Theme = { - ...getBaseTheme(settings.get("appearance:theme:base") ?? "dark"), - ...settings.get("appearance:theme:custom"), - }; + const theme = settings.theme; const root = document.documentElement.style; useEffect(() => { - const font = theme.font ?? DEFAULT_FONT; + const font = theme.getFont() ?? DEFAULT_FONT; root.setProperty("--font", `"${font}"`); FONTS[font].load(); - }, [root, theme.font]); + }, [root, theme.getFont()]); useEffect(() => { - const font = theme.monospaceFont ?? DEFAULT_MONO_FONT; + const font = theme.getMonospaceFont() ?? DEFAULT_MONO_FONT; root.setProperty("--monospace-font", `"${font}"`); MONOSPACE_FONTS[font].load(); - }, [root, theme.monospaceFont]); + }, [root, theme.getMonospaceFont()]); useEffect(() => { root.setProperty( @@ -363,16 +349,14 @@ export default function Theme({ children }: Props) { return () => window.removeEventListener("resize", resize); }, [root]); + const variables = theme.getVariables(); return ( - + <> - + - - {theme.css && ( -