Skip to content

Commit

Permalink
fix(front): fix problem with userStyle being overwritten when preset …
Browse files Browse the repository at this point in the history
…is selected
  • Loading branch information
SARDONYX-sard committed Oct 9, 2023
1 parent 5ecd48e commit 680ef30
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 20 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/pages/converter.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"use client";

import { ConvertForm } from "@/components/form";
import { useDynStyle, useToastLimit } from "@/hooks";
import { useDynStyleWithStorage, useToastLimit } from "@/hooks";
import { Box } from "@mui/material";
import { Toaster } from "react-hot-toast";

export default function Converter() {
useToastLimit(1);
useDynStyle();
useDynStyleWithStorage();

return (
<>
Expand Down
37 changes: 25 additions & 12 deletions frontend/src/components/style_list.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import MenuItem from "@mui/material/MenuItem";
import Select from "@mui/material/Select";
import { useState } from "react";
import { useEffect } from "react";
import { useStorageState } from "@/hooks";

function selectSample(select: string) {
function selectPreset(select: string) {
switch (select) {
case "1":
case "2":
return select;
default:
return "unknown";
return "0";
}
}

Expand All @@ -17,33 +18,45 @@ type Props = {
};

export const SelectStyleList = ({ setStyle }: Props) => {
const [sample, setSample] = useState("unknown");
const [preset, setPreset] = useStorageState("presetNumber", "0");

useEffect(() => {
const presetNumber = selectPreset(
localStorage.getItem("presetNumber") ?? ""
);
if (presetNumber === "0") {
setStyle(localStorage.getItem("customCSS") ?? "");
} else {
setStyle(presetStyles[presetNumber]);
}
}, [setStyle]);

return (
<>
<Select
name={sample}
name={preset}
onChange={(e) => {
const style = selectSample(e.target.value);
setSample(e.target.value);
if (style === "unknown") {
const presetNumber = selectPreset(e.target.value);
setPreset(presetNumber);
if (presetNumber === "0") {
setStyle(localStorage.getItem("customCSS") ?? "");
return;
}
setStyle(sampleStyles[style]);
setStyle(presetStyles[presetNumber]);
}}
labelId="style-select-label"
id="style-select"
value={sample}
value={preset}
>
<MenuItem value={"unknown"}>Yourself CSS</MenuItem>
<MenuItem value={"0"}>Yourself CSS</MenuItem>
<MenuItem value={"1"}>Preset1</MenuItem>
<MenuItem value={"2"}>Preset2</MenuItem>
</Select>
</>
);
};

const sampleStyles = {
const presetStyles = {
"1": `body {
background-attachment: fixed;
background-image: url("https://i.redd.it/red-forest-1920-1080-v0-s9u8ki2rr70a1.jpg?s=139edf608c428656505a143635a0687dec086229");
Expand Down
26 changes: 24 additions & 2 deletions frontend/src/hooks/dyn_style.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
import { useInsertionEffect } from "react";
import { useInsertionEffect, useState } from "react";
import { useStorageState } from "@/hooks";

/**
* Inject CSS dynamically on the client side. & auto set local storage
* # NOTE
* Frequent style recalculation is inevitable,
* but this hook can solve the delay problem caused by style injection lifecycle discrepancies.
* - See: [useInsertionEffect](https://react.dev/reference/react/useInsertionEffect)
*/
export function useDynStyleWithStorage() {
const [style, setStyle] = useStorageState("customCSS");

useInsertionEffect(() => {
const styleElement = document.createElement("style");
styleElement.innerHTML = style;
document.head.appendChild(styleElement);
return () => {
document.head.removeChild(styleElement);
};
}, [style]);

return [style, setStyle] as const;
}

/**
* Inject CSS dynamically on the client side.
* # NOTE
Expand All @@ -9,7 +31,7 @@ import { useStorageState } from "@/hooks";
* - See: [useInsertionEffect](https://react.dev/reference/react/useInsertionEffect)
*/
export function useDynStyle() {
const [style, setStyle] = useStorageState("customCSS");
const [style, setStyle] = useState("");

useInsertionEffect(() => {
const styleElement = document.createElement("style");
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { useStorageState } from "./storage_state";
export { useDynStyle } from "./dyn_style";
export { useDynStyleWithStorage, useDynStyle } from "./dyn_style";
export { useToastLimit } from "./toasts_limit";
8 changes: 5 additions & 3 deletions frontend/src/hooks/storage_state.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useState } from "react";

const getCacheStr = (cacheKey: string) => localStorage.getItem(cacheKey) ?? "";
const getCacheStr = (cacheKey: string, initialState: string) =>
localStorage.getItem(cacheKey) ?? initialState;

/**
* useState with localStorage
* @param keyName
* @param fallbackState - if localStorage.getItem is returned null, then use.
*/
export function useStorageState(keyName: string) {
const [value, setValue] = useState(getCacheStr(keyName));
export function useStorageState(keyName: string, fallbackState = "") {
const [value, setValue] = useState(getCacheStr(keyName, fallbackState));

const setState = (value_: string) => {
localStorage.setItem(keyName, value_);
Expand Down

0 comments on commit 680ef30

Please sign in to comment.