diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 6302791a..b73483bf 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -461,6 +461,8 @@ "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", + "contextMenu": "context menu (right click) configuration", + "contextMenu_description": "allows you to hide items that are shown in the menu when you right click on an item. items that are unchecked will be hidden", "crossfadeDuration": "crossfade duration", "crossfadeDuration_description": "sets the duration of the crossfade effect", "crossfadeStyle": "crossfade style", diff --git a/src/renderer/features/context-menu/context-menu-provider.tsx b/src/renderer/features/context-menu/context-menu-provider.tsx index 35471dcd..ff6d6fe6 100644 --- a/src/renderer/features/context-menu/context-menu-provider.tsx +++ b/src/renderer/features/context-menu/context-menu-provider.tsx @@ -57,6 +57,7 @@ import { useCurrentServer, usePlayerStore, useQueueControls, + useSettingsStore, } from '/@/renderer/store'; import { usePlaybackType } from '/@/renderer/store/settings.store'; import { Play, PlaybackType } from '/@/renderer/types'; @@ -99,6 +100,7 @@ export interface ContextMenuProviderProps { } export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { + const disabledItems = useSettingsStore((state) => state.general.disabledContextMenu); const { t } = useTranslation(); const [opened, setOpened] = useState(false); const clickOutsideRef = useClickOutside(() => setOpened(false)); @@ -927,7 +929,8 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { > {ctx.menuItems?.map((item) => { return ( - !contextMenuItems[item.id].disabled && ( + !contextMenuItems[item.id].disabled && + !disabledItems[item.id] && ( {item.children ? ( { + const disabledItems = useSettingsStore((state) => state.general.disabledContextMenu); + const { toggleContextMenuItem } = useSettingsStoreActions(); + const [open, setOpen] = useState(false); + const { t } = useTranslation(); + + return ( + <> + setOpen(!open)} + > + {t(open ? 'common.close' : 'common.edit', { postProcess: 'titleCase' })} + + } + description={t('setting.contextMenu', { + context: 'description', + postProcess: 'sentenceCase', + })} + title={t('setting.contextMenu', { + postProcess: 'sentenceCase', + })} + /> + {open && ( + + {CONFIGURABLE_CONTEXT_MENU_ITEMS.map((item) => ( + toggleContextMenuItem(item)} + /> + ))} + + )} + + + ); +}; diff --git a/src/renderer/features/settings/components/general/general-tab.tsx b/src/renderer/features/settings/components/general/general-tab.tsx index c1f4bef8..adceee4b 100644 --- a/src/renderer/features/settings/components/general/general-tab.tsx +++ b/src/renderer/features/settings/components/general/general-tab.tsx @@ -8,6 +8,7 @@ import { CacheSettings } from '/@/renderer/features/settings/components/window/c import isElectron from 'is-electron'; import { HomeSettings } from '/@/renderer/features/settings/components/general/home-settings'; import { SidebarReorder } from '/@/renderer/features/settings/components/general/sidebar-reorder'; +import { ContextMenuSettings } from '/@/renderer/features/settings/components/general/context-menu-settings'; export const GeneralTab = () => { return ( @@ -18,6 +19,7 @@ export const GeneralTab = () => { + {isElectron() && } diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index a75a359e..e645bec5 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -24,6 +24,7 @@ import { randomString } from '/@/renderer/utils'; import i18n from '/@/i18n/i18n'; import { usePlayerStore } from '/@/renderer/store/player.store'; import { mergeOverridingColumns } from '/@/renderer/store/utils'; +import type { ContextMenuItemType } from '/@/renderer/features/context-menu'; const utils = isElectron() ? window.electron.utils : null; @@ -196,6 +197,7 @@ export interface SettingsState { albumArtRes?: number | null; buttonSize: number; defaultFullPlaylist: boolean; + disabledContextMenu: { [k in ContextMenuItemType]?: boolean }; doubleClickQueueAll: boolean; externalLinks: boolean; followSystemTheme: boolean; @@ -293,6 +295,7 @@ export interface SettingsSlice extends SettingsState { setSettings: (data: Partial) => void; setSidebarItems: (items: SidebarItemType[]) => void; setTable: (type: TableType, data: DataTableProps) => void; + toggleContextMenuItem: (item: ContextMenuItemType) => void; toggleSidebarCollapseShare: () => void; }; } @@ -324,6 +327,7 @@ const initialState: SettingsState = { albumArtRes: undefined, buttonSize: 20, defaultFullPlaylist: true, + disabledContextMenu: {}, doubleClickQueueAll: true, externalLinks: true, followSystemTheme: false, @@ -648,6 +652,12 @@ export const useSettingsStore = create()( state.tables[type] = data; }); }, + toggleContextMenuItem: (item: ContextMenuItemType) => { + set((state) => { + state.general.disabledContextMenu[item] = + !state.general.disabledContextMenu[item]; + }); + }, toggleSidebarCollapseShare: () => { set((state) => { state.general.sidebarCollapseShared =