add setting to prevent sleep on playback (#1072)

This commit is contained in:
jeffvli 2025-09-06 00:56:06 -07:00
parent 40fb5ba916
commit b00305cc86
7 changed files with 114 additions and 0 deletions

View file

@ -6,6 +6,7 @@ import { AudioPlayer } from '/@/renderer/components';
import { CenterControls } from '/@/renderer/features/player/components/center-controls';
import { LeftControls } from '/@/renderer/features/player/components/left-controls';
import { RightControls } from '/@/renderer/features/player/components/right-controls';
import { usePowerSaveBlocker } from '/@/renderer/features/player/hooks/use-power-save-blocker';
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
import { updateSong } from '/@/renderer/features/player/update-remote-song';
import {
@ -41,6 +42,8 @@ export const Playerbar = () => {
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
usePowerSaveBlocker();
const handleToggleFullScreenPlayer = (e?: KeyboardEvent | MouseEvent<HTMLDivElement>) => {
e?.stopPropagation();
setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded });

View file

@ -0,0 +1,50 @@
import isElectron from 'is-electron';
import { useCallback, useEffect } from 'react';
import { useCurrentStatus } from '/@/renderer/store';
import { useWindowSettings } from '/@/renderer/store';
import { PlayerStatus } from '/@/shared/types/types';
const ipc = isElectron() ? window.api.ipc : null;
export const usePowerSaveBlocker = () => {
const status = useCurrentStatus();
const { preventSleepOnPlayback } = useWindowSettings();
const startPowerSaveBlocker = useCallback(async () => {
if (!ipc) return;
try {
await ipc.invoke('power-save-blocker-start');
} catch (error) {
console.error('Failed to start power save blocker:', error);
}
}, []);
const stopPowerSaveBlocker = useCallback(async () => {
if (!ipc) return;
try {
await ipc.invoke('power-save-blocker-stop');
} catch (error) {
console.error('Failed to stop power save blocker:', error);
}
}, []);
useEffect(() => {
if (!preventSleepOnPlayback) return;
if (status === PlayerStatus.PLAYING) {
startPowerSaveBlocker();
} else {
stopPowerSaveBlocker();
}
}, [status, preventSleepOnPlayback, startPowerSaveBlocker, stopPowerSaveBlocker]);
// Clean up on unmount
useEffect(() => {
return () => {
stopPowerSaveBlocker();
};
}, [stopPowerSaveBlocker]);
};

View file

@ -203,6 +203,34 @@ export const WindowSettings = () => {
isHidden: !isElectron() || !settings.tray,
title: t('setting.startMinimized', { postProcess: 'sentenceCase' }),
},
{
control: (
<Switch
aria-label="Toggle prevent sleep on playback"
defaultChecked={settings.preventSleepOnPlayback}
disabled={!isElectron()}
onChange={(e) => {
if (!e) return;
localSettings?.set(
'window_prevent_sleep_on_playback',
e.currentTarget.checked,
);
setSettings({
window: {
...settings,
preventSleepOnPlayback: e.currentTarget.checked,
},
});
}}
/>
),
description: t('setting.preventSleepOnPlayback', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: !isElectron(),
title: t('setting.preventSleepOnPlayback', { postProcess: 'sentenceCase' }),
},
];
return <SettingsSection options={windowOptions} />;

View file

@ -320,6 +320,7 @@ export interface SettingsState {
disableAutoUpdate: boolean;
exitToTray: boolean;
minimizeToTray: boolean;
preventSleepOnPlayback: boolean;
startMinimized: boolean;
tray: boolean;
windowBarStyle: Platform;
@ -664,6 +665,7 @@ const initialState: SettingsState = {
disableAutoUpdate: false,
exitToTray: false,
minimizeToTray: false,
preventSleepOnPlayback: false,
startMinimized: false,
tray: true,
windowBarStyle: platformDefaultWindowBarStyle,