mirror of https://github.com/usememos/memos.git
Merge a284053831 into 5f57f48673
This commit is contained in:
commit
f028bcb001
|
|
@ -1,6 +1,8 @@
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { useState } from "react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { workspaceStore } from "@/store";
|
import { workspaceStore } from "@/store";
|
||||||
|
import { loadTheme } from "@/utils/theme";
|
||||||
import LocaleSelect from "./LocaleSelect";
|
import LocaleSelect from "./LocaleSelect";
|
||||||
import ThemeSelect from "./ThemeSelect";
|
import ThemeSelect from "./ThemeSelect";
|
||||||
|
|
||||||
|
|
@ -9,10 +11,22 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AuthFooter = observer(({ className }: Props) => {
|
const AuthFooter = observer(({ className }: Props) => {
|
||||||
|
// Local state for login page theme since we can't persist to server
|
||||||
|
const [localTheme, setLocalTheme] = useState(workspaceStore.state.theme || "default");
|
||||||
|
|
||||||
|
const handleThemeChange = (theme: string) => {
|
||||||
|
// Update local state
|
||||||
|
setLocalTheme(theme);
|
||||||
|
// Update workspace store for immediate UI feedback
|
||||||
|
workspaceStore.state.setPartial({ theme });
|
||||||
|
// Apply theme to DOM
|
||||||
|
loadTheme(theme);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn("mt-4 flex flex-row items-center justify-center w-full gap-2", className)}>
|
<div className={cn("mt-4 flex flex-row items-center justify-center w-full gap-2", className)}>
|
||||||
<LocaleSelect value={workspaceStore.state.locale} onChange={(locale) => workspaceStore.state.setPartial({ locale })} />
|
<LocaleSelect value={workspaceStore.state.locale} onChange={(locale) => workspaceStore.state.setPartial({ locale })} />
|
||||||
<ThemeSelect value={workspaceStore.state.theme} onValueChange={(theme) => workspaceStore.state.setPartial({ theme })} />
|
<ThemeSelect value={localTheme} onValueChange={handleThemeChange} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,10 @@ const PreferencesSection = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full flex flex-row justify-between items-center">
|
<div className="w-full flex flex-row justify-between items-center">
|
||||||
<span>{t("setting.preference-section.theme")}</span>
|
<div className="flex flex-col">
|
||||||
|
<span>{t("setting.preference-section.theme")}</span>
|
||||||
|
<span className="text-xs text-muted-foreground">Your personal theme preference (overrides default)</span>
|
||||||
|
</div>
|
||||||
<ThemeSelect value={setting.theme} onValueChange={handleThemeChange} />
|
<ThemeSelect value={setting.theme} onValueChange={handleThemeChange} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,10 @@ const WorkspaceSection = observer(() => {
|
||||||
<Separator />
|
<Separator />
|
||||||
<p className="font-medium text-foreground">{t("setting.system-section.title")}</p>
|
<p className="font-medium text-foreground">{t("setting.system-section.title")}</p>
|
||||||
<div className="w-full flex flex-row justify-between items-center">
|
<div className="w-full flex flex-row justify-between items-center">
|
||||||
<span>Theme</span>
|
<div className="flex flex-col">
|
||||||
|
<span>Default Theme</span>
|
||||||
|
<span className="text-xs text-muted-foreground">Sets the default theme for all users</span>
|
||||||
|
</div>
|
||||||
<ThemeSelect
|
<ThemeSelect
|
||||||
value={workspaceGeneralSetting.theme || "default"}
|
value={workspaceGeneralSetting.theme || "default"}
|
||||||
onValueChange={(value: string) => updatePartialSetting({ theme: value })}
|
onValueChange={(value: string) => updatePartialSetting({ theme: value })}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
import { Moon, Palette, Sun, Wallpaper } from "lucide-react";
|
import { Moon, Palette, Sun, Wallpaper } from "lucide-react";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { workspaceStore } from "@/store";
|
import { workspaceStore, userStore } from "@/store";
|
||||||
import { THEME_OPTIONS } from "@/utils/theme";
|
import { THEME_OPTIONS } from "@/utils/theme";
|
||||||
|
|
||||||
interface ThemeSelectProps {
|
interface ThemeSelectProps {
|
||||||
value?: string;
|
value?: string;
|
||||||
onValueChange?: (theme: string) => void;
|
onValueChange?: (theme: string) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
showEffectiveTheme?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const THEME_ICONS: Record<string, JSX.Element> = {
|
const THEME_ICONS: Record<string, JSX.Element> = {
|
||||||
|
|
@ -16,8 +18,13 @@ const THEME_ICONS: Record<string, JSX.Element> = {
|
||||||
whitewall: <Wallpaper className="w-4 h-4" />,
|
whitewall: <Wallpaper className="w-4 h-4" />,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThemeSelect = ({ value, onValueChange, className }: ThemeSelectProps = {}) => {
|
const ThemeSelect = observer(({ value, onValueChange, className, showEffectiveTheme = false }: ThemeSelectProps = {}) => {
|
||||||
const currentTheme = value || workspaceStore.state.theme || "default";
|
const currentTheme = value || workspaceStore.state.theme || "default";
|
||||||
|
|
||||||
|
// Calculate effective theme (user preference overrides workspace default)
|
||||||
|
const effectiveTheme = userStore.state.userGeneralSetting?.theme || workspaceStore.state.theme || "default";
|
||||||
|
|
||||||
|
const displayTheme = showEffectiveTheme ? effectiveTheme : currentTheme;
|
||||||
|
|
||||||
const handleThemeChange = (newTheme: Theme) => {
|
const handleThemeChange = (newTheme: Theme) => {
|
||||||
if (onValueChange) {
|
if (onValueChange) {
|
||||||
|
|
@ -32,6 +39,9 @@ const ThemeSelect = ({ value, onValueChange, className }: ThemeSelectProps = {})
|
||||||
<SelectTrigger className={className}>
|
<SelectTrigger className={className}>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<SelectValue placeholder="Select theme" />
|
<SelectValue placeholder="Select theme" />
|
||||||
|
{showEffectiveTheme && effectiveTheme !== currentTheme && (
|
||||||
|
<span className="text-xs text-muted-foreground">(effective: {effectiveTheme})</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|
@ -40,12 +50,15 @@ const ThemeSelect = ({ value, onValueChange, className }: ThemeSelectProps = {})
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{THEME_ICONS[option.value]}
|
{THEME_ICONS[option.value]}
|
||||||
<span>{option.label}</span>
|
<span>{option.label}</span>
|
||||||
|
{showEffectiveTheme && option.value === effectiveTheme && (
|
||||||
|
<span className="text-xs text-green-600">✓</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default ThemeSelect;
|
export default ThemeSelect;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue