chore: update

pull/4824/head
Johnny 3 weeks ago
parent 9086e199d3
commit 36b5627ec3

@ -5,7 +5,7 @@ import { Outlet } from "react-router-dom";
import { getSystemColorScheme } from "./helpers/utils"; import { getSystemColorScheme } from "./helpers/utils";
import useNavigateTo from "./hooks/useNavigateTo"; import useNavigateTo from "./hooks/useNavigateTo";
import { userStore, workspaceStore } from "./store/v2"; import { userStore, workspaceStore } from "./store/v2";
import { loadTheme, validateTheme, getStoredTheme, loadStoredThemeSync } from "./utils/theme"; import { loadTheme } from "./utils/theme";
const App = observer(() => { const App = observer(() => {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
@ -15,11 +15,6 @@ const App = observer(() => {
const userSetting = userStore.state.userSetting; const userSetting = userStore.state.userSetting;
const workspaceGeneralSetting = workspaceStore.state.generalSetting; const workspaceGeneralSetting = workspaceStore.state.generalSetting;
// Load theme immediately from localStorage to prevent flickering
useEffect(() => {
loadStoredThemeSync();
}, []);
// Redirect to sign up page if no instance owner. // Redirect to sign up page if no instance owner.
useEffect(() => { useEffect(() => {
if (!workspaceProfile.owner) { if (!workspaceProfile.owner) {
@ -111,16 +106,7 @@ const App = observer(() => {
// Load theme when workspace setting changes, validate API response // Load theme when workspace setting changes, validate API response
useEffect(() => { useEffect(() => {
const theme = workspaceGeneralSetting.theme; loadTheme(workspaceGeneralSetting.theme);
if (theme) {
// Validate theme.
const validatedTheme = validateTheme(theme);
// Only load if different from current stored theme
const currentTheme = getStoredTheme();
if (validatedTheme !== currentTheme) {
loadTheme(validatedTheme);
}
}
}, [workspaceGeneralSetting.theme]); }, [workspaceGeneralSetting.theme]);
return <Outlet />; return <Outlet />;

@ -6,7 +6,8 @@ import { cn } from "@/lib/utils";
const DropdownMenu = React.forwardRef< const DropdownMenu = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Root>, React.ElementRef<typeof DropdownMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root>
>(({ ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
>(({ ...props }, _ref) => {
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />; return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
}); });
DropdownMenu.displayName = "DropdownMenu"; DropdownMenu.displayName = "DropdownMenu";

@ -5,7 +5,8 @@ import { cn } from "@/lib/utils";
const Popover = React.forwardRef< const Popover = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Root>, React.ElementRef<typeof PopoverPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root> React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Root>
>(({ ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
>(({ ...props }, _ref) => {
return <PopoverPrimitive.Root data-slot="popover" {...props} />; return <PopoverPrimitive.Root data-slot="popover" {...props} />;
}); });
Popover.displayName = "Popover"; Popover.displayName = "Popover";

@ -4,7 +4,8 @@ import * as React from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const Sheet = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Root>, React.ComponentPropsWithoutRef<typeof SheetPrimitive.Root>>( const Sheet = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Root>, React.ComponentPropsWithoutRef<typeof SheetPrimitive.Root>>(
({ ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
({ ...props }, _ref) => {
return <SheetPrimitive.Root data-slot="sheet" {...props} />; return <SheetPrimitive.Root data-slot="sheet" {...props} />;
}, },
); );

@ -5,7 +5,8 @@ import { cn } from "@/lib/utils";
const TooltipProvider = React.forwardRef< const TooltipProvider = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Provider>, React.ElementRef<typeof TooltipPrimitive.Provider>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider> React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>
>(({ delayDuration = 0, ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
>(({ delayDuration = 0, ...props }, _ref) => {
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />; return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />;
}); });
TooltipProvider.displayName = "TooltipProvider"; TooltipProvider.displayName = "TooltipProvider";
@ -13,7 +14,8 @@ TooltipProvider.displayName = "TooltipProvider";
const Tooltip = React.forwardRef< const Tooltip = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Root>, React.ElementRef<typeof TooltipPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>
>(({ ...props }) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
>(({ ...props }, _ref) => {
return ( return (
<TooltipProvider> <TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} /> <TooltipPrimitive.Root data-slot="tooltip" {...props} />

@ -1,5 +1,6 @@
@import "tailwindcss"; @import "tailwindcss";
@import "tw-animate-css"; @import "tw-animate-css";
@import "./themes/default.css";
@custom-variant dark (&: is(.dark *)); @custom-variant dark (&: is(.dark *));

@ -1,5 +0,0 @@
// Theme configuration for Tailwind CSS v4
// This file is kept for compatibility but no longer used for MUI theme configuration
// All styling is now handled by Tailwind CSS
export default {};

@ -1,74 +1,42 @@
import paperThemeContent from "../themes/paper.css?raw";
const VALID_THEMES = ["default", "paper"] as const; const VALID_THEMES = ["default", "paper"] as const;
type ValidTheme = (typeof VALID_THEMES)[number]; type ValidTheme = (typeof VALID_THEMES)[number];
// Validate theme name and return default if invalid const THEME_CONTENT: Record<ValidTheme, string | null> = {
export const validateTheme = (theme: string): ValidTheme => { default: null,
return VALID_THEMES.includes(theme as ValidTheme) ? (theme as ValidTheme) : "default"; paper: paperThemeContent,
}; };
// Get theme from localStorage const validateTheme = (theme: string): ValidTheme => {
export const getStoredTheme = (): ValidTheme => { return VALID_THEMES.includes(theme as ValidTheme) ? (theme as ValidTheme) : "default";
try {
const stored = localStorage.getItem("workspace-theme");
return stored ? validateTheme(stored) : "default";
} catch {
return "default";
}
};
// Save theme to localStorage
export const storeTheme = (theme: string): void => {
try {
const validTheme = validateTheme(theme);
localStorage.setItem("workspace-theme", validTheme);
} catch {
// Silently fail if localStorage is not available
}
}; };
// Load theme immediately from localStorage to prevent flickering export const getStoredTheme = (): ValidTheme => {
export const loadStoredThemeSync = (): void => { const stored = localStorage.getItem("workspace-theme");
const theme = getStoredTheme(); return stored ? validateTheme(stored) : "default";
// Apply theme synchronously to prevent flash
document.documentElement.setAttribute("data-theme", theme);
}; };
// Async theme loader export const loadTheme = (themeName: string): void => {
export const loadTheme = async (themeName: string): Promise<void> => {
const validTheme = validateTheme(themeName); const validTheme = validateTheme(themeName);
// Store theme for next page load // Store theme
storeTheme(validTheme); localStorage.setItem("workspace-theme", validTheme);
// Remove existing theme // Remove existing theme
const existingTheme = document.getElementById("workspace-theme"); document.getElementById("workspace-theme")?.remove();
if (existingTheme) {
existingTheme.remove(); // Apply theme (skip for default)
} if (validTheme !== "default") {
const css = THEME_CONTENT[validTheme];
try { if (css) {
// Load theme CSS const style = document.createElement("style");
const response = await fetch(`/themes/${validTheme}.css`); style.id = "workspace-theme";
if (!response.ok) { style.textContent = css;
throw new Error(`Failed to load theme: ${response.status}`); document.head.appendChild(style);
}
const css = await response.text();
// Apply theme
const styleElement = document.createElement("style");
styleElement.id = "workspace-theme";
styleElement.textContent = css;
document.head.appendChild(styleElement);
// Update data attribute
document.documentElement.setAttribute("data-theme", validTheme);
} catch (error) {
console.error("Failed to load theme:", error);
// Fallback to default theme if current theme fails
if (validTheme !== "default") {
await loadTheme("default");
} }
} }
// Set data attribute
document.documentElement.setAttribute("data-theme", validTheme);
}; };

Loading…
Cancel
Save