[enhancement]: support clearing query and http cache (#475)

* [enhancement]: support clearing query and http cache

  - Adds the ability to invalidate all queries (useful for forcing refresh, and clearing lyrics which are cached forever)
  - [Desktop only] adds the ability to clear the Electron HTTP cache (e.g. cached images)

* use clearer language

* move cache settings to general
This commit is contained in:
Kendall Garner 2024-01-31 06:27:56 +00:00 committed by GitHub
parent 04a468f8c9
commit 9995b2e774
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 119 additions and 2 deletions

View File

@ -396,6 +396,11 @@
"audioExclusiveMode_description": "enable exclusive output mode. In this mode, the system is usually locked out, and only mpv will be able to output audio",
"audioPlayer": "audio player",
"audioPlayer_description": "select the audio player to use for playback",
"clearCache": "Clear browser cache",
"clearCache_description": "A 'hard clear' of Feishin. In addition to clearing Feishin's cache, empty the browser cache (saved images and other assets). Server credentials and settings are preserved.",
"clearQueryCache": "Clear Feishin cache",
"clearQueryCache_description": "A 'soft clear' of Feishin. This will refresh playlists, track metadata, and reset saved lyrics. Settings, server credentials and cached images are preserved.",
"clearCacheSuccess": "cache cleared successfully",
"crossfadeDuration": "crossfade duration",
"crossfadeDuration_description": "sets the duration of the crossfade effect",
"crossfadeStyle": "crossfade style",

View File

@ -260,6 +260,10 @@ const createWindow = async () => {
app.exit();
});
ipcMain.handle('window-clear-cache', async () => {
return mainWindow?.webContents.session.clearCache();
});
ipcMain.on('app-restart', () => {
// Fix for .AppImage
if (process.env.APPIMAGE) {

View File

@ -24,7 +24,12 @@ const devtools = () => {
ipcRenderer.send('window-dev-tools');
};
const clearCache = (): Promise<void> => {
return ipcRenderer.invoke('window-clear-cache');
};
export const browser = {
clearCache,
devtools,
exit,
maximize,
@ -32,3 +37,5 @@ export const browser = {
quit,
unmaximize,
};
export type Browser = typeof browser;

View File

@ -4,6 +4,8 @@ import { ControlSettings } from '/@/renderer/features/settings/components/genera
import { SidebarSettings } from '/@/renderer/features/settings/components/general/sidebar-settings';
import { ThemeSettings } from '/@/renderer/features/settings/components/general/theme-settings';
import { RemoteSettings } from '/@/renderer/features/settings/components/general/remote-settings';
import { CacheSettings } from '/@/renderer/features/settings/components/window/cache-settngs';
import isElectron from 'is-electron';
export const GeneralTab = () => {
return (
@ -15,8 +17,14 @@ export const GeneralTab = () => {
<ControlSettings />
<Divider />
<SidebarSettings />
{isElectron() && (
<>
<Divider />
<RemoteSettings />
</>
)}
<Divider />
<RemoteSettings />
<CacheSettings />
</Stack>
);
};

View File

@ -0,0 +1,92 @@
import { Button } from '@mantine/core';
import { closeAllModals, openModal } from '@mantine/modals';
import { useQueryClient } from '@tanstack/react-query';
import isElectron from 'is-electron';
import { useTranslation } from 'react-i18next';
import { ConfirmModal, toast } from '/@/renderer/components';
import { SettingsOptions } from '/@/renderer/features/settings/components/settings-option';
import { useCallback, useState } from 'react';
const browser = isElectron() ? window.electron.browser : null;
export const CacheSettings = () => {
const [isClearing, setIsClearing] = useState(false);
const queryClient = useQueryClient();
const { t } = useTranslation();
const clearCache = useCallback(
async (full: boolean) => {
setIsClearing(true);
try {
queryClient.clear();
if (full && browser) {
await browser.clearCache();
}
toast.success({
message: t('setting.clearCacheSuccess', { postProcess: 'sentenceCase' }),
});
} catch (error) {
console.error(error);
toast.error({ message: (error as Error).message });
}
setIsClearing(false);
closeAllModals();
},
[queryClient, t],
);
const openResetConfirmModal = (full: boolean) => {
const key = full ? 'clearCache' : 'clearQueryCache';
openModal({
children: (
<ConfirmModal onConfirm={() => clearCache(full)}>
{t(`common.areYouSure`, { postProcess: 'sentenceCase' })}
</ConfirmModal>
),
title: t(`setting.${key}`),
});
};
return (
<>
<SettingsOptions
control={
<Button
compact
disabled={isClearing}
variant="filled"
onClick={() => openResetConfirmModal(false)}
>
{t('common.clear', { postProcess: 'sentenceCase' })}
</Button>
}
description={t('setting.clearQueryCache', {
context: 'description',
})}
title={t('setting.clearQueryCache')}
/>
{browser && (
<SettingsOptions
control={
<Button
compact
disabled={isClearing}
variant="filled"
onClick={() => openResetConfirmModal(true)}
>
{t('common.clear', { postProcess: 'sentenceCase' })}
</Button>
}
description={t('setting.clearCache', {
context: 'description',
})}
title={t('setting.clearCache')}
/>
)}
</>
);
};

View File

@ -9,11 +9,12 @@ import { Utils } from '/@/main/preload/utils';
import { LocalSettings } from '/@/main/preload/local-settings';
import { Ipc } from '/@/main/preload/ipc';
import { DiscordRpc } from '/@/main/preload/discord-rpc';
import { Browser } from '/@/main/preload/browser';
declare global {
interface Window {
electron: {
browser: any;
browser: Browser;
discordRpc: DiscordRpc;
ipc?: Ipc;
ipcRenderer: {