diff --git a/src/store/authCacheStorageActions.ts b/src/store/authCacheStorageActions.ts new file mode 100644 index 00000000..2cf5de82 --- /dev/null +++ b/src/store/authCacheStorageActions.ts @@ -0,0 +1,26 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +export function createCacheStorageActions(set: SetState): Pick< + AuthState, + | 'setMaxCacheMb' + | 'setDownloadFolder' + | 'setOfflineDownloadDir' + | 'setHotCacheEnabled' + | 'setHotCacheMaxMb' + | 'setHotCacheDebounceSec' + | 'setHotCacheDownloadDir' +> { + return { + setMaxCacheMb: (v) => set({ maxCacheMb: v }), + setDownloadFolder: (v) => set({ downloadFolder: v }), + setOfflineDownloadDir: (v) => set({ offlineDownloadDir: v }), + setHotCacheEnabled: (v) => set({ hotCacheEnabled: v }), + setHotCacheMaxMb: (v) => set({ hotCacheMaxMb: v }), + setHotCacheDebounceSec: (v) => set({ hotCacheDebounceSec: v }), + setHotCacheDownloadDir: (v) => set({ hotCacheDownloadDir: v }), + }; +} diff --git a/src/store/authDiscordSettingsActions.ts b/src/store/authDiscordSettingsActions.ts new file mode 100644 index 00000000..25d1462e --- /dev/null +++ b/src/store/authDiscordSettingsActions.ts @@ -0,0 +1,24 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +export function createDiscordSettingsActions(set: SetState): Pick< + AuthState, + | 'setDiscordRichPresence' + | 'setDiscordCoverSource' + | 'setEnableBandsintown' + | 'setDiscordTemplateDetails' + | 'setDiscordTemplateState' + | 'setDiscordTemplateLargeText' +> { + return { + setDiscordRichPresence: (v) => set({ discordRichPresence: v }), + setDiscordCoverSource: (v) => set({ discordCoverSource: v }), + setEnableBandsintown: (v) => set({ enableBandsintown: v }), + setDiscordTemplateDetails: (v) => set({ discordTemplateDetails: v }), + setDiscordTemplateState: (v) => set({ discordTemplateState: v }), + setDiscordTemplateLargeText: (v) => set({ discordTemplateLargeText: v }), + }; +} diff --git a/src/store/authDiscoveryActions.ts b/src/store/authDiscoveryActions.ts new file mode 100644 index 00000000..ebe5b49b --- /dev/null +++ b/src/store/authDiscoveryActions.ts @@ -0,0 +1,38 @@ +import { clampMixFilterMinStars, clampRandomMixSize } from './authStoreHelpers'; +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +/** + * Discovery + auto-queue settings: mix min-rating thresholds (each + * clamped to 0…3 stars), random-mix size (snapped to the allowed + * RANDOM_MIX_SIZE_OPTIONS bucket), lucky-mix sidebar visibility, + * random-nav style, infinite-queue + preserve-play-next-order + * toggles. + */ +export function createDiscoveryActions(set: SetState): Pick< + AuthState, + | 'setMixMinRatingFilterEnabled' + | 'setMixMinRatingSong' + | 'setMixMinRatingAlbum' + | 'setMixMinRatingArtist' + | 'setRandomMixSize' + | 'setShowLuckyMixMenu' + | 'setRandomNavMode' + | 'setInfiniteQueueEnabled' + | 'setPreservePlayNextOrder' +> { + return { + setMixMinRatingFilterEnabled: (v) => set({ mixMinRatingFilterEnabled: v }), + setMixMinRatingSong: (v) => set({ mixMinRatingSong: clampMixFilterMinStars(v) }), + setMixMinRatingAlbum: (v) => set({ mixMinRatingAlbum: clampMixFilterMinStars(v) }), + setMixMinRatingArtist: (v) => set({ mixMinRatingArtist: clampMixFilterMinStars(v) }), + setRandomMixSize: (v) => set({ randomMixSize: clampRandomMixSize(v) }), + setShowLuckyMixMenu: (v) => set({ showLuckyMixMenu: v }), + setRandomNavMode: (v) => set({ randomNavMode: v }), + setInfiniteQueueEnabled: (v) => set({ infiniteQueueEnabled: v }), + setPreservePlayNextOrder: (v) => set({ preservePlayNextOrder: v }), + }; +} diff --git a/src/store/authLyricsSettingsActions.ts b/src/store/authLyricsSettingsActions.ts new file mode 100644 index 00000000..311d9d70 --- /dev/null +++ b/src/store/authLyricsSettingsActions.ts @@ -0,0 +1,28 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +/** + * Lyrics fetch-pipeline settings: source order/enablement, mode + * (standard pipeline vs lyricsplus first), and the static-only + * rendering toggle. Visual lyrics chrome (rail vs apple, + * fullscreen show/hide) lives in `authUiAppearanceActions.ts`. + */ +export function createLyricsSettingsActions(set: SetState): Pick< + AuthState, + | 'setLyricsServerFirst' + | 'setEnableNeteaselyrics' + | 'setLyricsSources' + | 'setLyricsMode' + | 'setLyricsStaticOnly' +> { + return { + setLyricsServerFirst: (v) => set({ lyricsServerFirst: v }), + setEnableNeteaselyrics: (v) => set({ enableNeteaselyrics: v }), + setLyricsSources: (sources) => set({ lyricsSources: sources }), + setLyricsMode: (v) => set({ lyricsMode: v }), + setLyricsStaticOnly: (v) => set({ lyricsStaticOnly: v }), + }; +} diff --git a/src/store/authPlumbingActions.ts b/src/store/authPlumbingActions.ts new file mode 100644 index 00000000..b57fc6bb --- /dev/null +++ b/src/store/authPlumbingActions.ts @@ -0,0 +1,29 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +/** + * Persistent plumbing settings that don't fit a more specific domain: + * runtime logging level, Navidrome `getNowPlaying` toggle, preload + * mode + custom seconds, audiobook exclusion, genre blacklist. + */ +export function createPlumbingSettingsActions(set: SetState): Pick< + AuthState, + | 'setLoggingMode' + | 'setNowPlayingEnabled' + | 'setPreloadMode' + | 'setPreloadCustomSeconds' + | 'setExcludeAudiobooks' + | 'setCustomGenreBlacklist' +> { + return { + setLoggingMode: (v) => set({ loggingMode: v }), + setNowPlayingEnabled: (v) => set({ nowPlayingEnabled: v }), + setPreloadMode: (v) => set({ preloadMode: v }), + setPreloadCustomSeconds: (v) => set({ preloadCustomSeconds: v }), + setExcludeAudiobooks: (v) => set({ excludeAudiobooks: v }), + setCustomGenreBlacklist: (v) => set({ customGenreBlacklist: v }), + }; +} diff --git a/src/store/authStore.ts b/src/store/authStore.ts index 98ddb718..41d2f15a 100644 --- a/src/store/authStore.ts +++ b/src/store/authStore.ts @@ -10,7 +10,14 @@ import { } from '../utils/loudnessPreAnalysisSlider'; import { createAudioSettingsActions } from './authAudioSettingsActions'; import { createAuthLastfmActions } from './authLastfmActions'; +import { createCacheStorageActions } from './authCacheStorageActions'; +import { createDiscordSettingsActions } from './authDiscordSettingsActions'; +import { createDiscoveryActions } from './authDiscoveryActions'; +import { createLyricsSettingsActions } from './authLyricsSettingsActions'; +import { createPlumbingSettingsActions } from './authPlumbingActions'; import { createServerProfileActions } from './authServerProfileActions'; +import { createTrackPreviewActions } from './authTrackPreviewActions'; +import { createUiAppearanceActions } from './authUiAppearanceActions'; import { DEFAULT_LOUDNESS_PRE_ANALYSIS_ATTENUATION_DB, DEFAULT_LYRICS_SOURCES, @@ -129,56 +136,13 @@ export const useAuthStore = create()( ...createServerProfileActions(set), ...createAuthLastfmActions(set), ...createAudioSettingsActions(set), - - setMaxCacheMb: (v) => set({ maxCacheMb: v }), - setDownloadFolder: (v) => set({ downloadFolder: v }), - setOfflineDownloadDir: (v) => set({ offlineDownloadDir: v }), - setExcludeAudiobooks: (v) => set({ excludeAudiobooks: v }), - setCustomGenreBlacklist: (v) => set({ customGenreBlacklist: v }), - setTrackPreviewsEnabled: (v) => set({ trackPreviewsEnabled: !!v }), - setTrackPreviewLocation: (location, enabled) => set(state => ({ - trackPreviewLocations: { ...state.trackPreviewLocations, [location]: !!enabled }, - })), - setTrackPreviewStartRatio: (v) => set({ trackPreviewStartRatio: Math.max(0, Math.min(0.9, v)) }), - setTrackPreviewDurationSec: (v) => set({ trackPreviewDurationSec: Math.max(5, Math.min(120, Math.round(v))) }), - setPreloadMode: (v: 'off' | 'balanced' | 'early' | 'custom') => set({ preloadMode: v }), - setPreloadCustomSeconds: (v: number) => set({ preloadCustomSeconds: v }), - setInfiniteQueueEnabled: (v) => set({ infiniteQueueEnabled: v }), - setPreservePlayNextOrder: (v) => set({ preservePlayNextOrder: v }), - setShowArtistImages: (v) => set({ showArtistImages: v }), - setShowTrayIcon: (v) => set({ showTrayIcon: v }), - setMinimizeToTray: (v) => set({ minimizeToTray: v }), - setShowOrbitTrigger: (v) => set({ showOrbitTrigger: v }), - setDiscordRichPresence: (v) => set({ discordRichPresence: v }), - setDiscordCoverSource: (v) => set({ discordCoverSource: v }), - setEnableBandsintown: (v) => set({ enableBandsintown: v }), - setDiscordTemplateDetails: (v) => set({ discordTemplateDetails: v }), - setDiscordTemplateState: (v) => set({ discordTemplateState: v }), - setDiscordTemplateLargeText: (v) => set({ discordTemplateLargeText: v }), - setUseCustomTitlebar: (v) => set({ useCustomTitlebar: v }), - setPreloadMiniPlayer: (v) => set({ preloadMiniPlayer: v }), - setLinuxWebkitKineticScroll: (v) => set({ linuxWebkitKineticScroll: v }), - setLoggingMode: (v) => set({ loggingMode: v }), - setNowPlayingEnabled: (v) => set({ nowPlayingEnabled: v }), - setLyricsServerFirst: (v: boolean) => set({ lyricsServerFirst: v }), - setEnableNeteaselyrics: (v: boolean) => set({ enableNeteaselyrics: v }), - setLyricsSources: (sources) => set({ lyricsSources: sources }), - setLyricsMode: (v) => set({ lyricsMode: v }), - setLyricsStaticOnly: (v) => set({ lyricsStaticOnly: v }), - setShowFullscreenLyrics: (v: boolean) => set({ showFullscreenLyrics: v }), - setFsLyricsStyle: (v) => set({ fsLyricsStyle: v }), - setSidebarLyricsStyle: (v) => set({ sidebarLyricsStyle: v }), - setShowFsArtistPortrait: (v: boolean) => set({ showFsArtistPortrait: v }), - setFsPortraitDim: (v: number) => set({ fsPortraitDim: v }), - setShowChangelogOnUpdate: (v) => set({ showChangelogOnUpdate: v }), - setLastSeenChangelogVersion: (v) => set({ lastSeenChangelogVersion: v }), - - setSeekbarStyle: (v) => set({ seekbarStyle: v }), - setQueueNowPlayingCollapsed: (v: boolean) => set({ queueNowPlayingCollapsed: v }), - setHotCacheEnabled: (v) => set({ hotCacheEnabled: v }), - setHotCacheMaxMb: (v) => set({ hotCacheMaxMb: v }), - setHotCacheDebounceSec: (v) => set({ hotCacheDebounceSec: v }), - setHotCacheDownloadDir: (v) => set({ hotCacheDownloadDir: v }), + ...createCacheStorageActions(set), + ...createDiscordSettingsActions(set), + ...createUiAppearanceActions(set), + ...createLyricsSettingsActions(set), + ...createTrackPreviewActions(set), + ...createDiscoveryActions(set), + ...createPlumbingSettingsActions(set), setSkipStarOnManualSkipsEnabled: (v) => set({ @@ -213,14 +177,6 @@ export const useAuthStore = create()( set({ skipStarManualSkipCountsByKey: rest }); }, - setMixMinRatingFilterEnabled: (v) => set({ mixMinRatingFilterEnabled: v }), - setMixMinRatingSong: (v) => set({ mixMinRatingSong: clampMixFilterMinStars(v) }), - setMixMinRatingAlbum: (v) => set({ mixMinRatingAlbum: clampMixFilterMinStars(v) }), - setMixMinRatingArtist: (v) => set({ mixMinRatingArtist: clampMixFilterMinStars(v) }), - setRandomMixSize: (v) => set({ randomMixSize: clampRandomMixSize(v) }), - setShowLuckyMixMenu: (v) => set({ showLuckyMixMenu: v }), - setRandomNavMode: (v) => set({ randomNavMode: v }), - setMusicFolders: (folders) => { const sid = get().activeServerId; set(s => { diff --git a/src/store/authTrackPreviewActions.ts b/src/store/authTrackPreviewActions.ts new file mode 100644 index 00000000..5c9a4384 --- /dev/null +++ b/src/store/authTrackPreviewActions.ts @@ -0,0 +1,27 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +/** + * Track-preview settings. `setTrackPreviewStartRatio` clamps to + * 0…0.9 (preview window can't start past 90% of the track) and + * `setTrackPreviewDurationSec` clamps to 5…120 seconds. + */ +export function createTrackPreviewActions(set: SetState): Pick< + AuthState, + | 'setTrackPreviewsEnabled' + | 'setTrackPreviewLocation' + | 'setTrackPreviewStartRatio' + | 'setTrackPreviewDurationSec' +> { + return { + setTrackPreviewsEnabled: (v) => set({ trackPreviewsEnabled: !!v }), + setTrackPreviewLocation: (location, enabled) => set(state => ({ + trackPreviewLocations: { ...state.trackPreviewLocations, [location]: !!enabled }, + })), + setTrackPreviewStartRatio: (v) => set({ trackPreviewStartRatio: Math.max(0, Math.min(0.9, v)) }), + setTrackPreviewDurationSec: (v) => set({ trackPreviewDurationSec: Math.max(5, Math.min(120, Math.round(v))) }), + }; +} diff --git a/src/store/authUiAppearanceActions.ts b/src/store/authUiAppearanceActions.ts new file mode 100644 index 00000000..477b83f5 --- /dev/null +++ b/src/store/authUiAppearanceActions.ts @@ -0,0 +1,49 @@ +import type { AuthState } from './authStoreTypes'; + +type SetState = ( + partial: Partial | ((state: AuthState) => Partial), +) => void; + +/** + * Visual / chrome settings. Pure pass-through setters: tray, titlebar, + * sidebar toggles, fullscreen lyrics rendering options, changelog + * banner. No side effects. + */ +export function createUiAppearanceActions(set: SetState): Pick< + AuthState, + | 'setShowArtistImages' + | 'setShowTrayIcon' + | 'setMinimizeToTray' + | 'setShowOrbitTrigger' + | 'setUseCustomTitlebar' + | 'setPreloadMiniPlayer' + | 'setLinuxWebkitKineticScroll' + | 'setSeekbarStyle' + | 'setQueueNowPlayingCollapsed' + | 'setShowFullscreenLyrics' + | 'setFsLyricsStyle' + | 'setSidebarLyricsStyle' + | 'setShowFsArtistPortrait' + | 'setFsPortraitDim' + | 'setShowChangelogOnUpdate' + | 'setLastSeenChangelogVersion' +> { + return { + setShowArtistImages: (v) => set({ showArtistImages: v }), + setShowTrayIcon: (v) => set({ showTrayIcon: v }), + setMinimizeToTray: (v) => set({ minimizeToTray: v }), + setShowOrbitTrigger: (v) => set({ showOrbitTrigger: v }), + setUseCustomTitlebar: (v) => set({ useCustomTitlebar: v }), + setPreloadMiniPlayer: (v) => set({ preloadMiniPlayer: v }), + setLinuxWebkitKineticScroll: (v) => set({ linuxWebkitKineticScroll: v }), + setSeekbarStyle: (v) => set({ seekbarStyle: v }), + setQueueNowPlayingCollapsed: (v) => set({ queueNowPlayingCollapsed: v }), + setShowFullscreenLyrics: (v) => set({ showFullscreenLyrics: v }), + setFsLyricsStyle: (v) => set({ fsLyricsStyle: v }), + setSidebarLyricsStyle: (v) => set({ sidebarLyricsStyle: v }), + setShowFsArtistPortrait: (v) => set({ showFsArtistPortrait: v }), + setFsPortraitDim: (v) => set({ fsPortraitDim: v }), + setShowChangelogOnUpdate: (v) => set({ showChangelogOnUpdate: v }), + setLastSeenChangelogVersion: (v) => set({ lastSeenChangelogVersion: v }), + }; +}