mirror of
https://github.com/antebudimir/feishin.git
synced 2025-12-31 18:13:31 +00:00
add setting to prevent sleep on playback (#1072)
This commit is contained in:
parent
40fb5ba916
commit
b00305cc86
7 changed files with 114 additions and 0 deletions
|
|
@ -696,6 +696,8 @@
|
|||
"skipPlaylistPage_description": "when navigating to a playlist, go to the playlist song list page instead of the default page",
|
||||
"startMinimized": "start minimized",
|
||||
"startMinimized_description": "start the application in system tray",
|
||||
"preventSleepOnPlayback": "prevent sleep on playback",
|
||||
"preventSleepOnPlayback_description": "prevent the display from sleeping while music is playing",
|
||||
"theme": "theme",
|
||||
"theme_description": "sets the theme to use for the application",
|
||||
"themeDark": "theme (dark)",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
nativeImage,
|
||||
nativeTheme,
|
||||
net,
|
||||
powerSaveBlocker,
|
||||
protocol,
|
||||
Rectangle,
|
||||
screen,
|
||||
|
|
@ -66,6 +67,7 @@ let mainWindow: BrowserWindow | null = null;
|
|||
let tray: null | Tray = null;
|
||||
let exitFromTray = false;
|
||||
let forceQuit = false;
|
||||
let powerSaveBlockerId: null | number = null;
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
import('source-map-support').then((sourceMapSupport) => {
|
||||
|
|
@ -616,6 +618,28 @@ ipcMain.on(
|
|||
},
|
||||
);
|
||||
|
||||
ipcMain.handle('power-save-blocker-start', () => {
|
||||
if (powerSaveBlockerId !== null) {
|
||||
return powerSaveBlockerId;
|
||||
}
|
||||
|
||||
powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep');
|
||||
return powerSaveBlockerId;
|
||||
});
|
||||
|
||||
ipcMain.handle('power-save-blocker-stop', () => {
|
||||
if (powerSaveBlockerId !== null) {
|
||||
const stopped = powerSaveBlocker.stop(powerSaveBlockerId);
|
||||
powerSaveBlockerId = null;
|
||||
return stopped;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
ipcMain.handle('power-save-blocker-is-started', () => {
|
||||
return powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId);
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
globalShortcut.unregisterAll();
|
||||
// Respect the OSX convention of having the application in memory even
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ const send = (channel: string, ...args: any[]) => {
|
|||
ipcRenderer.send(channel, ...args);
|
||||
};
|
||||
|
||||
const invoke = (channel: string, ...args: any[]) => {
|
||||
return ipcRenderer.invoke(channel, ...args);
|
||||
};
|
||||
|
||||
export const ipc = {
|
||||
invoke,
|
||||
removeAllListeners,
|
||||
send,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
50
src/renderer/features/player/hooks/use-power-save-blocker.ts
Normal file
50
src/renderer/features/player/hooks/use-power-save-blocker.ts
Normal 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]);
|
||||
};
|
||||
|
|
@ -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} />;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue