diff --git a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx
index 6cb99cd2..eb75e2c0 100644
--- a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx
+++ b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx
@@ -19,6 +19,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
const [menuBarIconEnabled, setMenuBarIconEnabled] = useState(true);
const [dockIconEnabled, setDockIconEnabled] = useState(true);
const [quitConfirmationEnabled, setQuitConfirmationEnabled] = useState(true);
+ const [wakelockEnabled, setWakelockEnabled] = useState(true);
const [isMacOS, setIsMacOS] = useState(false);
const [isDockSwitchDisabled, setIsDockSwitchDisabled] = useState(false);
const [showNotificationModal, setShowNotificationModal] = useState(false);
@@ -147,6 +148,10 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
setQuitConfirmationEnabled(enabled);
});
+ window.electron.getWakelockState().then((enabled) => {
+ setWakelockEnabled(enabled);
+ });
+
if (isMacOS) {
window.electron.getDockIconState().then((enabled) => {
setDockIconEnabled(enabled);
@@ -202,6 +207,14 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
}
};
+ const handleWakelockToggle = async () => {
+ const newState = !wakelockEnabled;
+ const success = await window.electron.setWakelock(newState);
+ if (success) {
+ setWakelockEnabled(newState);
+ }
+ };
+
const handleShowPricingToggle = (checked: boolean) => {
setShowPricing(checked);
localStorage.setItem('show_pricing', String(checked));
@@ -299,6 +312,23 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
+ {/* Prevent Sleep */}
+
+
+
Prevent Sleep
+
+ Keep your computer awake while Goose is running a task (screen can still lock)
+
+
+
+
+
+
+
{/* Cost Tracking */}
{COST_TRACKING_ENABLED && (
diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts
index edde8c4d..f3745ac4 100644
--- a/ui/desktop/src/main.ts
+++ b/ui/desktop/src/main.ts
@@ -494,6 +494,9 @@ let appConfig = {
let windowCounter = 0;
const windowMap = new Map();
+// Track power save blocker ID globally
+let powerSaveBlockerId: number | null = null;
+
interface RecipeConfig {
id: string;
title: string;
@@ -1090,6 +1093,36 @@ ipcMain.handle('get-quit-confirmation-state', () => {
}
});
+// Handle wakelock setting
+ipcMain.handle('set-wakelock', async (_event, enable: boolean) => {
+ try {
+ const settings = loadSettings();
+ settings.enableWakelock = enable;
+ saveSettings(settings);
+
+ // Stop any existing power save blocker when disabling the setting
+ if (!enable && powerSaveBlockerId !== null) {
+ powerSaveBlocker.stop(powerSaveBlockerId);
+ powerSaveBlockerId = null;
+ }
+
+ return true;
+ } catch (error) {
+ console.error('Error setting wakelock:', error);
+ return false;
+ }
+});
+
+ipcMain.handle('get-wakelock-state', () => {
+ try {
+ const settings = loadSettings();
+ return settings.enableWakelock ?? false;
+ } catch (error) {
+ console.error('Error getting wakelock state:', error);
+ return false;
+ }
+});
+
// Add file/directory selection handler
ipcMain.handle('select-file-or-directory', async () => {
const result = (await dialog.showOpenDialog({
@@ -1889,24 +1922,19 @@ app.whenReady().then(async () => {
}
});
- let powerSaveBlockerId: number | null = null;
-
ipcMain.handle('start-power-save-blocker', () => {
- log.info('Starting power save blocker...');
if (powerSaveBlockerId === null) {
- powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep');
- log.info('Started power save blocker');
+ powerSaveBlockerId = powerSaveBlocker.start('prevent-app-suspension');
return true;
}
+
return false;
});
ipcMain.handle('stop-power-save-blocker', () => {
- log.info('Stopping power save blocker...');
if (powerSaveBlockerId !== null) {
powerSaveBlocker.stop(powerSaveBlockerId);
powerSaveBlockerId = null;
- log.info('Stopped power save blocker');
return true;
}
return false;
diff --git a/ui/desktop/src/preload.ts b/ui/desktop/src/preload.ts
index 091c2be9..04ac73fa 100644
--- a/ui/desktop/src/preload.ts
+++ b/ui/desktop/src/preload.ts
@@ -83,6 +83,8 @@ type ElectronAPI = {
setSchedulingEngine: (engine: string) => Promise;
setQuitConfirmation: (show: boolean) => Promise;
getQuitConfirmationState: () => Promise;
+ setWakelock: (enable: boolean) => Promise;
+ getWakelockState: () => Promise;
openNotificationsSettings: () => Promise;
on: (
channel: string,
@@ -176,6 +178,8 @@ const electronAPI: ElectronAPI = {
setSchedulingEngine: (engine: string) => ipcRenderer.invoke('set-scheduling-engine', engine),
setQuitConfirmation: (show: boolean) => ipcRenderer.invoke('set-quit-confirmation', show),
getQuitConfirmationState: () => ipcRenderer.invoke('get-quit-confirmation-state'),
+ setWakelock: (enable: boolean) => ipcRenderer.invoke('set-wakelock', enable),
+ getWakelockState: () => ipcRenderer.invoke('get-wakelock-state'),
openNotificationsSettings: () => ipcRenderer.invoke('open-notifications-settings'),
on: (
channel: string,
diff --git a/ui/desktop/src/utils/settings.ts b/ui/desktop/src/utils/settings.ts
index bda74a5b..0b956950 100644
--- a/ui/desktop/src/utils/settings.ts
+++ b/ui/desktop/src/utils/settings.ts
@@ -16,6 +16,7 @@ export interface Settings {
showDockIcon: boolean;
schedulingEngine: SchedulingEngine;
showQuitConfirmation: boolean;
+ enableWakelock: boolean;
}
// Constants
@@ -30,6 +31,7 @@ const defaultSettings: Settings = {
showDockIcon: true,
schedulingEngine: 'builtin-cron',
showQuitConfirmation: true,
+ enableWakelock: false,
};
// Settings management