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",
|
"skipPlaylistPage_description": "when navigating to a playlist, go to the playlist song list page instead of the default page",
|
||||||
"startMinimized": "start minimized",
|
"startMinimized": "start minimized",
|
||||||
"startMinimized_description": "start the application in system tray",
|
"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": "theme",
|
||||||
"theme_description": "sets the theme to use for the application",
|
"theme_description": "sets the theme to use for the application",
|
||||||
"themeDark": "theme (dark)",
|
"themeDark": "theme (dark)",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
nativeImage,
|
nativeImage,
|
||||||
nativeTheme,
|
nativeTheme,
|
||||||
net,
|
net,
|
||||||
|
powerSaveBlocker,
|
||||||
protocol,
|
protocol,
|
||||||
Rectangle,
|
Rectangle,
|
||||||
screen,
|
screen,
|
||||||
|
|
@ -66,6 +67,7 @@ let mainWindow: BrowserWindow | null = null;
|
||||||
let tray: null | Tray = null;
|
let tray: null | Tray = null;
|
||||||
let exitFromTray = false;
|
let exitFromTray = false;
|
||||||
let forceQuit = false;
|
let forceQuit = false;
|
||||||
|
let powerSaveBlockerId: null | number = null;
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
import('source-map-support').then((sourceMapSupport) => {
|
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', () => {
|
app.on('window-all-closed', () => {
|
||||||
globalShortcut.unregisterAll();
|
globalShortcut.unregisterAll();
|
||||||
// Respect the OSX convention of having the application in memory even
|
// 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);
|
ipcRenderer.send(channel, ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const invoke = (channel: string, ...args: any[]) => {
|
||||||
|
return ipcRenderer.invoke(channel, ...args);
|
||||||
|
};
|
||||||
|
|
||||||
export const ipc = {
|
export const ipc = {
|
||||||
|
invoke,
|
||||||
removeAllListeners,
|
removeAllListeners,
|
||||||
send,
|
send,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { AudioPlayer } from '/@/renderer/components';
|
||||||
import { CenterControls } from '/@/renderer/features/player/components/center-controls';
|
import { CenterControls } from '/@/renderer/features/player/components/center-controls';
|
||||||
import { LeftControls } from '/@/renderer/features/player/components/left-controls';
|
import { LeftControls } from '/@/renderer/features/player/components/left-controls';
|
||||||
import { RightControls } from '/@/renderer/features/player/components/right-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 { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
|
||||||
import { updateSong } from '/@/renderer/features/player/update-remote-song';
|
import { updateSong } from '/@/renderer/features/player/update-remote-song';
|
||||||
import {
|
import {
|
||||||
|
|
@ -41,6 +42,8 @@ export const Playerbar = () => {
|
||||||
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
||||||
const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
|
const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
|
||||||
|
|
||||||
|
usePowerSaveBlocker();
|
||||||
|
|
||||||
const handleToggleFullScreenPlayer = (e?: KeyboardEvent | MouseEvent<HTMLDivElement>) => {
|
const handleToggleFullScreenPlayer = (e?: KeyboardEvent | MouseEvent<HTMLDivElement>) => {
|
||||||
e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded });
|
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,
|
isHidden: !isElectron() || !settings.tray,
|
||||||
title: t('setting.startMinimized', { postProcess: 'sentenceCase' }),
|
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} />;
|
return <SettingsSection options={windowOptions} />;
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,7 @@ export interface SettingsState {
|
||||||
disableAutoUpdate: boolean;
|
disableAutoUpdate: boolean;
|
||||||
exitToTray: boolean;
|
exitToTray: boolean;
|
||||||
minimizeToTray: boolean;
|
minimizeToTray: boolean;
|
||||||
|
preventSleepOnPlayback: boolean;
|
||||||
startMinimized: boolean;
|
startMinimized: boolean;
|
||||||
tray: boolean;
|
tray: boolean;
|
||||||
windowBarStyle: Platform;
|
windowBarStyle: Platform;
|
||||||
|
|
@ -664,6 +665,7 @@ const initialState: SettingsState = {
|
||||||
disableAutoUpdate: false,
|
disableAutoUpdate: false,
|
||||||
exitToTray: false,
|
exitToTray: false,
|
||||||
minimizeToTray: false,
|
minimizeToTray: false,
|
||||||
|
preventSleepOnPlayback: false,
|
||||||
startMinimized: false,
|
startMinimized: false,
|
||||||
tray: true,
|
tray: true,
|
||||||
windowBarStyle: platformDefaultWindowBarStyle,
|
windowBarStyle: platformDefaultWindowBarStyle,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue