From 1e2c6511965e8d31396df62c7cf56646a24894e5 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Tue, 12 May 2026 21:01:12 +0200 Subject: [PATCH] =?UTF-8?q?refactor(player):=20E.35=20=E2=80=94=20extract?= =?UTF-8?q?=20misc-actions=20factory=20(#599)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Heterogeneous "misc" cluster — seven small-to-medium actions that didn't fit the more focused factories (transport / queue / Last.fm / UI state): - `playRadio` — switches the player into HTML5 radio mode. - `previous` — Subsonic-style back: restart if past 3 s, otherwise jump to the previous queue index. - `setVolume` — clamps + propagates to Rust engine and radio sink. - `setProgress` — pure UI state update for progress polling. - `initializeFromServerQueue` — startup queue restore from Navidrome. - `reanalyzeLoudnessForTrack` — toast + reseed the loudness cache. - `reseedQueueForInstantMix` — replace the queue with a single track. Pure code-move. playerStore.ts: 1167 → 1030 LOC (−137). --- src/store/miscActions.ts | 197 +++++++++++++++++++++++++++++++++++++++ src/store/playerStore.ts | 143 +--------------------------- 2 files changed, 200 insertions(+), 140 deletions(-) create mode 100644 src/store/miscActions.ts diff --git a/src/store/miscActions.ts b/src/store/miscActions.ts new file mode 100644 index 00000000..e1d879db --- /dev/null +++ b/src/store/miscActions.ts @@ -0,0 +1,197 @@ +import { invoke } from '@tauri-apps/api/core'; +import i18n from '../i18n'; +import { getPlayQueue } from '../api/subsonic'; +import { songToTrack } from '../utils/songToTrack'; +import { showToast } from '../utils/toast'; +import { useAuthStore } from './authStore'; +import { + bumpPlayGeneration, + setIsAudioPaused, +} from './engineState'; +import { clearPreloadingIds } from './gaplessPreloadState'; +import { reseedLoudnessForTrackId } from './loudnessReseed'; +import { getPlaybackProgressSnapshot } from './playbackProgress'; +import { shouldRebindPlaybackToHotCache } from './playbackUrlRouting'; +import type { PlayerState, Track } from './playerStoreTypes'; +import { pushQueueUndoFromGetter } from './queueUndo'; +import { syncQueueToServer } from './queueSync'; +import { + clearRadioReconnectTimer, + playRadioStream, + setRadioVolume, +} from './radioPlayer'; +import { clearAllPlaybackScheduleTimers } from './scheduleTimers'; +import { clearSeekDebounce } from './seekDebounce'; +import { + clearSeekFallbackRetry, + setSeekFallbackVisualTarget, +} from './seekFallbackState'; +import { clearSeekTarget } from './seekTargetState'; +import { refreshWaveformForTrack } from './waveformRefresh'; + +type SetState = ( + partial: Partial | ((state: PlayerState) => Partial), +) => void; +type GetState = () => PlayerState; + +/** + * Heterogeneous "misc" cluster — seven small-to-medium actions that + * don't fit the more focused factories (transport / queue / Last.fm / + * UI state): + * + * - `playRadio` — switches the player into HTML5 radio mode (Rust + * engine stopped, queue cleared, ICY stream resolved + played). + * - `previous` — Subsonic-style back: restart current track if past + * 3 s, otherwise jump to the previous queue index. + * - `setVolume` — clamps + propagates to Rust engine and radio sink. + * - `setProgress` — pure UI state update used by progress polling. + * - `initializeFromServerQueue` — startup queue restore from + * Navidrome's `getPlayQueue` endpoint. + * - `reanalyzeLoudnessForTrack` — toast + reseed the loudness cache + * for a single track. + * - `reseedQueueForInstantMix` — replaces the queue with a single + * track when "Instant Mix" is triggered on the currently-playing + * song. + */ +export function createMiscActions(set: SetState, get: GetState): Pick< + PlayerState, + | 'playRadio' + | 'previous' + | 'setVolume' + | 'setProgress' + | 'initializeFromServerQueue' + | 'reanalyzeLoudnessForTrack' + | 'reseedQueueForInstantMix' +> { + return { + playRadio: async (station) => { + const { volume } = get(); + bumpPlayGeneration(); + clearAllPlaybackScheduleTimers(); + set({ scheduledPauseAtMs: null, scheduledPauseStartMs: null, scheduledResumeAtMs: null, scheduledResumeStartMs: null }); + setIsAudioPaused(false); + clearRadioReconnectTimer(); + clearPreloadingIds(); + clearSeekFallbackRetry(); + clearSeekDebounce(); clearSeekTarget(); + // Stop Rust engine in case a regular track was playing. + invoke('audio_stop').catch(() => {}); + // Resolve PLS/M3U playlist URLs to the actual stream URL before handing + // to HTML5