diff --git a/src/App.tsx b/src/App.tsx
index 16b3cc318..f78b07cb4 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -8,6 +8,7 @@ import { ToastContainer, toast, Slide } from 'react-toastify';
import clsx from 'clsx';
import TitleBar from './window/TitleBar';
+import SettingsPanel from './components/panel/SettingsPanel';
import FolderTree from './components/panel/FolderTree';
import LibraryExportPanel from './components/panel/right/LibraryExportPanel';
import Resizer from './components/ui/Resizer';
@@ -130,6 +131,7 @@ function App() {
rightPanelWidth,
compactEditorPanelHeightOverride,
activeRightPanel,
+ isSettingsOpen,
setUI,
setRightPanel,
} = useUIStore(
@@ -144,6 +146,7 @@ function App() {
rightPanelWidth: state.rightPanelWidth,
compactEditorPanelHeightOverride: state.compactEditorPanelHeightOverride,
activeRightPanel: state.activeRightPanel,
+ isSettingsOpen: state.isSettingsOpen,
setUI: state.setUI,
setRightPanel: state.setRightPanel,
})),
@@ -907,6 +910,26 @@ function App() {
executeDelete={executeDelete}
handleSaveCollage={handleSaveCollage}
/>
+ {isSettingsOpen && appSettings && (
+
+
+
+ setUI({ isSettingsOpen: false })}
+ onLibraryRefresh={handleLibraryRefresh}
+ onSettingsChange={handleSettingsChange}
+ rootPath={rootPath}
+ />
+
+
+
+ )}
{
- const rootStyle = getComputedStyle(document.documentElement);
- const bgPrimaryStr = rootStyle.getPropertyValue('--app-bg-primary') || 'rgb(24, 24, 24)';
- const bgSecondaryStr = rootStyle.getPropertyValue('--app-bg-secondary') || 'rgb(35, 35, 35)';
-
- wgpuStateRef.current = {
- useWgpuRenderer: appSettings?.useWgpuRenderer,
- isReady: selectedImage?.isReady ?? false,
- hasRenderedFirstFrame,
- isCropping,
- uncroppedAdjustedPreviewUrl,
- showOriginal,
- bgPrimary: parseRgb(bgPrimaryStr),
- bgSecondary: parseRgb(bgSecondaryStr),
+ let isCancelled = false;
+ const applyDocumentThemeToWgpuRef = () => {
+ if (isCancelled) return;
+ const rootStyle = getComputedStyle(document.documentElement);
+ const bgPrimaryStr = rootStyle.getPropertyValue('--app-bg-primary') || 'rgb(24, 24, 24)';
+ const bgSecondaryStr = rootStyle.getPropertyValue('--app-bg-secondary') || 'rgb(35, 35, 35)';
+
+ wgpuStateRef.current = {
+ useWgpuRenderer: appSettings?.useWgpuRenderer,
+ isReady: selectedImage?.isReady ?? false,
+ hasRenderedFirstFrame,
+ isCropping,
+ uncroppedAdjustedPreviewUrl,
+ showOriginal,
+ bgPrimary: parseRgb(bgPrimaryStr),
+ bgSecondary: parseRgb(bgSecondaryStr),
+ };
+ };
+ queueMicrotask(applyDocumentThemeToWgpuRef);
+ return () => {
+ isCancelled = true;
};
}, [
appSettings?.useWgpuRenderer,
diff --git a/src/components/panel/SettingsPanel.tsx b/src/components/panel/SettingsPanel.tsx
index a9140f877..e017d34b6 100644
--- a/src/components/panel/SettingsPanel.tsx
+++ b/src/components/panel/SettingsPanel.tsx
@@ -837,7 +837,7 @@ export default function SettingsPanel({
onClick={onBack}
size="icon"
variant="ghost"
- data-tooltip="Go to Home"
+ data-tooltip="Back"
>
diff --git a/src/components/panel/right/RightPanelSwitcher.tsx b/src/components/panel/right/RightPanelSwitcher.tsx
index 704000b73..5e9b001a4 100644
--- a/src/components/panel/right/RightPanelSwitcher.tsx
+++ b/src/components/panel/right/RightPanelSwitcher.tsx
@@ -1,5 +1,15 @@
import { motion } from 'framer-motion';
-import { SlidersHorizontal, Info, Crop, Layers, Paintbrush, SwatchBook, FileInput, type LucideIcon } from 'lucide-react';
+import {
+ SlidersHorizontal,
+ Info,
+ Crop,
+ Layers,
+ Paintbrush,
+ SwatchBook,
+ FileInput,
+ Cog,
+ type LucideIcon,
+} from 'lucide-react';
import { Panel } from '../../ui/AppProperties';
interface PanelOptions {
@@ -11,6 +21,7 @@ interface PanelOptions {
interface RightPanelSwitcherProps {
activePanel: Panel | null;
onPanelSelect(id: Panel): void;
+ onOpenAppSettings?(): void;
isInstantTransition: boolean;
layout?: 'horizontal' | 'vertical';
}
@@ -32,6 +43,7 @@ const panelGroups: Array> = [
export default function RightPanelSwitcher({
activePanel,
onPanelSelect,
+ onOpenAppSettings,
isInstantTransition,
layout = 'vertical',
}: RightPanelSwitcherProps) {
@@ -69,6 +81,22 @@ export default function RightPanelSwitcher({
))}
))}
+ {!isHorizontal && onOpenAppSettings && (
+ <>
+
+
+
+
+ >
+ )}
);
}
diff --git a/src/components/views/EditorView.tsx b/src/components/views/EditorView.tsx
index 8886ced0b..f467deee0 100644
--- a/src/components/views/EditorView.tsx
+++ b/src/components/views/EditorView.tsx
@@ -318,6 +318,7 @@ export default function EditorView({
setUI({ isSettingsOpen: true })}
isInstantTransition={isInstantTransition}
/>
diff --git a/src/hooks/useKeyboardShortcuts.tsx b/src/hooks/useKeyboardShortcuts.tsx
index 092afea6b..264884257 100644
--- a/src/hooks/useKeyboardShortcuts.tsx
+++ b/src/hooks/useKeyboardShortcuts.tsx
@@ -441,7 +441,8 @@ export const useKeyboardShortcuts = ({
match: (e: KeyboardEvent) => e.code === 'Escape',
execute: (e: KeyboardEvent, s: any) => {
e.preventDefault();
- if (s.editor.isStraightenActive) s.editor.setEditor({ isStraightenActive: false });
+ if (s.ui.isSettingsOpen) s.ui.setUI({ isSettingsOpen: false });
+ else if (s.editor.isStraightenActive) s.editor.setEditor({ isStraightenActive: false });
else if (s.ui.customEscapeHandler) s.ui.customEscapeHandler();
else if (s.editor.activeAiSubMaskId) s.editor.setEditor({ activeAiSubMaskId: null });
else if (s.editor.activeAiPatchContainerId) s.editor.setEditor({ activeAiPatchContainerId: null });
@@ -504,7 +505,14 @@ export const useKeyboardShortcuts = ({
const handleKeyDown = (event: KeyboardEvent) => {
const state = getStoreState();
+ if (state.ui.isSettingsOpen && event.code === 'Escape') {
+ event.preventDefault();
+ state.ui.setUI({ isSettingsOpen: false });
+ return;
+ }
+
const isModalOpen =
+ state.ui.isSettingsOpen ||
state.ui.isCreateFolderModalOpen ||
state.ui.isRenameFolderModalOpen ||
state.ui.isRenameFileModalOpen ||
diff --git a/src/store/useUIStore.ts b/src/store/useUIStore.ts
index e7ef4eb7c..87c193a26 100644
--- a/src/store/useUIStore.ts
+++ b/src/store/useUIStore.ts
@@ -94,6 +94,7 @@ interface UIState {
renameTargetPaths: Array;
isImportModalOpen: boolean;
isCopyPasteSettingsModalOpen: boolean;
+ isSettingsOpen: boolean;
importTargetFolder: string | null;
importSourcePaths: Array;
folderActionTarget: string | null;
@@ -139,6 +140,7 @@ export const useUIStore = create((set, get) => ({
renameTargetPaths: [],
isImportModalOpen: false,
isCopyPasteSettingsModalOpen: false,
+ isSettingsOpen: false,
importTargetFolder: null,
importSourcePaths: [],
folderActionTarget: null,