From 8412c3392317eb8268221d6c87bb3f4853db44af Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Thu, 24 Mar 2022 12:00:06 +0900 Subject: [PATCH] use immer as middleware --- app/state/cache.ts | 158 +++++++++++++++------------------- app/state/library.ts | 164 ++++++++++++++---------------------- app/state/settings.ts | 119 ++++++++++---------------- app/state/store.ts | 45 ++++++++-- app/state/trackplayer.ts | 109 +++++++++++++++--------- app/state/trackplayermap.ts | 5 +- 6 files changed, 291 insertions(+), 309 deletions(-) diff --git a/app/state/cache.ts b/app/state/cache.ts index 430cc54..1db5c28 100644 --- a/app/state/cache.ts +++ b/app/state/cache.ts @@ -1,10 +1,8 @@ import { CacheFile, CacheImageSize, CacheItemType, CacheItemTypeKey, CacheRequest } from '@app/models/cache' import { mkdir, rmdir } from '@app/util/fs' import PromiseQueue from '@app/util/PromiseQueue' -import produce from 'immer' import RNFS from 'react-native-fs' -import { GetState, SetState } from 'zustand' -import { Store } from './store' +import { GetStore, SetStore } from './store' const queues: Record = { coverArt: new PromiseQueue(5), @@ -47,7 +45,7 @@ export const selectCache = { clearImageCache: (store: CacheSlice) => store.clearImageCache, } -export const createCacheSlice = (set: SetState, get: GetState): CacheSlice => ({ +export const createCacheSlice = (set: SetStore, get: GetStore): CacheSlice => ({ // cache: {}, cacheDirs: {}, cacheFiles: {}, @@ -105,34 +103,28 @@ export const createCacheSlice = (set: SetState, get: GetState): Ca // }, }).promise - set( - produce(state => { - state.cacheRequests[activeServerId][key][itemId].progress = 1 - delete state.cacheRequests[activeServerId][key][itemId].promise - }), - ) + set(state => { + state.cacheRequests[activeServerId][key][itemId].progress = 1 + delete state.cacheRequests[activeServerId][key][itemId].promise + }) } catch { - set( - produce(state => { - delete state.cacheFiles[activeServerId][key][itemId] - delete state.cacheRequests[activeServerId][key][itemId] - }), - ) + set(state => { + delete state.cacheFiles[activeServerId][key][itemId] + delete state.cacheRequests[activeServerId][key][itemId] + }) + } + }) + set(state => { + state.cacheFiles[activeServerId][key][itemId] = { + path, + date: Date.now(), + permanent: false, + } + state.cacheRequests[activeServerId][key][itemId] = { + progress: 0, + promise, } }) - set( - produce(state => { - state.cacheFiles[activeServerId][key][itemId] = { - path, - date: Date.now(), - permanent: false, - } - state.cacheRequests[activeServerId][key][itemId] = { - progress: 0, - promise, - } - }), - ) return await promise }, @@ -173,54 +165,48 @@ export const createCacheSlice = (set: SetState, get: GetState): Ca await mkdir(`${RNFS.DocumentDirectoryPath}/servers/${serverId}/${type}`) } - set( - produce(state => { - state.cacheFiles[serverId] = { + set(state => { + state.cacheFiles[serverId] = { + song: {}, + coverArt: {}, + coverArtThumb: {}, + artistArt: {}, + artistArtThumb: {}, + } + }) + + get().prepareCache(serverId) + }, + + prepareCache: serverId => { + set(state => { + if (!state.cacheDirs[serverId]) { + state.cacheDirs[serverId] = { + song: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/song`, + coverArt: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/coverArt`, + coverArtThumb: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/coverArtThumb`, + artistArt: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/artistArt`, + artistArtThumb: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/artistArtThumb`, + } + } + if (!state.cacheRequests[serverId]) { + state.cacheRequests[serverId] = { song: {}, coverArt: {}, coverArtThumb: {}, artistArt: {}, artistArtThumb: {}, } - }), - ) - - get().prepareCache(serverId) - }, - - prepareCache: serverId => { - set( - produce(state => { - if (!state.cacheDirs[serverId]) { - state.cacheDirs[serverId] = { - song: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/song`, - coverArt: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/coverArt`, - coverArtThumb: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/coverArtThumb`, - artistArt: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/artistArt`, - artistArtThumb: `${RNFS.DocumentDirectoryPath}/servers/${serverId}/artistArtThumb`, - } - } - if (!state.cacheRequests[serverId]) { - state.cacheRequests[serverId] = { - song: {}, - coverArt: {}, - coverArtThumb: {}, - artistArt: {}, - artistArtThumb: {}, - } - } - }), - ) + } + }) }, pendingRemoval: {}, removeCache: async serverId => { - set( - produce(state => { - state.pendingRemoval[serverId] = true - }), - ) + set(state => { + state.pendingRemoval[serverId] = true + }) const cacheRequests = get().cacheRequests[serverId] const pendingRequests: Promise[] = [] @@ -235,21 +221,19 @@ export const createCacheSlice = (set: SetState, get: GetState): Ca await Promise.all(pendingRequests) await rmdir(`${RNFS.DocumentDirectoryPath}/servers/${serverId}`) - set( - produce(state => { - delete state.pendingRemoval[serverId] + set(state => { + delete state.pendingRemoval[serverId] - if (state.cacheDirs[serverId]) { - delete state.cacheDirs[serverId] - } - if (state.cacheFiles[serverId]) { - delete state.cacheFiles[serverId] - } - if (state.cacheRequests[serverId]) { - delete state.cacheRequests[serverId] - } - }), - ) + if (state.cacheDirs[serverId]) { + delete state.cacheDirs[serverId] + } + if (state.cacheFiles[serverId]) { + delete state.cacheFiles[serverId] + } + if (state.cacheRequests[serverId]) { + delete state.cacheRequests[serverId] + } + }) }, clearImageCache: async () => { @@ -270,14 +254,12 @@ export const createCacheSlice = (set: SetState, get: GetState): Ca await rmdir(get().cacheDirs[serverId].artistArt) await mkdir(get().cacheDirs[serverId].artistArt) - set( - produce(state => { - state.cacheFiles[serverId].coverArt = {} - state.cacheFiles[serverId].coverArtThumb = {} - state.cacheFiles[serverId].artistArt = {} - state.cacheFiles[serverId].artistArtThumb = {} - }), - ) + set(state => { + state.cacheFiles[serverId].coverArt = {} + state.cacheFiles[serverId].coverArtThumb = {} + state.cacheFiles[serverId].artistArt = {} + state.cacheFiles[serverId].artistArtThumb = {} + }) } }, }) diff --git a/app/state/library.ts b/app/state/library.ts index c1d3c46..60c8222 100644 --- a/app/state/library.ts +++ b/app/state/library.ts @@ -1,6 +1,6 @@ import { Album, Artist, ArtistInfo, Playlist, SearchResults, Song } from '@app/models/library' import { ById, OneToMany } from '@app/models/state' -import { Store } from '@app/state/store' +import { GetStore, SetStore, Store } from '@app/state/store' import { AlbumID3Element, ArtistID3Element, @@ -24,10 +24,8 @@ import { } from '@app/subsonic/responses' import PromiseQueue from '@app/util/PromiseQueue' import { reduceById, mergeById } from '@app/util/state' -import produce from 'immer' import { WritableDraft } from 'immer/dist/types/types-external' import pick from 'lodash.pick' -import { GetState, SetState } from 'zustand' const songCoverArtQueue = new PromiseQueue(2) @@ -84,7 +82,7 @@ const defaultEntities = () => ({ songs: {}, }) -export const createLibrarySlice = (set: SetState, get: GetState): LibrarySlice => ({ +export const createLibrarySlice = (set: SetStore, get: GetStore): LibrarySlice => ({ entities: defaultEntities(), resetLibrary: state => { @@ -92,9 +90,7 @@ export const createLibrarySlice = (set: SetState, get: GetState): state.entities = defaultEntities() return } - set(store => { - store.entities = defaultEntities() - }) + set(store => (store.entities = defaultEntities())) }, fetchArtists: async () => { @@ -113,12 +109,10 @@ export const createLibrarySlice = (set: SetState, get: GetState): const artists = response.data.artists.map(mapArtist) const artistsById = reduceById(artists) - set( - produce(state => { - state.entities.artists = artistsById - state.entities.artistAlbums = pick(state.entities.artistAlbums, mapId(artists)) - }), - ) + set(state => { + state.entities.artists = artistsById + state.entities.artistAlbums = pick(state.entities.artistAlbums, mapId(artists)) + }) }, fetchArtist: async id => { @@ -138,13 +132,11 @@ export const createLibrarySlice = (set: SetState, get: GetState): const albums = response.data.albums.map(mapAlbum) const albumsById = reduceById(albums) - set( - produce(state => { - state.entities.artists[id] = artist - state.entities.artistAlbums[id] = mapId(albums) - mergeById(state.entities.albums, albumsById) - }), - ) + set(state => { + state.entities.artists[id] = artist + state.entities.artistAlbums[id] = mapId(albums) + mergeById(state.entities.albums, albumsById) + }) }, fetchArtistInfo: async id => { @@ -162,11 +154,9 @@ export const createLibrarySlice = (set: SetState, get: GetState): const info = mapArtistInfo(id, response.data.artistInfo) - set( - produce(state => { - state.entities.artistInfo[id] = info - }), - ) + set(state => { + state.entities.artistInfo[id] = info + }) }, fetchArtistTopSongs: async artistName => { @@ -187,12 +177,10 @@ export const createLibrarySlice = (set: SetState, get: GetState): get()._fixSongCoverArt(topSongs) - set( - produce(state => { - mergeById(state.entities.songs, topSongsById) - state.entities.artistNameTopSongs[artistName] = mapId(topSongs) - }), - ) + set(state => { + mergeById(state.entities.songs, topSongsById) + state.entities.artistNameTopSongs[artistName] = mapId(topSongs) + }) }, fetchAlbum: async id => { @@ -214,13 +202,11 @@ export const createLibrarySlice = (set: SetState, get: GetState): get()._fixSongCoverArt(songs) - set( - produce(state => { - state.entities.albums[id] = album - state.entities.albumSongs[id] = mapId(songs) - mergeById(state.entities.songs, songsById) - }), - ) + set(state => { + state.entities.albums[id] = album + state.entities.albumSongs[id] = mapId(songs) + mergeById(state.entities.songs, songsById) + }) }, fetchPlaylists: async () => { @@ -239,12 +225,10 @@ export const createLibrarySlice = (set: SetState, get: GetState): const playlists = response.data.playlists.map(mapPlaylist) const playlistsById = reduceById(playlists) - set( - produce(state => { - state.entities.playlists = playlistsById - state.entities.playlistSongs = pick(state.entities.playlistSongs, mapId(playlists)) - }), - ) + set(state => { + state.entities.playlists = playlistsById + state.entities.playlistSongs = pick(state.entities.playlistSongs, mapId(playlists)) + }) }, fetchPlaylist: async id => { @@ -266,13 +250,11 @@ export const createLibrarySlice = (set: SetState, get: GetState): get()._fixSongCoverArt(songs) - set( - produce(state => { - state.entities.playlists[id] = playlist - state.entities.playlistSongs[id] = mapId(songs) - mergeById(state.entities.songs, songsById) - }), - ) + set(state => { + state.entities.playlists[id] = playlist + state.entities.playlistSongs[id] = mapId(songs) + mergeById(state.entities.songs, songsById) + }) }, fetchSong: async id => { @@ -292,11 +274,9 @@ export const createLibrarySlice = (set: SetState, get: GetState): get()._fixSongCoverArt([song]) - set( - produce(state => { - state.entities.songs[id] = song - }), - ) + set(state => { + state.entities.songs[id] = song + }) }, fetchAlbumList: async params => { @@ -315,11 +295,7 @@ export const createLibrarySlice = (set: SetState, get: GetState): const albums = response.data.albums.map(mapAlbum) const albumsById = reduceById(albums) - set( - produce(state => { - mergeById(state.entities.albums, albumsById) - }), - ) + set(state => mergeById(state.entities.albums, albumsById)) return mapId(albums) }, @@ -348,13 +324,11 @@ export const createLibrarySlice = (set: SetState, get: GetState): get()._fixSongCoverArt(songs) - set( - produce(state => { - mergeById(state.entities.artists, artistsById) - mergeById(state.entities.albums, albumsById) - mergeById(state.entities.songs, songsById) - }), - ) + set(state => { + mergeById(state.entities.artists, artistsById) + mergeById(state.entities.albums, albumsById) + mergeById(state.entities.songs, songsById) + }) return { artists: mapId(artists), @@ -387,22 +361,18 @@ export const createLibrarySlice = (set: SetState, get: GetState): const item = get().entities[entity][id] const originalValue = item ? item.starred : null - set( - produce(state => { - state.entities[entity][id].starred = new Date() - }), - ) + set(state => { + state.entities[entity][id].starred = new Date() + }) try { await client.star(params) } catch { - set( - produce(state => { - if (originalValue !== null) { - state.entities[entity][id].starred = originalValue - } - }), - ) + set(state => { + if (originalValue !== null) { + state.entities[entity][id].starred = originalValue + } + }) } }, @@ -430,22 +400,18 @@ export const createLibrarySlice = (set: SetState, get: GetState): const item = get().entities[entity][id] const originalValue = item ? item.starred : null - set( - produce(state => { - state.entities[entity][id].starred = undefined - }), - ) + set(state => { + state.entities[entity][id].starred = undefined + }) try { await client.unstar(params) } catch { - set( - produce(state => { - if (originalValue !== null) { - state.entities[entity][id].starred = originalValue - } - }), - ) + set(state => { + if (originalValue !== null) { + state.entities[entity][id].starred = originalValue + } + }) } }, @@ -479,14 +445,12 @@ export const createLibrarySlice = (set: SetState, get: GetState): .then(res => { const album = mapAlbum(res.data.album) - set( - produce(state => { - state.entities.albums[album.id] = album - for (const song of albumsToGet[album.id]) { - state.entities.songs[song.id].coverArt = album.coverArt - } - }), - ) + set(state => { + state.entities.albums[album.id] = album + for (const song of albumsToGet[album.id]) { + state.entities.songs[song.id].coverArt = album.coverArt + } + }) }) } }, diff --git a/app/state/settings.ts b/app/state/settings.ts index a9f7657..b42cb52 100644 --- a/app/state/settings.ts +++ b/app/state/settings.ts @@ -1,8 +1,6 @@ -import { AppSettings, ArtistFilterSettings, AlbumFilterSettings, Server } from '@app/models/settings' -import { Store } from '@app/state/store' +import { AlbumFilterSettings, AppSettings, ArtistFilterSettings, Server } from '@app/models/settings' +import { GetStore, SetStore } from '@app/state/store' import { SubsonicApiClient } from '@app/subsonic/api' -import produce from 'immer' -import { GetState, SetState } from 'zustand' export type SettingsSlice = { settings: AppSettings @@ -66,7 +64,7 @@ export const selectSettings = { libraryArtistFilter: (state: SettingsSlice) => state.settings.screens.library.artists, } -export const createSettingsSlice = (set: SetState, get: GetState): SettingsSlice => ({ +export const createSettingsSlice = (set: SetStore, get: GetStore): SettingsSlice => ({ settings: { servers: [], screens: { @@ -99,8 +97,8 @@ export const createSettingsSlice = (set: SetState, get: GetState): const newActiveServer = servers.find(s => s.id === id) if (!newActiveServer) { - set({ - client: undefined, + set(state => { + state.client = undefined }) return } @@ -111,13 +109,11 @@ export const createSettingsSlice = (set: SetState, get: GetState): get().prepareCache(newActiveServer.id) - set( - produce(state => { - state.settings.activeServer = newActiveServer.id - state.client = new SubsonicApiClient(newActiveServer) - get().resetLibrary(state) - }), - ) + set(state => { + state.settings.activeServer = newActiveServer.id + state.client = new SubsonicApiClient(newActiveServer) + get().resetLibrary(state) + }) }, getActiveServer: () => get().settings.servers.find(s => s.id === get().settings.activeServer), @@ -125,11 +121,7 @@ export const createSettingsSlice = (set: SetState, get: GetState): addServer: async server => { await get().createCache(server.id) - set( - produce(state => { - state.settings.servers.push(server) - }), - ) + set(state => state.settings.servers.push(server)) if (get().settings.servers.length === 1) { get().setActiveServer(server.id) @@ -139,23 +131,19 @@ export const createSettingsSlice = (set: SetState, get: GetState): removeServer: async id => { await get().removeCache(id) - set( - produce(state => { - state.settings.servers = state.settings.servers.filter(s => s.id !== id) - }), - ) + set(state => { + state.settings.servers = state.settings.servers.filter(s => s.id !== id) + }) }, updateServer: server => { - set( - produce(state => { - state.settings.servers = replaceIndex( - state.settings.servers, - state.settings.servers.findIndex(s => s.id === server.id), - server, - ) - }), - ) + set(state => { + state.settings.servers = replaceIndex( + state.settings.servers, + state.settings.servers.findIndex(s => s.id === server.id), + server, + ) + }) if (get().settings.activeServer === server.id) { get().setActiveServer(server.id, true) @@ -163,29 +151,22 @@ export const createSettingsSlice = (set: SetState, get: GetState): }, setScrobble: scrobble => { - set( - produce(state => { - state.settings.scrobble = scrobble - }), - ) + set(state => { + state.settings.scrobble = scrobble + }) }, setEstimateContentLength: estimateContentLength => { - set( - produce(state => { - state.settings.estimateContentLength = estimateContentLength - }), - ) - + set(state => { + state.settings.estimateContentLength = estimateContentLength + }) get().rebuildQueue() }, setMaxBitrateWifi: maxBitrateWifi => { - set( - produce(state => { - state.settings.maxBitrateWifi = maxBitrateWifi - }), - ) + set(state => { + state.settings.maxBitrateWifi = maxBitrateWifi + }) if (get().netState === 'wifi') { get().rebuildQueue() @@ -193,11 +174,9 @@ export const createSettingsSlice = (set: SetState, get: GetState): }, setMaxBitrateMobile: maxBitrateMobile => { - set( - produce(state => { - state.settings.maxBitrateMobile = maxBitrateMobile - }), - ) + set(state => { + state.settings.maxBitrateMobile = maxBitrateMobile + }) if (get().netState === 'mobile') { get().rebuildQueue() @@ -209,11 +188,9 @@ export const createSettingsSlice = (set: SetState, get: GetState): return } - set( - produce(state => { - state.settings.minBuffer = Math.max(1, Math.min(minBuffer, state.settings.maxBuffer / 2)) - }), - ) + set(state => { + state.settings.minBuffer = Math.max(1, Math.min(minBuffer, state.settings.maxBuffer / 2)) + }) get().rebuildQueue() }, @@ -223,11 +200,9 @@ export const createSettingsSlice = (set: SetState, get: GetState): return } - set( - produce(state => { - state.settings.maxBuffer = Math.min(5 * 60, Math.max(maxBuffer, state.settings.minBuffer * 2)) - }), - ) + set(state => { + state.settings.maxBuffer = Math.min(5 * 60, Math.max(maxBuffer, state.settings.minBuffer * 2)) + }) get().rebuildQueue() }, @@ -253,19 +228,15 @@ export const createSettingsSlice = (set: SetState, get: GetState): }, setLibraryAlbumFilter: filter => { - set( - produce(state => { - state.settings.screens.library.albums = filter - }), - ) + set(state => { + state.settings.screens.library.albums = filter + }) }, setLibraryArtistFiler: filter => { - set( - produce(state => { - state.settings.screens.library.artists = filter - }), - ) + set(state => { + state.settings.screens.library.artists = filter + }) }, }) diff --git a/app/state/store.ts b/app/state/store.ts index 20be9ac..796c2bd 100644 --- a/app/state/store.ts +++ b/app/state/store.ts @@ -1,13 +1,15 @@ import { createSettingsSlice, SettingsSlice } from '@app/state/settings' import AsyncStorage from '@react-native-async-storage/async-storage' import equal from 'fast-deep-equal/es6/react' -import create, { GetState, Mutate, SetState, StateSelector, StoreApi } from 'zustand' +import create, { GetState, Mutate, SetState, State, StateCreator, StateSelector, StoreApi } from 'zustand' import { persist, subscribeWithSelector } from 'zustand/middleware' import { CacheSlice, createCacheSlice } from './cache' import { createLibrarySlice, LibrarySlice } from './library' import migrations from './migrations' import { createTrackPlayerSlice, TrackPlayerSlice } from './trackplayer' import { createTrackPlayerMapSlice, TrackPlayerMapSlice } from './trackplayermap' +import produce, { Draft } from 'immer' +import { WritableDraft } from 'immer/dist/internal' const DB_VERSION = migrations.length @@ -20,6 +22,37 @@ export type Store = SettingsSlice & setHydrated: (hydrated: boolean) => void } +// taken from zustand test examples: +// https://github.com/pmndrs/zustand/blob/v3.7.1/tests/middlewareTypes.test.tsx#L20 +const immer = + < + T extends State, + CustomSetState extends SetState, + CustomGetState extends GetState, + CustomStoreApi extends StoreApi, + >( + config: StateCreator< + T, + (partial: ((draft: Draft) => void) | T, replace?: boolean) => void, + CustomGetState, + CustomStoreApi + >, + ): StateCreator => + (set, get, api) => + config( + (partial, replace) => { + const nextState = typeof partial === 'function' ? produce(partial as (state: Draft) => T) : (partial as T) + return set(nextState, replace) + }, + get, + api, + ) + +export type SetStore = (partial: Store | ((draft: WritableDraft) => void), replace?: boolean | undefined) => void +export type GetStore = GetState + +// types taken from zustand test examples: +// https://github.com/pmndrs/zustand/blob/v3.7.1/tests/middlewareTypes.test.tsx#L584 export const useStore = create< Store, SetState, @@ -28,7 +61,7 @@ export const useStore = create< >( subscribeWithSelector( persist( - (set, get) => ({ + immer((set, get) => ({ ...createSettingsSlice(set, get), ...createLibrarySlice(set, get), ...createTrackPlayerSlice(set, get), @@ -36,13 +69,15 @@ export const useStore = create< ...createCacheSlice(set, get), hydrated: false, - setHydrated: hydrated => set({ hydrated }), - }), + setHydrated: hydrated => + set(state => { + state.hydrated = hydrated + }), + })), { name: '@appStore', version: DB_VERSION, getStorage: () => AsyncStorage, - // whitelist: ['settings', 'cacheFiles'], partialize: state => ({ settings: state.settings, cacheFiles: state.cacheFiles }), onRehydrateStorage: _preState => { return async (postState, _error) => { diff --git a/app/state/trackplayer.ts b/app/state/trackplayer.ts index d61b653..e11b366 100644 --- a/app/state/trackplayer.ts +++ b/app/state/trackplayer.ts @@ -3,8 +3,7 @@ import { Song } from '@app/models/library' import PromiseQueue from '@app/util/PromiseQueue' import produce from 'immer' import TrackPlayer, { PlayerOptions, RepeatMode, State, Track } from 'react-native-track-player' -import { GetState, SetState } from 'zustand' -import { Store } from './store' +import { GetStore, SetStore } from './store' export type TrackExt = Track & { id: string @@ -114,15 +113,24 @@ export const selectTrackPlayer = { export const trackPlayerCommands = new PromiseQueue(1) -export const createTrackPlayerSlice = (set: SetState, get: GetState): TrackPlayerSlice => ({ +export const createTrackPlayerSlice = (set: SetStore, get: GetStore): TrackPlayerSlice => ({ queueName: undefined, - setQueueName: name => set({ queueName: name }), + setQueueName: name => + set(state => { + state.queueName = name + }), queueContextType: undefined, - setQueueContextType: queueContextType => set({ queueContextType }), + setQueueContextType: queueContextType => + set(state => { + state.queueContextType = queueContextType + }), queueContextId: undefined, - setQueueContextId: queueContextId => set({ queueContextId }), + setQueueContextId: queueContextId => + set(state => { + state.queueContextId = queueContextId + }), shuffleOrder: undefined, toggleShuffle: async () => { @@ -140,7 +148,9 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState { + state.shuffleOrder = shuffleOrder + }) } else { const tracks = unshuffleTracks(queue, queueShuffleOrder) @@ -155,10 +165,14 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState { + state.shuffleOrder = undefined + }) } - set({ queue: await getQueue() }) + set(async state => { + state.queue = await getQueue() + }) get().setCurrentTrackIdx(await getCurrentTrack()) }) }, @@ -182,12 +196,17 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState { + state.repeatMode = nextMode + }) }) }, playerState: State.None, - setPlayerState: playerState => set({ playerState }), + setPlayerState: playerState => + set(state => { + state.playerState = playerState + }), currentTrack: undefined, currentTrackIdx: undefined, @@ -201,7 +220,10 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState set({ duckPaused }), + setDuckPaused: duckPaused => + set(state => { + state.duckPaused = duckPaused + }), queue: [], setQueue: async (songs, name, contextType, contextId, playTrack, shuffle) => { @@ -219,21 +241,25 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState { + state.shuffleOrder = shuffleOrder + }) queue = tracks playTrack = 0 } else { - set({ shuffleOrder: undefined }) + set(state => { + state.shuffleOrder = undefined + }) } playTrack = playTrack || 0 try { - set({ - queue, - queueName: name, - queueContextType: contextType, - queueContextId: contextId, + set(state => { + state.queue = queue + state.queueName = name + state.queueContextType = contextType + state.queueContextId = contextId }) get().setCurrentTrackIdx(playTrack) @@ -256,7 +282,10 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState set({ progress }), + setProgress: progress => + set(state => { + state.progress = progress + }), scrobbleTrack: async id => { const client = get().client @@ -278,7 +307,9 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState { + state.netState = netState + }) get().rebuildQueue() }, @@ -290,7 +321,7 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState, get: GetState { + state.queue = queue + state.queueName = queueName + state.queueContextType = queueContextType + state.queueContextId = queueContextId }) get().setCurrentTrackIdx(currentTrack) @@ -324,7 +355,7 @@ export const createTrackPlayerSlice = (set: SetState, get: GetState, get: GetState { - set({ - queueName: undefined, - queueContextType: undefined, - queueContextId: undefined, - shuffleOrder: undefined, - repeatMode: RepeatMode.Off, - playerState: State.None, - currentTrack: undefined, - currentTrackIdx: undefined, - queue: [], - progress: { position: 0, duration: 0, buffered: 0 }, + set(state => { + state.queueName = undefined + state.queueContextType = undefined + state.queueContextId = undefined + state.shuffleOrder = undefined + state.repeatMode = RepeatMode.Off + state.playerState = State.None + state.currentTrack = undefined + state.currentTrackIdx = undefined + state.queue = [] + state.progress = { position: 0, duration: 0, buffered: 0 } }) }, diff --git a/app/state/trackplayermap.ts b/app/state/trackplayermap.ts index 3c80ff4..d4dd505 100644 --- a/app/state/trackplayermap.ts +++ b/app/state/trackplayermap.ts @@ -1,7 +1,6 @@ import { Song } from '@app/models/library' import userAgent from '@app/util/userAgent' -import { GetState, SetState } from 'zustand' -import { Store } from './store' +import { GetStore, SetStore } from './store' import { TrackExt } from './trackplayer' export type TrackPlayerMapSlice = { @@ -14,7 +13,7 @@ export const selectTrackPlayerMap = { mapTrackExtToSong: (store: TrackPlayerMapSlice) => store.mapTrackExtToSong, } -export const createTrackPlayerMapSlice = (set: SetState, get: GetState): TrackPlayerMapSlice => ({ +export const createTrackPlayerMapSlice = (set: SetStore, get: GetStore): TrackPlayerMapSlice => ({ mapSongtoTrackExt: async song => { let artwork = require('@res/fallback.png') if (song.coverArt) {