Files
feishin/src/renderer/hooks/use-sync-settings-to-main.ts
T
2026-01-18 18:53:21 -08:00

149 lines
5.6 KiB
TypeScript

import isElectron from 'is-electron';
import { useEffect, useRef } from 'react';
import i18n from '/@/i18n/i18n';
import { openRestartRequiredToast } from '/@/renderer/features/settings/restart-toast';
import { useSettingsStore } from '/@/renderer/store/settings.store';
import { logFn } from '/@/renderer/utils/logger';
import { logMsg } from '/@/renderer/utils/logger-message';
// Synchronizes settings from the renderer store to the main process electron store
// on app initialization. If there are differences, it updates the main store and shows
// a restart required toast.
export const useSyncSettingsToMain = () => {
const hasRunRef = useRef(false);
useEffect(() => {
if (hasRunRef.current) {
return;
}
if (!isElectron() || !window.api.localSettings) {
hasRunRef.current = true;
return;
}
// Wait some before checking for differences to ensure the store is hydrated from localStorage
const timeoutId = setTimeout(() => {
if (hasRunRef.current) {
return;
}
const settingsFromStore = useSettingsStore.getState();
const settings = {
general: settingsFromStore.general,
hotkeys: settingsFromStore.hotkeys,
lyrics: settingsFromStore.lyrics,
playback: settingsFromStore.playback,
window: settingsFromStore.window,
};
hasRunRef.current = true;
const localSettings = window.api.localSettings;
const settingsMappings: Array<{
mainStoreKey: string;
rendererValue: any;
}> = [
{
mainStoreKey: 'lyrics',
rendererValue: settings.lyrics.sources,
},
{
mainStoreKey: 'window_window_bar_style',
rendererValue: settings.window.windowBarStyle,
},
{
mainStoreKey: 'window_start_minimized',
rendererValue: settings.window.startMinimized,
},
{
mainStoreKey: 'window_exit_to_tray',
rendererValue: settings.window.exitToTray,
},
{
mainStoreKey: 'window_minimize_to_tray',
rendererValue: settings.window.minimizeToTray,
},
{
mainStoreKey: 'disable_auto_updates',
rendererValue: settings.window.disableAutoUpdate,
},
// For some reason after the application is updated, the release channel from the
// renderer is always set to the latest channel. This causes an infinite update loop
// {
// mainStoreKey: 'release_channel',
// rendererValue: settings.window.releaseChannel,
// },
{
mainStoreKey: 'window_enable_tray',
rendererValue: settings.window.tray,
},
{
mainStoreKey: 'password_store',
rendererValue: settings.general.passwordStore,
},
{
mainStoreKey: 'mediaSession',
rendererValue: settings.playback.mediaSession,
},
{
mainStoreKey: 'playbackType',
rendererValue: settings.playback.type,
},
{
mainStoreKey: 'global_media_hotkeys',
rendererValue: settings.hotkeys.globalMediaHotkeys,
},
{
mainStoreKey: 'enableNeteaseTranslation',
rendererValue: settings.lyrics.enableNeteaseTranslation,
},
];
// Compare and sync each setting
(async () => {
let hasDifferences = false;
for (const mapping of settingsMappings) {
const mainValue = await localSettings.get(mapping.mainStoreKey);
const rendererValue = mapping.rendererValue;
const mainValueNormalized = mainValue === undefined ? null : mainValue;
const rendererValueNormalized =
rendererValue === undefined ? null : rendererValue;
if (
JSON.stringify(mainValueNormalized) !==
JSON.stringify(rendererValueNormalized)
) {
hasDifferences = true;
logFn.warn(logMsg.system.settingsSynchronized, {
meta: {
mainStoreKey: mapping.mainStoreKey,
mainValue: mainValueNormalized,
rendererValue: rendererValueNormalized,
},
});
localSettings.set(mapping.mainStoreKey, rendererValue);
}
}
// Show restart toast if there were differences
if (hasDifferences) {
openRestartRequiredToast(
i18n.t('error.settingsSyncError', { postProcess: 'sentenceCase' }),
);
}
})();
}, 5000);
return () => {
clearTimeout(timeoutId);
};
// Only run once on mount
}, []);
};