[enhancement]: Support disabling MPV entirely
Supports running Feishin solely using web audio (useful for clients with problems with MPV). Also moves save/restore queue to utils, as MPV object is now optional
This commit is contained in:
parent
ae8fc6df13
commit
f82da2e76b
10 changed files with 127 additions and 74 deletions
|
@ -428,6 +428,8 @@
|
||||||
"customFontPath_description": "sets the path to the custom font to use for the application",
|
"customFontPath_description": "sets the path to the custom font to use for the application",
|
||||||
"disableAutomaticUpdates": "disable automatic updates",
|
"disableAutomaticUpdates": "disable automatic updates",
|
||||||
"disableLibraryUpdateOnStartup": "disable checking for new versions on startup",
|
"disableLibraryUpdateOnStartup": "disable checking for new versions on startup",
|
||||||
|
"disableMpv": "Disable MPV",
|
||||||
|
"disableMpv_description": "If checked, prevent MPV from starting and bypass MPV requirement.",
|
||||||
"discordApplicationId": "{{discord}} application id",
|
"discordApplicationId": "{{discord}} application id",
|
||||||
"discordApplicationId_description": "the application id for {{discord}} rich presence (defaults to {{defaultId}})",
|
"discordApplicationId_description": "the application id for {{discord}} rich presence (defaults to {{defaultId}})",
|
||||||
"discordIdleStatus": "show rich presence idle status",
|
"discordIdleStatus": "show rich presence idle status",
|
||||||
|
|
|
@ -316,7 +316,7 @@ const createWindow = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const queue = JSON.parse(data.toString());
|
const queue = JSON.parse(data.toString());
|
||||||
getMainWindow()?.webContents.send('renderer-player-restore-queue', queue);
|
getMainWindow()?.webContents.send('renderer-restore-queue', queue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -362,7 +362,7 @@ const createWindow = async () => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
saved = true;
|
saved = true;
|
||||||
|
|
||||||
getMainWindow()?.webContents.send('renderer-player-save-queue');
|
getMainWindow()?.webContents.send('renderer-save-queue');
|
||||||
|
|
||||||
ipcMain.once('player-save-queue', async (_event, data: Record<string, any>) => {
|
ipcMain.once('player-save-queue', async (_event, data: Record<string, any>) => {
|
||||||
const queueLocation = join(app.getPath('userData'), 'queue');
|
const queueLocation = join(app.getPath('userData'), 'queue');
|
||||||
|
|
|
@ -9,6 +9,8 @@ import { mpvPlayer, mpvPlayerListener } from './preload/mpv-player';
|
||||||
import { remote } from './preload/remote';
|
import { remote } from './preload/remote';
|
||||||
import { utils } from './preload/utils';
|
import { utils } from './preload/utils';
|
||||||
|
|
||||||
|
const disableMpv = localSettings.get('disable_mpv');
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electron', {
|
contextBridge.exposeInMainWorld('electron', {
|
||||||
browser,
|
browser,
|
||||||
discordRpc,
|
discordRpc,
|
||||||
|
@ -16,8 +18,8 @@ contextBridge.exposeInMainWorld('electron', {
|
||||||
localSettings,
|
localSettings,
|
||||||
lyrics,
|
lyrics,
|
||||||
mpris,
|
mpris,
|
||||||
mpvPlayer,
|
mpvPlayer: disableMpv ? undefined : mpvPlayer,
|
||||||
mpvPlayerListener,
|
mpvPlayerListener: disableMpv ? undefined : mpvPlayerListener,
|
||||||
remote,
|
remote,
|
||||||
utils,
|
utils,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
||||||
import { PlayerData, PlayerState } from '/@/renderer/store';
|
import { PlayerData } from '/@/renderer/store';
|
||||||
|
|
||||||
const initialize = (data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
|
const initialize = (data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
|
||||||
return ipcRenderer.invoke('player-initialize', data);
|
return ipcRenderer.invoke('player-initialize', data);
|
||||||
|
@ -50,14 +50,6 @@ const previous = () => {
|
||||||
ipcRenderer.send('player-previous');
|
ipcRenderer.send('player-previous');
|
||||||
};
|
};
|
||||||
|
|
||||||
const restoreQueue = () => {
|
|
||||||
ipcRenderer.send('player-restore-queue');
|
|
||||||
};
|
|
||||||
|
|
||||||
const saveQueue = (data: Record<string, any>) => {
|
|
||||||
ipcRenderer.send('player-save-queue', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
const seek = (seconds: number) => {
|
const seek = (seconds: number) => {
|
||||||
ipcRenderer.send('player-seek', seconds);
|
ipcRenderer.send('player-seek', seconds);
|
||||||
};
|
};
|
||||||
|
@ -154,16 +146,6 @@ const rendererQuit = (cb: (event: IpcRendererEvent) => void) => {
|
||||||
ipcRenderer.on('renderer-player-quit', cb);
|
ipcRenderer.on('renderer-player-quit', cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
const rendererSaveQueue = (cb: (event: IpcRendererEvent) => void) => {
|
|
||||||
ipcRenderer.on('renderer-player-save-queue', cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
const rendererRestoreQueue = (
|
|
||||||
cb: (event: IpcRendererEvent, data: Partial<PlayerState>) => void,
|
|
||||||
) => {
|
|
||||||
ipcRenderer.on('renderer-player-restore-queue', cb);
|
|
||||||
};
|
|
||||||
|
|
||||||
const rendererError = (cb: (event: IpcRendererEvent, data: string) => void) => {
|
const rendererError = (cb: (event: IpcRendererEvent, data: string) => void) => {
|
||||||
ipcRenderer.on('renderer-player-error', cb);
|
ipcRenderer.on('renderer-player-error', cb);
|
||||||
};
|
};
|
||||||
|
@ -182,8 +164,6 @@ export const mpvPlayer = {
|
||||||
previous,
|
previous,
|
||||||
quit,
|
quit,
|
||||||
restart,
|
restart,
|
||||||
restoreQueue,
|
|
||||||
saveQueue,
|
|
||||||
seek,
|
seek,
|
||||||
seekTo,
|
seekTo,
|
||||||
setProperties,
|
setProperties,
|
||||||
|
@ -203,8 +183,6 @@ export const mpvPlayerListener = {
|
||||||
rendererPlayPause,
|
rendererPlayPause,
|
||||||
rendererPrevious,
|
rendererPrevious,
|
||||||
rendererQuit,
|
rendererQuit,
|
||||||
rendererRestoreQueue,
|
|
||||||
rendererSaveQueue,
|
|
||||||
rendererSkipBackward,
|
rendererSkipBackward,
|
||||||
rendererSkipForward,
|
rendererSkipForward,
|
||||||
rendererStop,
|
rendererStop,
|
||||||
|
|
|
@ -1,9 +1,31 @@
|
||||||
|
import { IpcRendererEvent, ipcRenderer } from 'electron';
|
||||||
import { isMacOS, isWindows, isLinux } from '../utils';
|
import { isMacOS, isWindows, isLinux } from '../utils';
|
||||||
|
import { PlayerState } from '/@/renderer/store';
|
||||||
|
|
||||||
|
const saveQueue = (data: Record<string, any>) => {
|
||||||
|
ipcRenderer.send('player-save-queue', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreQueue = () => {
|
||||||
|
ipcRenderer.send('player-restore-queue');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSaveQueue = (cb: (event: IpcRendererEvent) => void) => {
|
||||||
|
ipcRenderer.on('renderer-save-queue', cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRestoreQueue = (cb: (event: IpcRendererEvent, data: Partial<PlayerState>) => void) => {
|
||||||
|
ipcRenderer.on('renderer-restore-queue', cb);
|
||||||
|
};
|
||||||
|
|
||||||
export const utils = {
|
export const utils = {
|
||||||
isLinux,
|
isLinux,
|
||||||
isMacOS,
|
isMacOS,
|
||||||
isWindows,
|
isWindows,
|
||||||
|
onRestoreQueue,
|
||||||
|
onSaveQueue,
|
||||||
|
restoreQueue,
|
||||||
|
saveQueue,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Utils = typeof utils;
|
export type Utils = typeof utils;
|
||||||
|
|
|
@ -33,9 +33,9 @@ ModuleRegistry.registerModules([ClientSideRowModelModule, InfiniteRowModelModule
|
||||||
initSimpleImg({ threshold: 0.05 }, true);
|
initSimpleImg({ threshold: 0.05 }, true);
|
||||||
|
|
||||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||||
const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null;
|
|
||||||
const ipc = isElectron() ? window.electron.ipc : null;
|
const ipc = isElectron() ? window.electron.ipc : null;
|
||||||
const remote = isElectron() ? window.electron.remote : null;
|
const remote = isElectron() ? window.electron.remote : null;
|
||||||
|
const utils = isElectron() ? window.electron.utils : null;
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
@ -97,28 +97,31 @@ export const App = () => {
|
||||||
// Start the mpv instance on startup
|
// Start the mpv instance on startup
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeMpv = async () => {
|
const initializeMpv = async () => {
|
||||||
const isRunning: boolean | undefined = await mpvPlayer?.isRunning();
|
if (playbackType === PlaybackType.LOCAL) {
|
||||||
|
const isRunning: boolean | undefined = await mpvPlayer?.isRunning();
|
||||||
|
|
||||||
mpvPlayer?.stop();
|
mpvPlayer?.stop();
|
||||||
|
|
||||||
if (!isRunning) {
|
if (!isRunning) {
|
||||||
const extraParameters = useSettingsStore.getState().playback.mpvExtraParameters;
|
const extraParameters = useSettingsStore.getState().playback.mpvExtraParameters;
|
||||||
const properties: Record<string, any> = {
|
const properties: Record<string, any> = {
|
||||||
speed: usePlayerStore.getState().current.speed,
|
speed: usePlayerStore.getState().current.speed,
|
||||||
...getMpvProperties(useSettingsStore.getState().playback.mpvProperties),
|
...getMpvProperties(useSettingsStore.getState().playback.mpvProperties),
|
||||||
};
|
};
|
||||||
|
|
||||||
await mpvPlayer?.initialize({
|
await mpvPlayer?.initialize({
|
||||||
extraParameters,
|
extraParameters,
|
||||||
properties,
|
properties,
|
||||||
});
|
});
|
||||||
|
|
||||||
mpvPlayer?.volume(properties.volume);
|
mpvPlayer?.volume(properties.volume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mpvPlayer?.restoreQueue();
|
|
||||||
|
utils?.restoreQueue();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isElectron() && playbackType === PlaybackType.LOCAL) {
|
if (isElectron()) {
|
||||||
initializeMpv();
|
initializeMpv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +139,8 @@ export const App = () => {
|
||||||
}, [bindings]);
|
}, [bindings]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isElectron()) {
|
if (utils) {
|
||||||
mpvPlayerListener!.rendererSaveQueue(() => {
|
utils.onSaveQueue(() => {
|
||||||
const { current, queue } = usePlayerStore.getState();
|
const { current, queue } = usePlayerStore.getState();
|
||||||
const stateToSave: Partial<Pick<PlayerState, 'current' | 'queue'>> = {
|
const stateToSave: Partial<Pick<PlayerState, 'current' | 'queue'>> = {
|
||||||
current: {
|
current: {
|
||||||
|
@ -146,10 +149,10 @@ export const App = () => {
|
||||||
},
|
},
|
||||||
queue,
|
queue,
|
||||||
};
|
};
|
||||||
mpvPlayer!.saveQueue(stateToSave);
|
utils.saveQueue(stateToSave);
|
||||||
});
|
});
|
||||||
|
|
||||||
mpvPlayerListener!.rendererRestoreQueue((_event: any, data) => {
|
utils.onRestoreQueue((_event: any, data) => {
|
||||||
const playerData = restoreQueue(data);
|
const playerData = restoreQueue(data);
|
||||||
if (playbackType === PlaybackType.LOCAL) {
|
if (playbackType === PlaybackType.LOCAL) {
|
||||||
mpvPlayer!.setQueue(playerData, true);
|
mpvPlayer!.setQueue(playerData, true);
|
||||||
|
@ -158,8 +161,8 @@ export const App = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
ipc?.removeAllListeners('renderer-player-restore-queue');
|
ipc?.removeAllListeners('renderer-restore-queue');
|
||||||
ipc?.removeAllListeners('renderer-player-save-queue');
|
ipc?.removeAllListeners('renderer-save-queue');
|
||||||
};
|
};
|
||||||
}, [playbackType, restoreQueue]);
|
}, [playbackType, restoreQueue]);
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,36 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
import { FileInput, Text, Button } from '/@/renderer/components';
|
import { FileInput, Text, Button, Checkbox } from '/@/renderer/components';
|
||||||
|
import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store';
|
||||||
|
import { PlaybackType } from '/@/renderer/types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const localSettings = isElectron() ? window.electron.localSettings : null;
|
const localSettings = isElectron() ? window.electron.localSettings : null;
|
||||||
|
|
||||||
export const MpvRequired = () => {
|
export const MpvRequired = () => {
|
||||||
const [mpvPath, setMpvPath] = useState('');
|
const [mpvPath, setMpvPath] = useState('');
|
||||||
|
const settings = usePlaybackSettings();
|
||||||
|
const { setSettings } = useSettingsStoreActions();
|
||||||
|
const [disabled, setDisabled] = useState(false);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleSetMpvPath = (e: File) => {
|
const handleSetMpvPath = (e: File) => {
|
||||||
localSettings?.set('mpv_path', e.path);
|
localSettings?.set('mpv_path', e.path);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const handleSetDisableMpv = (disabled: boolean) => {
|
||||||
const getMpvPath = async () => {
|
setDisabled(disabled);
|
||||||
if (!localSettings) return setMpvPath('');
|
localSettings?.set('disable_mpv', disabled);
|
||||||
const mpvPath = localSettings.get('mpv_path') as string;
|
|
||||||
return setMpvPath(mpvPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
getMpvPath();
|
setSettings({
|
||||||
|
playback: { ...settings, type: disabled ? PlaybackType.WEB : PlaybackType.LOCAL },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!localSettings) return setMpvPath('');
|
||||||
|
const mpvPath = localSettings.get('mpv_path') as string;
|
||||||
|
return setMpvPath(mpvPath);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -34,9 +47,15 @@ export const MpvRequired = () => {
|
||||||
</a>
|
</a>
|
||||||
</Text>
|
</Text>
|
||||||
<FileInput
|
<FileInput
|
||||||
|
disabled={disabled}
|
||||||
placeholder={mpvPath}
|
placeholder={mpvPath}
|
||||||
onChange={handleSetMpvPath}
|
onChange={handleSetMpvPath}
|
||||||
/>
|
/>
|
||||||
|
<Text>{t('setting.disable_mpv', { context: 'description' })}</Text>
|
||||||
|
<Checkbox
|
||||||
|
label={t('setting.disableMpv')}
|
||||||
|
onChange={(e) => handleSetDisableMpv(e.currentTarget.checked)}
|
||||||
|
/>
|
||||||
<Button onClick={() => localSettings?.restart()}>Restart</Button>
|
<Button onClick={() => localSettings?.restart()}>Restart</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState, useEffect } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Center, Group, Stack } from '@mantine/core';
|
import { Center, Group, Stack } from '@mantine/core';
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -18,23 +18,19 @@ const localSettings = isElectron() ? window.electron.localSettings : null;
|
||||||
const ActionRequiredRoute = () => {
|
const ActionRequiredRoute = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const currentServer = useCurrentServer();
|
const currentServer = useCurrentServer();
|
||||||
const [isMpvRequired, setIsMpvRequired] = useState(false);
|
|
||||||
const isServerRequired = !currentServer;
|
const isServerRequired = !currentServer;
|
||||||
const isCredentialRequired = false;
|
const isCredentialRequired = false;
|
||||||
|
|
||||||
useEffect(() => {
|
const isMpvRequired = useMemo(() => {
|
||||||
const getMpvPath = async () => {
|
if (!localSettings) return false;
|
||||||
if (!localSettings) return setIsMpvRequired(false);
|
|
||||||
const mpvPath = await localSettings.get('mpv_path');
|
|
||||||
|
|
||||||
if (mpvPath) {
|
const mpvPath = localSettings.get('mpv_path');
|
||||||
return setIsMpvRequired(false);
|
if (mpvPath) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return setIsMpvRequired(true);
|
const mpvDisabled = localSettings.get('disable_mpv');
|
||||||
};
|
return !mpvDisabled;
|
||||||
|
|
||||||
getMpvPath();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const checks = [
|
const checks = [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { SelectItem } from '@mantine/core';
|
import { SelectItem } from '@mantine/core';
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
import { Select, Slider, toast } from '/@/renderer/components';
|
import { Checkbox, Select, Slider, toast } from '/@/renderer/components';
|
||||||
import {
|
import {
|
||||||
SettingsSection,
|
SettingsSection,
|
||||||
SettingOption,
|
SettingOption,
|
||||||
|
@ -12,12 +12,15 @@ import { PlaybackType, PlayerStatus, PlaybackStyle, CrossfadeStyle } from '/@/re
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||||
|
const localSettings = isElectron() ? window.electron.localSettings : null;
|
||||||
|
|
||||||
const getAudioDevice = async () => {
|
const getAudioDevice = async () => {
|
||||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
return (devices || []).filter((dev: MediaDeviceInfo) => dev.kind === 'audiooutput');
|
return (devices || []).filter((dev: MediaDeviceInfo) => dev.kind === 'audiooutput');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initialDisable = (localSettings?.get('disable_mpv') as boolean | undefined) ?? false;
|
||||||
|
|
||||||
export const AudioSettings = () => {
|
export const AudioSettings = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const settings = usePlaybackSettings();
|
const settings = usePlaybackSettings();
|
||||||
|
@ -25,6 +28,18 @@ export const AudioSettings = () => {
|
||||||
const status = useCurrentStatus();
|
const status = useCurrentStatus();
|
||||||
|
|
||||||
const [audioDevices, setAudioDevices] = useState<SelectItem[]>([]);
|
const [audioDevices, setAudioDevices] = useState<SelectItem[]>([]);
|
||||||
|
const [disableMpv, setDisableMpv] = useState(initialDisable);
|
||||||
|
|
||||||
|
const handleSetDisableMpv = (disabled: boolean) => {
|
||||||
|
setDisableMpv(disabled);
|
||||||
|
localSettings?.set('disable_mpv', disabled);
|
||||||
|
|
||||||
|
if (disabled) {
|
||||||
|
setSettings({
|
||||||
|
playback: { ...settings, type: disabled ? PlaybackType.WEB : PlaybackType.LOCAL },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getAudioDevices = () => {
|
const getAudioDevices = () => {
|
||||||
|
@ -45,6 +60,18 @@ export const AudioSettings = () => {
|
||||||
}, [settings.type, t]);
|
}, [settings.type, t]);
|
||||||
|
|
||||||
const audioOptions: SettingOption[] = [
|
const audioOptions: SettingOption[] = [
|
||||||
|
{
|
||||||
|
control: (
|
||||||
|
<Checkbox
|
||||||
|
defaultChecked={disableMpv}
|
||||||
|
onChange={(e) => handleSetDisableMpv(e.currentTarget.checked)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
description: t('setting.disableMpv', { context: 'description' }),
|
||||||
|
isHidden: !isElectron(),
|
||||||
|
note: t('common.restartRequired', { postProcess: 'sentenceCase' }),
|
||||||
|
title: t('setting.disableMpv'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
control: (
|
control: (
|
||||||
<Select
|
<Select
|
||||||
|
@ -71,7 +98,7 @@ export const AudioSettings = () => {
|
||||||
context: 'description',
|
context: 'description',
|
||||||
postProcess: 'sentenceCase',
|
postProcess: 'sentenceCase',
|
||||||
}),
|
}),
|
||||||
isHidden: !isElectron(),
|
isHidden: !isElectron() || initialDisable || disableMpv,
|
||||||
note:
|
note:
|
||||||
status === PlayerStatus.PLAYING
|
status === PlayerStatus.PLAYING
|
||||||
? t('common.playerMustBePaused', { postProcess: 'sentenceCase' })
|
? t('common.playerMustBePaused', { postProcess: 'sentenceCase' })
|
||||||
|
|
|
@ -13,8 +13,12 @@ export const AppOutlet = () => {
|
||||||
const isMpvRequired = () => {
|
const isMpvRequired = () => {
|
||||||
if (!localSettings) return false;
|
if (!localSettings) return false;
|
||||||
const mpvPath = localSettings.get('mpv_path');
|
const mpvPath = localSettings.get('mpv_path');
|
||||||
if (mpvPath) return false;
|
if (mpvPath) {
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mpvDisabled = localSettings.get('disable_mpv');
|
||||||
|
return !mpvDisabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isServerRequired = !currentServer;
|
const isServerRequired = !currentServer;
|
||||||
|
|
Reference in a new issue