diff --git a/src/main/main.ts b/src/main/main.ts index 4f45e001..00fbcab1 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -32,6 +32,7 @@ import { cleanupOrphanedAttachments, preparePoracodeDataRoot } from "./poracodeD import { createLocalIpcHandlers, showAddFilesDialog } from "./ipc/localHandlers"; import { registerIpcHandlers } from "./ipc/registerHandlers"; import { createSleepInhibitor } from "./sleepInhibitor"; +import { shouldPreventSystemSleep } from "./sleepPolicy"; import { installLocalFileProtocolHandler, registerLocalFileProtocolScheme, @@ -611,10 +612,12 @@ function requirePoracodePaths(): PoracodePaths { } function updatePowerSaveBlocker(): void { - const enabled = poracodePaths - ? readSharedSettingsFile(poracodePaths.settingsPath).preventSleepWhileWorking - : true; - sleepInhibitor.setActive(enabled && workingThreads.size > 0); + if (!poracodePaths) { + sleepInhibitor.setActive(workingThreads.size > 0); + return; + } + const settings = readSharedSettingsFile(poracodePaths.settingsPath); + sleepInhibitor.setActive(shouldPreventSystemSleep(settings, workingThreads.size)); } function handleSupervisorEventForSleep(event: SupervisorEvent): void { @@ -1058,6 +1061,7 @@ if (!hasSingleInstanceLock) { }, getBrowserPanelManager: () => browserPanelManager, notifySharedSettingsChanged: (settings) => { + updatePowerSaveBlocker(); mainWindow?.webContents.send(IPC_EVENT_CHANNELS.sharedSettingsChanged, settings); }, notifyRemoteAccessPairingChanged: (info) => { @@ -1211,6 +1215,7 @@ if (!hasSingleInstanceLock) { // The remote controller performs one bounded warm-up when enabled. // Recurring Git refreshes remain demand-driven by connected clients. + updatePowerSaveBlocker(); void controller.startIfEnabled(); initialMainWindow.once("ready-to-show", () => { diff --git a/src/main/sharedSettingsFile.test.ts b/src/main/sharedSettingsFile.test.ts index 144a02c8..3dea639b 100644 --- a/src/main/sharedSettingsFile.test.ts +++ b/src/main/sharedSettingsFile.test.ts @@ -129,6 +129,7 @@ describe("sharedSettingsFile", () => { guiChatFontSize: 13, terminalPanelFontSize: 12, preventSleepWhileWorking: true, + remoteAccessPreventSleep: true, launchAtStartup: true, startMinimized: true, closeToTray: true, @@ -256,6 +257,7 @@ describe("sharedSettingsFile", () => { guiChatFontSize: 13, terminalPanelFontSize: 12, preventSleepWhileWorking: true, + remoteAccessPreventSleep: true, launchAtStartup: true, startMinimized: true, closeToTray: true, diff --git a/src/main/sleepInhibitor.test.ts b/src/main/sleepInhibitor.test.ts index 1560375b..0d6ea4ce 100644 --- a/src/main/sleepInhibitor.test.ts +++ b/src/main/sleepInhibitor.test.ts @@ -126,13 +126,7 @@ describe("createSleepInhibitor", () => { expect(spawnFn).toHaveBeenCalledTimes(1); expect(spawnFn).toHaveBeenCalledWith( "systemd-inhibit", - [ - "--what=sleep:idle", - "--who=Poracode", - "--why=Agent thread is working", - "--mode=block", - "cat", - ], + ["--what=sleep:idle", "--who=Poracode", "--why=Poracode is active", "--mode=block", "cat"], expect.objectContaining({ detached: false }), ); }); diff --git a/src/main/sleepInhibitor.ts b/src/main/sleepInhibitor.ts index 9e643cbb..d1a2888a 100644 --- a/src/main/sleepInhibitor.ts +++ b/src/main/sleepInhibitor.ts @@ -90,13 +90,7 @@ class SystemdInhibitor implements Inhibitor { try { child = this.spawnFn( "systemd-inhibit", - [ - "--what=sleep:idle", - "--who=Poracode", - "--why=Agent thread is working", - "--mode=block", - "cat", - ], + ["--what=sleep:idle", "--who=Poracode", "--why=Poracode is active", "--mode=block", "cat"], { stdio: ["pipe", "ignore", "ignore"], detached: false }, ); } catch (error) { diff --git a/src/main/sleepPolicy.test.ts b/src/main/sleepPolicy.test.ts new file mode 100644 index 00000000..fc18e785 --- /dev/null +++ b/src/main/sleepPolicy.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from "vitest"; +import { shouldPreventSystemSleep } from "./sleepPolicy"; + +describe("shouldPreventSystemSleep", () => { + it("keeps the system awake for a working thread when enabled", () => { + expect( + shouldPreventSystemSleep( + { + preventSleepWhileWorking: true, + remoteAccessPreventSleep: false, + remoteAccessEnabled: false, + }, + 1, + ), + ).toBe(true); + }); + + it("keeps the system awake for enabled remote access independently of thread activity", () => { + expect( + shouldPreventSystemSleep( + { + preventSleepWhileWorking: false, + remoteAccessPreventSleep: true, + remoteAccessEnabled: true, + }, + 0, + ), + ).toBe(true); + }); + + it("allows sleep when each active reason is opted out", () => { + expect( + shouldPreventSystemSleep( + { + preventSleepWhileWorking: false, + remoteAccessPreventSleep: false, + remoteAccessEnabled: true, + }, + 1, + ), + ).toBe(false); + }); +}); diff --git a/src/main/sleepPolicy.ts b/src/main/sleepPolicy.ts new file mode 100644 index 00000000..4a67fc3c --- /dev/null +++ b/src/main/sleepPolicy.ts @@ -0,0 +1,16 @@ +import type { SharedSettings } from "@/shared/settings"; + +type SleepPolicySettings = Pick< + SharedSettings, + "preventSleepWhileWorking" | "remoteAccessPreventSleep" | "remoteAccessEnabled" +>; + +export function shouldPreventSystemSleep( + settings: SleepPolicySettings, + workingThreadCount: number, +): boolean { + const threadRequiresAwake = settings.preventSleepWhileWorking && workingThreadCount > 0; + const remoteAccessRequiresAwake = + settings.remoteAccessPreventSleep && settings.remoteAccessEnabled; + return threadRequiresAwake || remoteAccessRequiresAwake; +} diff --git a/src/renderer/locales/de/messages.po b/src/renderer/locales/de/messages.po index 2ece26a1..e98510aa 100644 --- a/src/renderer/locales/de/messages.po +++ b/src/renderer/locales/de/messages.po @@ -5601,6 +5601,11 @@ msgstr "Poracode beim Start im Infobereich der Taskleiste belassen." msgid "Keep the system awake while any thread is actively working." msgstr "Halten Sie das System wach, während ein Thread aktiv arbeitet." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Das System aktiv halten, solange der Fernzugriff aktiviert ist." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Weiter warten" @@ -8090,6 +8095,11 @@ msgstr "Voreinstellungen" msgid "Press shortcut…" msgstr "Tastenkürzel drücken…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Ruhezustand bei Fernzugriff verhindern" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/en/messages.po b/src/renderer/locales/en/messages.po index 661737a0..d656830b 100644 --- a/src/renderer/locales/en/messages.po +++ b/src/renderer/locales/en/messages.po @@ -5601,6 +5601,11 @@ msgstr "Keep Poracode in the system tray when it launches at startup." msgid "Keep the system awake while any thread is actively working." msgstr "Keep the system awake while any thread is actively working." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Keep the system awake while remote access is enabled." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Keep waiting" @@ -8090,6 +8095,11 @@ msgstr "Presets" msgid "Press shortcut…" msgstr "Press shortcut…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Prevent sleep during remote access" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/es/messages.po b/src/renderer/locales/es/messages.po index 66f912b9..eda3451b 100644 --- a/src/renderer/locales/es/messages.po +++ b/src/renderer/locales/es/messages.po @@ -5601,6 +5601,11 @@ msgstr "Mantener Poracode en la bandeja del sistema cuando se inicie automática msgid "Keep the system awake while any thread is actively working." msgstr "Mantener el sistema activo mientras cualquier hilo esté trabajando." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Mantén el sistema activo mientras el acceso remoto esté habilitado." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Seguir esperando" @@ -8090,6 +8095,11 @@ msgstr "Preajustes" msgid "Press shortcut…" msgstr "Pulsa el atajo…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Impedir la suspensión durante el acceso remoto" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/fr/messages.po b/src/renderer/locales/fr/messages.po index b4c500dd..9aa8e7d8 100644 --- a/src/renderer/locales/fr/messages.po +++ b/src/renderer/locales/fr/messages.po @@ -5601,6 +5601,11 @@ msgstr "Garder Poracode dans la zone de notification lors de son lancement au d msgid "Keep the system awake while any thread is actively working." msgstr "Gardez le système éveillé pendant qu'un thread fonctionne activement." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Garder le système éveillé tant que l’accès à distance est activé." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Continuer à attendre" @@ -8089,6 +8094,11 @@ msgstr "Préréglages" msgid "Press shortcut…" msgstr "Appuyez sur le raccourci…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Empêcher la mise en veille pendant l’accès à distance" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/ja/messages.po b/src/renderer/locales/ja/messages.po index 13810d73..fcf0062f 100644 --- a/src/renderer/locales/ja/messages.po +++ b/src/renderer/locales/ja/messages.po @@ -5600,6 +5600,11 @@ msgstr "スタートアップ時は Poracode をシステムトレイに格納 msgid "Keep the system awake while any thread is actively working." msgstr "スレッドがアクティブに動作している間は、システムを起動したままにします。" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "リモートアクセスが有効な間、システムをスリープさせません。" + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "待機を続ける" @@ -8088,6 +8093,11 @@ msgstr "プリセット" msgid "Press shortcut…" msgstr "ショートカットを押してください…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "リモートアクセス中のスリープを防止" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/ko/messages.po b/src/renderer/locales/ko/messages.po index 7c3ecdbc..e9b763bb 100644 --- a/src/renderer/locales/ko/messages.po +++ b/src/renderer/locales/ko/messages.po @@ -5601,6 +5601,11 @@ msgstr "시작 시 Poracode를 시스템 트레이에 둡니다." msgid "Keep the system awake while any thread is actively working." msgstr "스레드가 활발하게 작동하는 동안 시스템을 활성 상태로 유지합니다." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "원격 액세스가 활성화된 동안 시스템이 절전 모드로 전환되지 않도록 합니다." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "계속 기다리기" @@ -8090,6 +8095,11 @@ msgstr "프리셋" msgid "Press shortcut…" msgstr "단축키를 누르세요…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "원격 액세스 중 절전 모드 방지" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/pl/messages.po b/src/renderer/locales/pl/messages.po index 5776ed63..69bc0f3c 100644 --- a/src/renderer/locales/pl/messages.po +++ b/src/renderer/locales/pl/messages.po @@ -5601,6 +5601,11 @@ msgstr "Po uruchomieniu przy starcie pozostaw Poracode w zasobniku systemowym." msgid "Keep the system awake while any thread is actively working." msgstr "Utrzymuj system w stanie czuwania, gdy dowolny wątek aktywnie działa." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Utrzymuj system w stanie aktywnym, gdy dostęp zdalny jest włączony." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Czekaj dalej" @@ -8090,6 +8095,11 @@ msgstr "Ustawienia predefiniowane" msgid "Press shortcut…" msgstr "Naciśnij skrót…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Zapobiegaj uśpieniu podczas dostępu zdalnego" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/pt-BR/messages.po b/src/renderer/locales/pt-BR/messages.po index 1eaa880e..a7d1126c 100644 --- a/src/renderer/locales/pt-BR/messages.po +++ b/src/renderer/locales/pt-BR/messages.po @@ -5601,6 +5601,11 @@ msgstr "Manter o Poracode na bandeja do sistema quando ele for iniciado com o Wi msgid "Keep the system awake while any thread is actively working." msgstr "Mantém o sistema ativo enquanto qualquer thread estiver trabalhando ativamente." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Mantenha o sistema ativo enquanto o acesso remoto estiver habilitado." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Continuar aguardando" @@ -8090,6 +8095,11 @@ msgstr "Predefinições" msgid "Press shortcut…" msgstr "Pressione o atalho…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Impedir suspensão durante o acesso remoto" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/ru/messages.po b/src/renderer/locales/ru/messages.po index e78d038d..0dcfe0ed 100644 --- a/src/renderer/locales/ru/messages.po +++ b/src/renderer/locales/ru/messages.po @@ -5601,6 +5601,11 @@ msgstr "При запуске вместе с системой оставлят msgid "Keep the system awake while any thread is actively working." msgstr "Не давать системе засыпать, пока хотя бы один тред активно работает." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Не переводить систему в спящий режим, пока включён удалённый доступ." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Продолжить ожидание" @@ -8090,6 +8095,11 @@ msgstr "Пресеты" msgid "Press shortcut…" msgstr "Нажмите сочетание клавиш…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Запрещать спящий режим при удалённом доступе" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/tr/messages.po b/src/renderer/locales/tr/messages.po index 6e10fe07..8c492c14 100644 --- a/src/renderer/locales/tr/messages.po +++ b/src/renderer/locales/tr/messages.po @@ -5601,6 +5601,11 @@ msgstr "Başlangıçta açıldığında Poracode'u sistem tepsisinde tutun." msgid "Keep the system awake while any thread is actively working." msgstr "Herhangi bir konu aktif olarak çalışırken sistemi uyanık tutun." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Uzaktan erişim etkinken sistemi uyanık tutun." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Beklemeye devam et" @@ -8090,6 +8095,11 @@ msgstr "Hazır ayarlar" msgid "Press shortcut…" msgstr "Kısayola basın…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Uzaktan erişim sırasında uyku modunu engelle" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/uk/messages.po b/src/renderer/locales/uk/messages.po index d46a2201..547693d5 100644 --- a/src/renderer/locales/uk/messages.po +++ b/src/renderer/locales/uk/messages.po @@ -5601,6 +5601,11 @@ msgstr "Під час запуску разом із системою залиш msgid "Keep the system awake while any thread is actively working." msgstr "Не давати системі засинати, поки будь-який тред активно працює." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Не переводити систему в режим сну, доки ввімкнено віддалений доступ." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Продовжити очікування" @@ -8090,6 +8095,11 @@ msgstr "Пресети" msgid "Press shortcut…" msgstr "Натисніть комбінацію клавіш…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Запобігати сну під час віддаленого доступу" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/vi/messages.po b/src/renderer/locales/vi/messages.po index 569dd475..f59dcde1 100644 --- a/src/renderer/locales/vi/messages.po +++ b/src/renderer/locales/vi/messages.po @@ -5601,6 +5601,11 @@ msgstr "Giữ Poracode trong khay hệ thống khi ứng dụng khởi chạy c msgid "Keep the system awake while any thread is actively working." msgstr "Giữ cho hệ thống luôn hoạt động trong khi bất kỳ luồng nào đang hoạt động tích cực." +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "Giữ hệ thống luôn hoạt động khi truy cập từ xa được bật." + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "Tiếp tục chờ" @@ -8090,6 +8095,11 @@ msgstr "Cấu hình sẵn" msgid "Press shortcut…" msgstr "Nhấn phím tắt…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "Ngăn chế độ ngủ khi truy cập từ xa" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/locales/zh-CN/messages.po b/src/renderer/locales/zh-CN/messages.po index 3c3210a1..b63b3f3a 100644 --- a/src/renderer/locales/zh-CN/messages.po +++ b/src/renderer/locales/zh-CN/messages.po @@ -5601,6 +5601,11 @@ msgstr "开机启动时将 Poracode 保持在系统托盘中。" msgid "Keep the system awake while any thread is actively working." msgstr "当任何线程正在工作时保持系统唤醒状态(不休眠)。" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Keep the system awake while remote access is enabled." +msgstr "启用远程访问时保持系统唤醒。" + #: src/renderer/components/startup/StartupRecoveryScreen.tsx msgid "Keep waiting" msgstr "继续等待" @@ -8089,6 +8094,11 @@ msgstr "预设" msgid "Press shortcut…" msgstr "请按快捷键…" +#: src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +msgid "Prevent sleep during remote access" +msgstr "防止远程访问期间休眠" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Prevent sleep while working" diff --git a/src/renderer/state/devTerminalStore.ts b/src/renderer/state/devTerminalStore.ts index 9252f0ee..ce7c9822 100644 --- a/src/renderer/state/devTerminalStore.ts +++ b/src/renderer/state/devTerminalStore.ts @@ -110,7 +110,12 @@ export const useDevTerminalStore = create focusRequestId: state.focusRequestId + 1, })), closePanel: () => - set({ isOpen: false, explicitlyOpened: false, activeProjectId: null, activeWorktreePath: null }), + set({ + isOpen: false, + explicitlyOpened: false, + activeProjectId: null, + activeWorktreePath: null, + }), setActiveProject: (projectId) => { const tabs = get().tabs.filter((t) => t.projectId === projectId); diff --git a/src/renderer/state/sharedSettingsStore.ts b/src/renderer/state/sharedSettingsStore.ts index e6771c3b..d0b56434 100644 --- a/src/renderer/state/sharedSettingsStore.ts +++ b/src/renderer/state/sharedSettingsStore.ts @@ -80,6 +80,7 @@ interface SharedSettingsState extends SharedSettings { setGuiChatFontSize: (value: number) => void; setTerminalPanelFontSize: (value: number) => void; setPreventSleepWhileWorking: (value: boolean) => void; + setRemoteAccessPreventSleep: (value: boolean) => void; setLaunchAtStartup: (value: boolean) => void; setStartMinimized: (value: boolean) => void; setCloseToTray: (value: boolean) => void; @@ -438,6 +439,10 @@ export const useSharedSettings = create()((set, get) => ({ set({ preventSleepWhileWorking }); persistSettings(selectSharedSettings(get())); }, + setRemoteAccessPreventSleep: (remoteAccessPreventSleep) => { + set({ remoteAccessPreventSleep }); + persistSettings(selectSharedSettings(get())); + }, setLaunchAtStartup: (launchAtStartup) => { if (get().launchAtStartup === launchAtStartup) return; set({ launchAtStartup }); @@ -874,6 +879,7 @@ function selectSharedSettings(state: SharedSettingsState): SharedSettingsInput { guiChatFontSize: state.guiChatFontSize, terminalPanelFontSize: state.terminalPanelFontSize, preventSleepWhileWorking: state.preventSleepWhileWorking, + remoteAccessPreventSleep: state.remoteAccessPreventSleep, launchAtStartup: state.launchAtStartup, startMinimized: state.startMinimized, closeToTray: state.closeToTray, diff --git a/src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.test.tsx b/src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.test.tsx index d26c10dd..b52e27f8 100644 --- a/src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.test.tsx +++ b/src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.test.tsx @@ -559,9 +559,9 @@ describe("AcpRegistrySettings", () => { render(); await screen.findByRole("heading", { name: "Agent Registry" }); - const grokCard = screen - .getByText(/First-class Grok Build CLI integration/u) - .closest(".rounded-lg"); + const grokCard = (await screen.findByText(/First-class Grok Build CLI integration/u)).closest( + ".rounded-lg", + ); expect(grokCard).toBeTruthy(); expect(within(grokCard as HTMLElement).queryByText(/Windows is not supported/u)).toBeNull(); diff --git a/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.test.tsx b/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.test.tsx index 162c0135..f818b587 100644 --- a/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.test.tsx +++ b/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.test.tsx @@ -18,6 +18,8 @@ const { bridgeMock, pairingChangedState, sharedSettingsState, toDataURLMock } = listener: null as ((info: RemoteAccessPairingInfo) => void) | null, }, sharedSettingsState: { + remoteAccessPreventSleep: true, + setRemoteAccessPreventSleep: vi.fn<(enabled: boolean) => void>(), remoteAccessTailscaleHttps: true, remoteAccessAdvertisedUrl: "", remotePushEnabled: true, @@ -86,6 +88,16 @@ describe("RemoteAccessSettings", () => { toDataURLMock.mockResolvedValue("data:image/png;base64,test"); }); + it("allows preventing sleep during remote access independently", () => { + render(); + + const toggle = screen.getByRole("switch", { name: "Prevent sleep during remote access" }); + expect(toggle).toBeChecked(); + fireEvent.click(toggle); + + expect(sharedSettingsState.setRemoteAccessPreventSleep).toHaveBeenCalledWith(false); + }); + it("switches the displayed endpoint and QR code from Tailscale to local", async () => { render(); diff --git a/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx b/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx index 1a56b06a..ee2217d6 100644 --- a/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx +++ b/src/renderer/views/SettingsOverlay/parts/RemoteAccessSettings.tsx @@ -709,6 +709,10 @@ function RemotePushSection() { export function RemoteAccessSettings() { const { t } = useLingui(); + const remoteAccessPreventSleep = useSharedSettings((state) => state.remoteAccessPreventSleep); + const setRemoteAccessPreventSleep = useSharedSettings( + (state) => state.setRemoteAccessPreventSleep, + ); const [state, setState] = useState({ info: null, error: null, @@ -857,6 +861,18 @@ export function RemoteAccessSettings() { ) : null } > + Keep the system awake while remote access is enabled.} + > + + + {isLoading ? (
diff --git a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts index e0b9f68e..d05d5583 100644 --- a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +++ b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts @@ -137,6 +137,16 @@ export const SETTINGS_SEARCH_INDEX: readonly SettingsSearchEntry[] = [ desktopOnly: true, }, + // Remote Access + { + section: "remoteAccess", + anchor: "remoteAccess.preventSleep", + title: msg`Prevent sleep during remote access`, + description: msg`Keep the system awake while remote access is enabled.`, + keywords: "sleep awake wake idle power server connection", + desktopOnly: true, + }, + // Audio { section: "audio", diff --git a/src/shared/settings.test.ts b/src/shared/settings.test.ts index 45bb9796..d901765c 100644 --- a/src/shared/settings.test.ts +++ b/src/shared/settings.test.ts @@ -8,6 +8,14 @@ describe("shared settings defaults", () => { expect(defaultSharedSettings.notificationFilter).toBe("all"); }); + it("prevents sleep during remote access by default and preserves opt-outs", () => { + expect(defaultSharedSettings.remoteAccessPreventSleep).toBe(true); + expect(normalizeSharedSettings({}).remoteAccessPreventSleep).toBe(true); + expect( + normalizeSharedSettings({ remoteAccessPreventSleep: false }).remoteAccessPreventSleep, + ).toBe(false); + }); + it("enables Crossagents as the standing MCP default and preserves opt-outs", () => { expect(defaultSharedSettings.enabledMcpServers.crossagents).toBe(true); expect(normalizeSharedSettings({}).enabledMcpServers.crossagents).toBe(true); diff --git a/src/shared/settings.ts b/src/shared/settings.ts index be934910..4cf00a01 100644 --- a/src/shared/settings.ts +++ b/src/shared/settings.ts @@ -294,6 +294,8 @@ export const sharedSettingsSchema = z.object({ terminalPanelFontSize: z.number().int().min(8).max(20), /** Prevent OS sleep while any thread is actively working. */ preventSleepWhileWorking: z.boolean(), + /** Prevent OS sleep while the desktop remote access server is enabled. */ + remoteAccessPreventSleep: z.boolean(), /** Register Poracode to launch automatically when the user signs in to Windows. */ launchAtStartup: z.boolean(), /** Keep the main window hidden when Poracode is launched automatically at sign-in. */ @@ -588,6 +590,7 @@ export const defaultSharedSettings: SharedSettings = { guiChatFontSize: 13, terminalPanelFontSize: 12, preventSleepWhileWorking: true, + remoteAccessPreventSleep: true, launchAtStartup: true, startMinimized: true, closeToTray: true,