mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-28 01:56:47 +00:00
refactor(waveform): co-locate seekbar feature into features/waveform
This commit is contained in:
@@ -14,7 +14,7 @@ import { backdropFromConfig } from '../../cover/artistBackdrop';
|
|||||||
import { useThemeStore } from '../../store/themeStore';
|
import { useThemeStore } from '../../store/themeStore';
|
||||||
import { useFsIdleFade } from '../../hooks/useFsIdleFade';
|
import { useFsIdleFade } from '../../hooks/useFsIdleFade';
|
||||||
import { useQueueTrackAt } from '../../hooks/useQueueTracks';
|
import { useQueueTrackAt } from '../../hooks/useQueueTracks';
|
||||||
import WaveformSeek from '../WaveformSeek';
|
import { WaveformSeek } from '@/features/waveform';
|
||||||
import { FsQueueModal } from './FsQueueModal';
|
import { FsQueueModal } from './FsQueueModal';
|
||||||
import { FsLyricsApple } from './FsLyricsApple';
|
import { FsLyricsApple } from './FsLyricsApple';
|
||||||
import { FsPlayBtn } from './FsPlayBtn';
|
import { FsPlayBtn } from './FsPlayBtn';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { TFunction } from 'i18next';
|
|||||||
import type { RadioMetadata } from '../../hooks/useRadioMetadata';
|
import type { RadioMetadata } from '../../hooks/useRadioMetadata';
|
||||||
import { useThemeStore } from '../../store/themeStore';
|
import { useThemeStore } from '../../store/themeStore';
|
||||||
import { formatTrackTime, playbarMinuteFieldWidth } from '../../utils/format/formatDuration';
|
import { formatTrackTime, playbarMinuteFieldWidth } from '../../utils/format/formatDuration';
|
||||||
import WaveformSeek from '../WaveformSeek';
|
import { WaveformSeek } from '@/features/waveform';
|
||||||
import { PlaybackTime, ToggleClock } from './PlaybackClock';
|
import { PlaybackTime, ToggleClock } from './PlaybackClock';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { SettingsGroup } from './SettingsGroup';
|
|||||||
import { SettingsToggle } from './SettingsToggle';
|
import { SettingsToggle } from './SettingsToggle';
|
||||||
import { SettingsSubCard, SettingsField, SettingsValue } from './SettingsSubCard';
|
import { SettingsSubCard, SettingsField, SettingsValue } from './SettingsSubCard';
|
||||||
import { SettingsSegmented, type SegmentedOption } from './SettingsSegmented';
|
import { SettingsSegmented, type SegmentedOption } from './SettingsSegmented';
|
||||||
import { SeekbarPreview } from '../WaveformSeekPreview';
|
import { SeekbarPreview } from '@/features/waveform';
|
||||||
import WindowButtonPreview from '../WindowButtonPreview';
|
import WindowButtonPreview from '../WindowButtonPreview';
|
||||||
|
|
||||||
export function AppearanceTab() {
|
export function AppearanceTab() {
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ vi.mock('@/api/subsonic', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
import WaveformSeek from './WaveformSeek';
|
import WaveformSeek from '@/features/waveform/components/WaveformSeek';
|
||||||
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
|
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
|
||||||
import { usePlayerStore } from '@/store/playerStore';
|
import { usePlayerStore } from '@/store/playerStore';
|
||||||
import { useAuthStore } from '@/store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '../store/playbackProgress';
|
import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/store/playbackProgress';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { usePlayerStore } from '../store/playerStore';
|
import { usePlayerStore } from '@/store/playerStore';
|
||||||
import { usePreviewStore } from '../store/previewStore';
|
import { usePreviewStore } from '@/store/previewStore';
|
||||||
import { useAuthStore } from '../store/authStore';
|
import { useAuthStore } from '@/store/authStore';
|
||||||
import {
|
import {
|
||||||
ANIMATED_STYLES, AnimState,
|
ANIMATED_STYLES, AnimState,
|
||||||
STATIC_REDRAW_FORCE_MS, STATIC_REDRAW_MIN_MS,
|
STATIC_REDRAW_FORCE_MS, STATIC_REDRAW_MIN_MS,
|
||||||
fmt, invalidateColorCache, isBarQuantizedSeekStyle, makeAnimState,
|
fmt, invalidateColorCache, isBarQuantizedSeekStyle, makeAnimState,
|
||||||
quantizeProgressByBars,
|
quantizeProgressByBars,
|
||||||
} from '../utils/waveform/waveformSeekHelpers';
|
} from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
import { drawSeekbar } from '@/features/waveform/utils/waveformSeekRenderers';
|
||||||
import { useWaveformHeights } from '../hooks/useWaveformHeights';
|
import { useWaveformHeights } from '@/features/waveform/hooks/useWaveformHeights';
|
||||||
import { useWaveformInterpolation } from '../hooks/useWaveformInterpolation';
|
import { useWaveformInterpolation } from '@/features/waveform/hooks/useWaveformInterpolation';
|
||||||
|
|
||||||
// ── main component ────────────────────────────────────────────────────────────
|
// ── main component ────────────────────────────────────────────────────────────
|
||||||
//
|
//
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import type { SeekbarStyle } from '../store/authStoreTypes';
|
import type { SeekbarStyle } from '@/store/authStoreTypes';
|
||||||
import { makeAnimState, makeHeights } from '../utils/waveform/waveformSeekHelpers';
|
import { makeAnimState, makeHeights } from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
import { drawSeekbar } from '@/features/waveform/utils/waveformSeekRenderers';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
style: SeekbarStyle;
|
style: SeekbarStyle;
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import type { SeekbarStyle } from '../store/authStoreTypes';
|
import type { SeekbarStyle } from '@/store/authStoreTypes';
|
||||||
import type { AnimState } from '../utils/waveform/waveformSeekHelpers';
|
import type { AnimState } from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import {
|
import {
|
||||||
ANIMATED_STYLES, BAR_COUNT, FLAT_WAVE_NORM, WAVE_MORPH_MS,
|
ANIMATED_STYLES, BAR_COUNT, FLAT_WAVE_NORM, WAVE_MORPH_MS,
|
||||||
binsToHeights, easeOutCubic, heightsNearlyEqual,
|
binsToHeights, easeOutCubic, heightsNearlyEqual,
|
||||||
makeFlatWaveHeights, makeHeights,
|
makeFlatWaveHeights, makeHeights,
|
||||||
} from '../utils/waveform/waveformSeekHelpers';
|
} from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
import { drawSeekbar } from '@/features/waveform/utils/waveformSeekRenderers';
|
||||||
|
|
||||||
interface Args {
|
interface Args {
|
||||||
trackId: string | undefined;
|
trackId: string | undefined;
|
||||||
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import type { SeekbarStyle } from '../store/authStoreTypes';
|
import type { SeekbarStyle } from '@/store/authStoreTypes';
|
||||||
import { getPlaybackProgressSnapshot } from '../store/playbackProgress';
|
import { getPlaybackProgressSnapshot } from '@/store/playbackProgress';
|
||||||
import {
|
import {
|
||||||
ANIMATED_STYLES, AnimState, INTERPOLATION_PAINT_MIN_MS,
|
ANIMATED_STYLES, AnimState, INTERPOLATION_PAINT_MIN_MS,
|
||||||
isBarQuantizedSeekStyle, quantizeProgressByBars,
|
isBarQuantizedSeekStyle, quantizeProgressByBars,
|
||||||
} from '../utils/waveform/waveformSeekHelpers';
|
} from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import { drawSeekbar } from '../utils/waveform/waveformSeekRenderers';
|
import { drawSeekbar } from '@/features/waveform/utils/waveformSeekRenderers';
|
||||||
|
|
||||||
interface Args {
|
interface Args {
|
||||||
duration: number;
|
duration: number;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Waveform seekbar feature — the canvas seekbar, its waveform-bin loading, and
|
||||||
|
* the per-track refresh generation guard. Co-located mirror of `cover/` /
|
||||||
|
* `music-network/`. `waveformSilence` stays in `utils/waveform/` (crossfade /
|
||||||
|
* auto-dj concern, not seekbar rendering).
|
||||||
|
*/
|
||||||
|
export { default as WaveformSeek } from './components/WaveformSeek';
|
||||||
|
export { SeekbarPreview } from './components/WaveformSeekPreview';
|
||||||
|
export { fetchWaveformBins, refreshWaveformForTrack } from './store/waveformRefresh';
|
||||||
|
export type { WaveformCachePayload } from './store/waveformRefresh';
|
||||||
|
export { bumpWaveformRefreshGen, getWaveformRefreshGen } from './store/waveformRefreshGen';
|
||||||
+4
-4
@@ -22,18 +22,18 @@ const hoisted = vi.hoisted(() => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock('@tauri-apps/api/core', () => ({ invoke: hoisted.invokeMock }));
|
vi.mock('@tauri-apps/api/core', () => ({ invoke: hoisted.invokeMock }));
|
||||||
vi.mock('../utils/waveform/waveformParse', () => ({ coerceWaveformBins: hoisted.coerceWaveformBinsMock }));
|
vi.mock('@/features/waveform/utils/waveformParse', () => ({ coerceWaveformBins: hoisted.coerceWaveformBinsMock }));
|
||||||
vi.mock('./playerStore', () => ({
|
vi.mock('@/store/playerStore', () => ({
|
||||||
usePlayerStore: {
|
usePlayerStore: {
|
||||||
getState: () => hoisted.playerSnapshot,
|
getState: () => hoisted.playerSnapshot,
|
||||||
setState: hoisted.playerSetStateMock,
|
setState: hoisted.playerSetStateMock,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
vi.mock('./waveformRefreshGen', () => ({
|
vi.mock('@/features/waveform/store/waveformRefreshGen', () => ({
|
||||||
getWaveformRefreshGen: hoisted.getGenMock,
|
getWaveformRefreshGen: hoisted.getGenMock,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import { refreshWaveformForTrack } from './waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform/store/waveformRefresh';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
hoisted.invokeMock.mockReset();
|
hoisted.invokeMock.mockReset();
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { coerceWaveformBins } from '../utils/waveform/waveformParse';
|
import { coerceWaveformBins } from '@/features/waveform/utils/waveformParse';
|
||||||
import { getPlaybackIndexKey } from '../utils/playback/playbackServer';
|
import { getPlaybackIndexKey } from '@/utils/playback/playbackServer';
|
||||||
import { usePlayerStore } from './playerStore';
|
import { usePlayerStore } from '@/store/playerStore';
|
||||||
import { getWaveformRefreshGen } from './waveformRefreshGen';
|
import { getWaveformRefreshGen } from '@/features/waveform/store/waveformRefreshGen';
|
||||||
|
|
||||||
/** Subsonic-server waveform-cache row as Rust hands it back. */
|
/** Subsonic-server waveform-cache row as Rust hands it back. */
|
||||||
export type WaveformCachePayload = {
|
export type WaveformCachePayload = {
|
||||||
+1
-1
@@ -3,7 +3,7 @@ import {
|
|||||||
_resetWaveformRefreshGenForTest,
|
_resetWaveformRefreshGenForTest,
|
||||||
bumpWaveformRefreshGen,
|
bumpWaveformRefreshGen,
|
||||||
getWaveformRefreshGen,
|
getWaveformRefreshGen,
|
||||||
} from './waveformRefreshGen';
|
} from '@/features/waveform/store/waveformRefreshGen';
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
_resetWaveformRefreshGenForTest();
|
_resetWaveformRefreshGenForTest();
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { coerceWaveformBins, waveformBlobLenOk } from './waveformParse';
|
import { coerceWaveformBins, waveformBlobLenOk } from '@/features/waveform/utils/waveformParse';
|
||||||
|
|
||||||
describe('waveformBlobLenOk', () => {
|
describe('waveformBlobLenOk', () => {
|
||||||
it('accepts the legacy single-curve length (500)', () => {
|
it('accepts the legacy single-curve length (500)', () => {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import type { SeekbarStyle } from '../../store/authStoreTypes';
|
import type { SeekbarStyle } from '@/store/authStoreTypes';
|
||||||
|
|
||||||
export function fmt(s: number): string {
|
export function fmt(s: number): string {
|
||||||
if (!s || isNaN(s)) return '0:00';
|
if (!s || isNaN(s)) return '0:00';
|
||||||
+5
-5
@@ -1,12 +1,12 @@
|
|||||||
import type { SeekbarStyle } from '../../store/authStoreTypes';
|
import type { SeekbarStyle } from '@/store/authStoreTypes';
|
||||||
import { bumpPerfCounter } from '../perf/perfTelemetry';
|
import { bumpPerfCounter } from '@/utils/perf/perfTelemetry';
|
||||||
import { AnimState, makeAnimState } from './waveformSeekHelpers';
|
import { AnimState, makeAnimState } from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
import {
|
import {
|
||||||
drawBar, drawLineDot, drawNeon, drawSegmented, drawThick, drawWaveform,
|
drawBar, drawLineDot, drawNeon, drawSegmented, drawThick, drawWaveform,
|
||||||
} from './waveformSeekRenderersStatic';
|
} from '@/features/waveform/utils/waveformSeekRenderersStatic';
|
||||||
import {
|
import {
|
||||||
drawLiquidFill, drawParticleTrail, drawPulseWave, drawRetroTape,
|
drawLiquidFill, drawParticleTrail, drawPulseWave, drawRetroTape,
|
||||||
} from './waveformSeekRenderersAnimated';
|
} from '@/features/waveform/utils/waveformSeekRenderersAnimated';
|
||||||
|
|
||||||
export function drawSeekbar(
|
export function drawSeekbar(
|
||||||
canvas: HTMLCanvasElement,
|
canvas: HTMLCanvasElement,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { AnimState, getColors, setShadowBlur, setupCanvas } from './waveformSeekHelpers';
|
import { AnimState, getColors, setShadowBlur, setupCanvas } from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
|
|
||||||
export function drawPulseWave(
|
export function drawPulseWave(
|
||||||
canvas: HTMLCanvasElement,
|
canvas: HTMLCanvasElement,
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
BAR_COUNT, SEG_COUNT,
|
BAR_COUNT, SEG_COUNT,
|
||||||
getColors, setShadowBlur, setupCanvas, waveformBarThickness,
|
getColors, setShadowBlur, setupCanvas, waveformBarThickness,
|
||||||
} from './waveformSeekHelpers';
|
} from '@/features/waveform/utils/waveformSeekHelpers';
|
||||||
|
|
||||||
export function drawWaveform(
|
export function drawWaveform(
|
||||||
canvas: HTMLCanvasElement,
|
canvas: HTMLCanvasElement,
|
||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
type QueueUndoSnapshot,
|
type QueueUndoSnapshot,
|
||||||
} from './queueUndo';
|
} from './queueUndo';
|
||||||
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
||||||
import { refreshWaveformForTrack } from './waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { stopRadio } from './radioPlayer';
|
import { stopRadio } from './radioPlayer';
|
||||||
import { clearAllPlaybackScheduleTimers } from './scheduleTimers';
|
import { clearAllPlaybackScheduleTimers } from './scheduleTimers';
|
||||||
import { syncUserQueueMutationToServer } from './queueSync';
|
import { syncUserQueueMutationToServer } from './queueSync';
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ vi.mock('./pausedRestorePrepare', () => ({
|
|||||||
preparePausedRestoreOnStartup: vi.fn(),
|
preparePausedRestoreOnStartup: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock('./waveformRefresh', () => ({
|
vi.mock('@/features/waveform', () => ({
|
||||||
refreshWaveformForTrack: vi.fn(),
|
refreshWaveformForTrack: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { useAuthStore } from './authStore';
|
|||||||
import { usePlayerStore } from './playerStore';
|
import { usePlayerStore } from './playerStore';
|
||||||
import { preparePausedRestoreOnStartup } from './pausedRestorePrepare';
|
import { preparePausedRestoreOnStartup } from './pausedRestorePrepare';
|
||||||
import { pushQueueUndoFromGetter } from './queueUndo';
|
import { pushQueueUndoFromGetter } from './queueUndo';
|
||||||
import { refreshWaveformForTrack } from './waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import {
|
import {
|
||||||
getIdlePullGeneration,
|
getIdlePullGeneration,
|
||||||
isIdleQueuePullSuspended,
|
isIdleQueuePullSuspended,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ import {
|
|||||||
getSeekTarget,
|
getSeekTarget,
|
||||||
getSeekTargetSetAt,
|
getSeekTargetSetAt,
|
||||||
} from './seekTargetState';
|
} from './seekTargetState';
|
||||||
import { refreshWaveformForTrack } from './waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { analyzeBoundary, computeWaveformSilence } from '../utils/waveform/waveformSilence';
|
import { analyzeBoundary, computeWaveformSilence } from '../utils/waveform/waveformSilence';
|
||||||
import { autodjMaxOverlapCapSec } from '../utils/playback/autodjOverlapCap';
|
import { autodjMaxOverlapCapSec } from '../utils/playback/autodjOverlapCap';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import {
|
|||||||
markNormalizationUiUpdate,
|
markNormalizationUiUpdate,
|
||||||
} from '../playbackThrottles';
|
} from '../playbackThrottles';
|
||||||
import { usePlayerStore } from '../playerStore';
|
import { usePlayerStore } from '../playerStore';
|
||||||
import { refreshWaveformForTrack } from '../waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { bumpWaveformRefreshGen } from '../waveformRefreshGen';
|
import { bumpWaveformRefreshGen } from '@/features/waveform';
|
||||||
import { setBytePreloadingId } from '../gaplessPreloadState';
|
import { setBytePreloadingId } from '../gaplessPreloadState';
|
||||||
|
|
||||||
type PreloadEventPayload = {
|
type PreloadEventPayload = {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { invokeAudioSetNormalizationDeduped } from '../normalizationIpcDedupe';
|
|||||||
import { usePlayerStore } from '../playerStore';
|
import { usePlayerStore } from '../playerStore';
|
||||||
import { clearLoudnessCacheStateForTrackId } from '../loudnessGainCache';
|
import { clearLoudnessCacheStateForTrackId } from '../loudnessGainCache';
|
||||||
import { refreshLoudnessForTrack } from '../loudnessRefresh';
|
import { refreshLoudnessForTrack } from '../loudnessRefresh';
|
||||||
import { refreshWaveformForTrack } from '../waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { bumpWaveformRefreshGen } from '../waveformRefreshGen';
|
import { bumpWaveformRefreshGen } from '@/features/waveform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps the Rust audio engine in sync whenever the auth store changes
|
* Keeps the Rust audio engine in sync whenever the auth store changes
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { emitNormalizationDebug } from '../normalizationDebug';
|
|||||||
import { invokeAudioSetNormalizationDeduped } from '../normalizationIpcDedupe';
|
import { invokeAudioSetNormalizationDeduped } from '../normalizationIpcDedupe';
|
||||||
import { usePlayerStore } from '../playerStore';
|
import { usePlayerStore } from '../playerStore';
|
||||||
import { refreshLoudnessForTrack } from '../loudnessRefresh';
|
import { refreshLoudnessForTrack } from '../loudnessRefresh';
|
||||||
import { refreshWaveformForTrack } from '../waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One-shot startup sync: pushes the persisted audio settings to the Rust engine
|
* One-shot startup sync: pushes the persisted audio settings to the Rust engine
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
import { getBytePreloadingId, setBytePreloadingId } from './gaplessPreloadState';
|
import { getBytePreloadingId, setBytePreloadingId } from './gaplessPreloadState';
|
||||||
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
||||||
import { usePlayerStore } from './playerStore';
|
import { usePlayerStore } from './playerStore';
|
||||||
import { fetchWaveformBins } from './waveformRefresh';
|
import { fetchWaveformBins } from '@/features/waveform';
|
||||||
|
|
||||||
// Crossfade pre-buffer budget: begin downloading the next track this many
|
// Crossfade pre-buffer budget: begin downloading the next track this many
|
||||||
// seconds before it needs to play (the crossfade start), so a large lossless
|
// seconds before it needs to play (the crossfade start), so a large lossless
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ vi.mock('./playerStore', () => ({
|
|||||||
setState: hoisted.playerSetStateMock,
|
setState: hoisted.playerSetStateMock,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
vi.mock('./waveformRefreshGen', () => ({
|
vi.mock('@/features/waveform', () => ({
|
||||||
bumpWaveformRefreshGen: hoisted.bumpWaveformRefreshGenMock,
|
bumpWaveformRefreshGen: hoisted.bumpWaveformRefreshGenMock,
|
||||||
}));
|
}));
|
||||||
vi.mock('./loudnessGainCache', () => ({
|
vi.mock('./loudnessGainCache', () => ({
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { invoke } from '@tauri-apps/api/core';
|
|||||||
import { getPlaybackIndexKey } from '../utils/playback/playbackServer';
|
import { getPlaybackIndexKey } from '../utils/playback/playbackServer';
|
||||||
import { useAuthStore } from './authStore';
|
import { useAuthStore } from './authStore';
|
||||||
import { usePlayerStore } from './playerStore';
|
import { usePlayerStore } from './playerStore';
|
||||||
import { bumpWaveformRefreshGen } from './waveformRefreshGen';
|
import { bumpWaveformRefreshGen } from '@/features/waveform';
|
||||||
import { clearLoudnessCacheStateForTrackId } from './loudnessGainCache';
|
import { clearLoudnessCacheStateForTrackId } from './loudnessGainCache';
|
||||||
import { resetLoudnessBackfillStateForTrackId } from './loudnessBackfillState';
|
import { resetLoudnessBackfillStateForTrackId } from './loudnessBackfillState';
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import {
|
|||||||
loudnessGainDbForEngineBind,
|
loudnessGainDbForEngineBind,
|
||||||
} from './loudnessGainCache';
|
} from './loudnessGainCache';
|
||||||
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
import { refreshLoudnessForTrack } from './loudnessRefresh';
|
||||||
import { fetchWaveformBins, refreshWaveformForTrack } from './waveformRefresh';
|
import { fetchWaveformBins, refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
||||||
import { useOrbitStore } from './orbitStore';
|
import { useOrbitStore } from './orbitStore';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { clearSeekDebounce } from './seekDebounce';
|
|||||||
import { clearSeekFallbackRetry } from './seekFallbackState';
|
import { clearSeekFallbackRetry } from './seekFallbackState';
|
||||||
import { clearSeekTarget } from './seekTargetState';
|
import { clearSeekTarget } from './seekTargetState';
|
||||||
import { tryAcquireTogglePlayLock } from './togglePlayLock';
|
import { tryAcquireTogglePlayLock } from './togglePlayLock';
|
||||||
import { refreshWaveformForTrack } from './waveformRefresh';
|
import { refreshWaveformForTrack } from '@/features/waveform';
|
||||||
import { clearAutodjTransitionUi } from './autodjTransitionUi';
|
import { clearAutodjTransitionUi } from './autodjTransitionUi';
|
||||||
|
|
||||||
type SetState = (
|
type SetState = (
|
||||||
|
|||||||
Reference in New Issue
Block a user