diff --git a/app.go b/app.go
index a8e7efc..943afb6 100644
--- a/app.go
+++ b/app.go
@@ -489,3 +489,27 @@ func formatShutterSpeed(num, den int64) string {
return fmt.Sprintf("%d/%ds", reducedNum, reducedDen)
}
}
+
+// OpenSettingsWindow opens the settings window or focuses it if already open.
+func (a *App) OpenSettingsWindow() {
+ app := application.Get()
+
+ // If the window already exists, focus it
+ if win, ok := app.Window.GetByName("settings"); ok && win != nil {
+ win.Show()
+ win.Focus()
+ return
+ }
+
+ app.Window.NewWithOptions(application.WebviewWindowOptions{
+ Name: "settings",
+ Title: "Preferences",
+ Width: 600,
+ Height: 500,
+ Mac: application.MacWindow{
+ TitleBar: application.MacTitleBarHiddenInsetUnified,
+ },
+ BackgroundColour: application.NewRGB(27, 38, 54),
+ URL: "/settings",
+ })
+}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 81c5b66..d9474cc 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -2,7 +2,7 @@ import { useState, useRef, useEffect, useCallback, ChangeEvent } from 'react';
import './App.css';
// @ts-expect-error generated bindings does not provide declaration files for JS module
import { App as AppAPI, Settings } from '../bindings/ExifFrame/index';
-import { Window, Events, System } from '@wailsio/runtime';
+import { Window, Events, System, Call } from '@wailsio/runtime';
interface ExifData {
camera: string;
@@ -33,8 +33,8 @@ interface MetadataVisibility {
}
const VISIBILITY_KEYS = [
- 'camera','lens','focalLength','aperture','shutterSpeed','iso',
- 'film','developer','dilution','temperature','time',
+ 'camera', 'lens', 'focalLength', 'aperture', 'shutterSpeed', 'iso',
+ 'film', 'developer', 'dilution', 'temperature', 'time',
] as const;
const settingsKey = (k: typeof VISIBILITY_KEYS[number]) =>
@@ -217,9 +217,9 @@ const ToggleInput = ({ label, id, value, onChange, visible, onToggleVisibility }
);
@@ -260,12 +260,11 @@ interface WailsProcessFileEvent {
}
function App() {
- const [showSettings, setShowSettings] = useState(false);
const [watchFolder, setWatchFolder] = useState("");
const [exportFolder, setExportFolder] = useState("");
const [profile, setProfile] = useState("digital");
-
+
useEffect(() => {
const unsubProcess = Events.On("process_file", (event: WailsProcessFileEvent) => {
if (!event?.data) return;
@@ -301,7 +300,7 @@ function App() {
temperature: currentSet.temperature || "",
time: currentSet.time || ""
};
-
+
renderImageToCanvas(offscreenCanvas, img, exifData, {
aspectRatioPreset: currentSet.aspectRatioPreset || "4300:3618",
customRatioW: currentSet.customRatioW || 4300,
@@ -325,7 +324,7 @@ function App() {
offscreenCanvas.toBlob(async (blob) => {
if (!blob) return;
try {
- const resultSave = await AppAPI.SaveAutoImage(isPng, savePath);
+ const resultSave = await AppAPI.SaveAutoImage(isPng, savePath);
if (resultSave.saveToken) {
const arrayBuffer = await blob.arrayBuffer();
const resp = await fetch(`/api/save?token=${encodeURIComponent(resultSave.saveToken)}`, {
@@ -358,7 +357,7 @@ function App() {
unsubProcess();
};
}, []);
-
+
const canvasRef = useRef(null);
const [imageLoaded, setImageLoaded] = useState(false);
const [exif, setExif] = useState({
@@ -428,7 +427,7 @@ function App() {
window.cancelAnimationFrame(toastRafRef.current);
toastRafRef.current = null;
}
-
+
// Force a re-render by clearing the state first
setToastMessage(null);
toastRafRef.current = requestAnimationFrame(() => {
@@ -455,7 +454,7 @@ function App() {
if (s.profile) {
setProfile(['digital', 'film'].includes(s.profile) ? s.profile : 'digital');
}
-
+
setExif(prev => ({
...prev,
film: s.film || "",
@@ -475,31 +474,26 @@ function App() {
}, 100);
});
- const unsubSettings = Events.On("open_settings", () => {
- console.log("open_settings event received");
- setShowSettings(true);
+ const unsubSettings = Events.On("settings_saved", () => {
+ AppAPI.GetSettings().then((s: Settings) => {
+ if (s.watchFolder) setWatchFolder(s.watchFolder);
+ else setWatchFolder("");
+ if (s.exportFolder) setExportFolder(s.exportFolder);
+ else setExportFolder("");
+ }).catch((err: any) => {
+ console.error("Failed to reload settings:", err);
+ });
});
-
+
return () => {
unsubSettings();
};
}, []);
- // Escape key to close settings modal
- useEffect(() => {
- const handleKeyDown = (e: KeyboardEvent) => {
- if (e.key === 'Escape') {
- setShowSettings(false);
- }
- };
- window.addEventListener('keydown', handleKeyDown);
- return () => window.removeEventListener('keydown', handleKeyDown);
- }, []);
-
// Save settings when aspect ratio etc changes
useEffect(() => {
if (isInitialLoad.current) return;
-
+
const saveCurrentSettings = async () => {
const s = new Settings();
s.watchFolder = watchFolder;
@@ -516,7 +510,7 @@ function App() {
s.dilution = exif.dilution;
s.temperature = exif.temperature;
s.time = exif.time;
-
+
applyVisibility(s, visibility);
try {
@@ -689,9 +683,9 @@ function App() {
{filePath && {filePath.split(/[/\\]/).filter(Boolean).join(' > ')}}
-