mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-17 06:00:20 +02:00
feat: macOS menu enhancement (#1903)
This commit is contained in:
+4
-16
@@ -10,9 +10,9 @@ import isElectron from 'is-electron';
|
||||
import { lazy, memo, Suspense, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import i18n from '/@/i18n/i18n';
|
||||
import { openSettingsModal } from '/@/renderer/features/settings/utils/open-settings-modal';
|
||||
import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-context';
|
||||
import { useCheckForUpdates } from '/@/renderer/hooks/use-check-for-updates';
|
||||
import { useNativeMenuSync } from '/@/renderer/hooks/use-native-menu-sync';
|
||||
import { useSyncSettingsToMain } from '/@/renderer/hooks/use-sync-settings-to-main';
|
||||
import { AppRouter } from '/@/renderer/router/app-router';
|
||||
import { useCssSettings, useHotkeySettings, useLanguage } from '/@/renderer/store';
|
||||
@@ -97,7 +97,7 @@ const AppEffects = () => (
|
||||
<CssSettingsEffect />
|
||||
<GlobalShortcutsEffect />
|
||||
<LanguageEffect />
|
||||
<OpenSettingsEffect />
|
||||
<NativeMenuSyncEffect />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -170,20 +170,8 @@ const LanguageEffect = () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const OpenSettingsEffect = () => {
|
||||
useEffect(() => {
|
||||
if (isElectron()) {
|
||||
window.api.utils.rendererOpenSettings(() => {
|
||||
openSettingsModal();
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-open-settings');
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, []);
|
||||
const NativeMenuSyncEffect = () => {
|
||||
useNativeMenuSync();
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import { openModal } from '@mantine/modals';
|
||||
import isElectron from 'is-electron';
|
||||
import { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import packageJson from '../../../package.json';
|
||||
|
||||
import { ServerList } from '/@/renderer/features/servers/components/server-list';
|
||||
import { openSettingsModal } from '/@/renderer/features/settings/utils/open-settings-modal';
|
||||
import { openReleaseNotesModal } from '/@/renderer/release-notes-modal';
|
||||
import {
|
||||
useAppStore,
|
||||
useAppStoreActions,
|
||||
useCommandPalette,
|
||||
usePlayerHydrated,
|
||||
usePlayerRepeat,
|
||||
usePlayerShuffle,
|
||||
usePlayerStatus,
|
||||
} from '/@/renderer/store';
|
||||
import { PlayerShuffle } from '/@/shared/types/types';
|
||||
|
||||
const ipc = isElectron() ? window.api.ipc : null;
|
||||
|
||||
export const useNativeMenuSync = () => {
|
||||
const { t } = useTranslation();
|
||||
const privateMode = useAppStore((state) => state.privateMode);
|
||||
const sidebar = useAppStore((state) => state.sidebar);
|
||||
const { setPrivateMode, setSideBar } = useAppStoreActions();
|
||||
const { open: openCommandPalette } = useCommandPalette();
|
||||
const playerHydrated = usePlayerHydrated();
|
||||
const playerRepeat = usePlayerRepeat();
|
||||
const playerShuffle = usePlayerShuffle();
|
||||
const playerStatus = usePlayerStatus();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererOpenSettings(() => {
|
||||
openSettingsModal();
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-open-settings');
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererOpenCommandPalette(() => {
|
||||
openCommandPalette();
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-open-command-palette');
|
||||
};
|
||||
}, [openCommandPalette]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererOpenManageServers(() => {
|
||||
openModal({
|
||||
children: <ServerList />,
|
||||
title: t('page.manageServers.title', { postProcess: 'titleCase' }),
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-open-manage-servers');
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererTogglePrivateMode(() => {
|
||||
setPrivateMode(!privateMode);
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-toggle-private-mode');
|
||||
};
|
||||
}, [privateMode, setPrivateMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererToggleSidebar(() => {
|
||||
setSideBar({ collapsed: !sidebar.collapsed });
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-toggle-sidebar');
|
||||
};
|
||||
}, [setSideBar, sidebar.collapsed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playerHydrated) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipc?.send('update-playback', playerStatus);
|
||||
ipc?.send('update-repeat', playerRepeat);
|
||||
ipc?.send('update-shuffle', playerShuffle !== PlayerShuffle.NONE);
|
||||
}, [playerHydrated, playerRepeat, playerShuffle, playerStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipc?.send('update-private-mode', privateMode);
|
||||
}, [privateMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipc?.send('update-sidebar-collapsed', sidebar.collapsed);
|
||||
}, [sidebar.collapsed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
window.api.utils.rendererOpenReleaseNotes(() => {
|
||||
openReleaseNotesModal(
|
||||
t('common.newVersion', {
|
||||
postProcess: 'sentenceCase',
|
||||
version: packageJson.version,
|
||||
}) as string,
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-open-release-notes');
|
||||
};
|
||||
}, [t]);
|
||||
};
|
||||
@@ -92,6 +92,7 @@ interface GroupedQueue {
|
||||
}
|
||||
|
||||
interface State {
|
||||
hydrated: boolean;
|
||||
player: {
|
||||
crossfadeDuration: number;
|
||||
crossfadeStyle: CrossfadeStyle;
|
||||
@@ -297,6 +298,7 @@ function regenerateShuffledIndexesIfNeeded(state: {
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
hydrated: false,
|
||||
player: {
|
||||
crossfadeDuration: 5,
|
||||
crossfadeStyle: CrossfadeStyle.EQUAL_POWER,
|
||||
@@ -1564,6 +1566,9 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
return persistedState as Partial<PlayerState>;
|
||||
},
|
||||
name: 'player-store',
|
||||
onRehydrateStorage: () => () => {
|
||||
usePlayerStoreBase.setState({ hydrated: true });
|
||||
},
|
||||
partialize: (state) => {
|
||||
const shouldRestorePlayQueue = useSettingsStore.getState().general.resume;
|
||||
|
||||
@@ -2025,6 +2030,10 @@ export const usePlayerStatus = () => {
|
||||
return usePlayerStoreBase((state) => state.player.status);
|
||||
};
|
||||
|
||||
export const usePlayerHydrated = () => {
|
||||
return usePlayerStoreBase((state) => state.hydrated);
|
||||
};
|
||||
|
||||
export const usePlayerVolume = () => {
|
||||
return usePlayerStoreBase((state) => state.player.volume);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user