feat(mobx): continue implementing themes; performance work on settings

This commit is contained in:
Paul Makles
2021-12-13 17:27:30 +00:00
parent bd4369cf29
commit 65be047dc6
15 changed files with 497 additions and 287 deletions

View File

@@ -1,61 +1,50 @@
import { Reset, Import } from "@styled-icons/boxicons-regular";
import { Pencil, Store } from "@styled-icons/boxicons-solid";
import { Link } from "react-router-dom";
import { Pencil } from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
// @ts-expect-error shade-blend-color does not have typings.
import pSBC from "shade-blend-color";
import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { useCallback, useContext, useEffect, useState } from "preact/hooks";
import { useCallback, useEffect, useState } from "preact/hooks";
import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
import { debounce } from "../../../lib/debounce";
import { useApplicationState } from "../../../mobx/State";
import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import { isExperimentEnabled } from "../../../redux/reducers/experiments";
import { EmojiPacks, Settings } from "../../../redux/reducers/settings";
import {
DEFAULT_FONT,
DEFAULT_MONO_FONT,
Fonts,
FONTS,
FONT_KEYS,
MonospaceFonts,
MONOSPACE_FONTS,
MONOSPACE_FONT_KEYS,
Theme,
ThemeOptions,
} from "../../../context/Theme";
import { Theme, ThemeOptions } from "../../../context/Theme";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import CollapsibleSection from "../../../components/common/CollapsibleSection";
import Tooltip from "../../../components/common/Tooltip";
import Button from "../../../components/ui/Button";
import Checkbox from "../../../components/ui/Checkbox";
import ColourSwatches from "../../../components/ui/ColourSwatches";
import ComboBox from "../../../components/ui/ComboBox";
import InputBox from "../../../components/ui/InputBox";
import CategoryButton from "../../../components/ui/fluent/CategoryButton";
import darkSVG from "../assets/dark.svg";
import lightSVG from "../assets/light.svg";
import mutantSVG from "../assets/mutant_emoji.svg";
import notoSVG from "../assets/noto_emoji.svg";
import openmojiSVG from "../assets/openmoji_emoji.svg";
import twemojiSVG from "../assets/twemoji_emoji.svg";
import {
ThemeBaseSelectorShim,
ThemeShopShim,
ThemeAccentShim,
DisplayCompactShim,
DisplayFontShim,
DisplayMonospaceFontShim,
DisplayLigaturesShim,
DisplayEmojiShim,
ThemeCustomCSSShim,
} from "../../../components/settings/AppearanceShims";
interface Props {
settings: Settings;
}
// ! FIXME: code needs to be rewritten to fix jittering
export function Component(props: Props) {
const theme = useApplicationState().settings.theme;
export const Component = observer((props: Props) => {
//const theme = useApplicationState().settings.theme;
const { writeClipboard, openScreen } = useIntermediate();
function setTheme(theme: ThemeOptions) {
/*function setTheme(theme: ThemeOptions) {
dispatch({
type: "SETTINGS_SET_THEME",
theme,
@@ -95,191 +84,18 @@ export function Component(props: Props) {
useEffect(() => setOverride({ css }), [setOverride, css]);
const selected = props.settings.theme?.base ?? "dark";
const selected = theme.getBase();*/
return (
<div className={styles.appearance}>
<h3>
<Text id="app.settings.pages.appearance.theme" />
</h3>
<div className={styles.themes}>
<div className={styles.theme}>
<img
loading="eager"
src={lightSVG}
draggable={false}
data-active={selected === "light"}
onClick={() =>
selected !== "light" && setTheme({ base: "light" })
}
onContextMenu={(e) => e.preventDefault()}
/>
<h4>
<Text id="app.settings.pages.appearance.color.light" />
</h4>
</div>
<div className={styles.theme}>
<img
loading="eager"
src={darkSVG}
draggable={false}
data-active={selected === "dark"}
onClick={() =>
selected !== "dark" && setTheme({ base: "dark" })
}
onContextMenu={(e) => e.preventDefault()}
/>
<h4>
<Text id="app.settings.pages.appearance.color.dark" />
</h4>
</div>
</div>
<ThemeBaseSelectorShim />
<ThemeShopShim />
<ThemeAccentShim />
{/*<DisplayCompactShim />
<DisplayFontShim />
<DisplayLigaturesShim />
<DisplayEmojiShim />*/}
{isExperimentEnabled("theme_shop") && (
<Link to="/settings/theme_shop" replace>
<CategoryButton
icon={<Store size={24} />}
action="chevron"
hover>
<Text id="app.settings.pages.theme_shop.title" />
</CategoryButton>
</Link>
)}
<h3>
<Text id="app.settings.pages.appearance.accent_selector" />
</h3>
<ColourSwatches
value={theme.getVariable("accent")}
onChange={setAccent}
/>
{/*<h3>
<Text id="app.settings.pages.appearance.message_display" />
</h3>
<div className={styles.display}>
<Radio
description={
<Text id="app.settings.pages.appearance.display.default_description" />
}
checked
>
<Text id="app.settings.pages.appearance.display.default" />
</Radio>
<Radio
description={
<Text id="app.settings.pages.appearance.display.compact_description" />
}
disabled
>
<Text id="app.settings.pages.appearance.display.compact" />
</Radio>
</div>*/}
<h3>
<Text id="app.settings.pages.appearance.font" />
</h3>
<ComboBox
value={theme.getFont()}
onChange={(e) =>
pushOverride({ font: e.currentTarget.value as Fonts })
}>
{FONT_KEYS.map((key) => (
<option value={key} key={key}>
{FONTS[key as keyof typeof FONTS].name}
</option>
))}
</ComboBox>
{/* TOFIX: Only show when a font with ligature support is selected, i.e.: Inter.*/}
<p>
<Checkbox
checked={props.settings.theme?.ligatures === true}
onChange={() =>
setTheme({
ligatures: !props.settings.theme?.ligatures,
})
}
description={
<Text id="app.settings.pages.appearance.ligatures_desc" />
}>
<Text id="app.settings.pages.appearance.ligatures" />
</Checkbox>
</p>
<h3>
<Text id="app.settings.pages.appearance.emoji_pack" />
</h3>
<div className={styles.emojiPack}>
<div className={styles.row}>
<div>
<div
className={styles.button}
onClick={() => setEmojiPack("mutant")}
data-active={emojiPack === "mutant"}>
<img
loading="eager"
src={mutantSVG}
draggable={false}
onContextMenu={(e) => e.preventDefault()}
/>
</div>
<h4>
Mutant Remix{" "}
<a
href="https://mutant.revolt.chat"
target="_blank"
rel="noreferrer">
(by Revolt)
</a>
</h4>
</div>
<div>
<div
className={styles.button}
onClick={() => setEmojiPack("twemoji")}
data-active={emojiPack === "twemoji"}>
<img
loading="eager"
src={twemojiSVG}
draggable={false}
onContextMenu={(e) => e.preventDefault()}
/>
</div>
<h4>Twemoji</h4>
</div>
</div>
<div className={styles.row}>
<div>
<div
className={styles.button}
onClick={() => setEmojiPack("openmoji")}
data-active={emojiPack === "openmoji"}>
<img
loading="eager"
src={openmojiSVG}
draggable={false}
onContextMenu={(e) => e.preventDefault()}
/>
</div>
<h4>Openmoji</h4>
</div>
<div>
<div
className={styles.button}
onClick={() => setEmojiPack("noto")}
data-active={emojiPack === "noto"}>
<img
loading="eager"
src={notoSVG}
draggable={false}
onContextMenu={(e) => e.preventDefault()}
/>
</div>
<h4>Noto Emoji</h4>
</div>
</div>
</div>
<CollapsibleSection
{/*<CollapsibleSection
defaultValue={false}
id="settings_overrides"
summary={<Text id="app.settings.pages.appearance.overrides" />}>
@@ -300,7 +116,6 @@ export function Component(props: Props) {
onClick={() => writeClipboard(JSON.stringify(theme))}>
<Tooltip content={<Text id="app.special.copy" />}>
{" "}
{/*TOFIX: Try to put the tooltip above the .code div without messing up the css challenge */}
{JSON.stringify(theme)}
</Tooltip>
</div>
@@ -410,48 +225,18 @@ export function Component(props: Props) {
</div>
))}
</div>
</CollapsibleSection>
</CollapsibleSection>*/}
<CollapsibleSection
id="settings_advanced_appearance"
defaultValue={false}
summary={<Text id="app.settings.pages.appearance.advanced" />}>
<h3>
<Text id="app.settings.pages.appearance.mono_font" />
</h3>
<ComboBox
value={theme.getMonospaceFont()}
onChange={(e) =>
pushOverride({
monospaceFont: e.currentTarget
.value as MonospaceFonts,
})
}>
{MONOSPACE_FONT_KEYS.map((key) => (
<option value={key} key={key}>
{
MONOSPACE_FONTS[
key as keyof typeof MONOSPACE_FONTS
].name
}
</option>
))}
</ComboBox>
<h3>
<Text id="app.settings.pages.appearance.custom_css" />
</h3>
<TextAreaAutoSize
maxRows={20}
minHeight={480}
code
value={css}
onChange={(ev) => setCSS(ev.currentTarget.value)}
/>
<DisplayMonospaceFontShim />
<ThemeCustomCSSShim />
</CollapsibleSection>
</div>
);
}
});
export const Appearance = connectState(Component, (state) => {
return {

View File

@@ -150,38 +150,6 @@
}
.appearance {
.theme {
min-width: 0;
display: flex;
flex-direction: column;
}
.themes {
gap: 8px;
display: flex;
width: 100%;
img {
cursor: pointer;
border-radius: var(--border-radius);
transition: border 0.3s;
border: 3px solid transparent;
width: 100%;
&[data-active="true"] {
cursor: default;
border: 3px solid var(--accent);
&:hover {
border: 3px solid var(--accent);
}
}
&:hover {
border: 3px solid var(--tertiary-background);
}
}
}
details {
summary {
font-size: 0.8125rem;