mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
Library store refactor (#76)
* start of music store refactor moving stuff into a state cache better separate it from view logic * added paginated list/album list * reworked fetchAlbumList to remove ui state refactored home screen to use new method i broke playing songs somehow, JS thread goes into a loop * don't reset parts manually, do it all at once * fixed perf issue related to too many rerenders rerenders were caused by strict equality check on object/array picks switched artistInfo to new store updated zustand and fixed deprecation warnings * update typescript and use workspace tsc version for vscode * remove old artistInfo * switched to new playlist w/songs removed more unused stuff * remove unused + (slightly) rework search * refactor star * use only original/large imges for covers/artist fix view artist from context menu add loading indicators to song list and artist views (show info we have right away) * set starred/unstar assuming it works and correct state on error * reorg, remove old music slice files * added back fix for song cover art * sort artists by localCompare name * update licenses * fix now playing background grey bar * update react-native-gesture-handler for node-fetch security alert * fix another gradient height grey bar issue * update licenses again * remove thumbnail cache * rename to remove "Library" from methods * Revert "remove thumbnail cache" This reverts commite0db4931f1. * use ids for lists, pull state later * Revert "use only original/large imges for covers/artist" This reverts commitc9aea9065c. * deep equal ListItem props for now this needs a bigger refactor * use immer as middleware * refactor api client to use string method hoping to use this for requestKey/deduping next * use thumbnails in list items * Revert "refactor api client to use string method" This reverts commit234326135b. * rename/cleanup * store servers by id * get rid of settings selectors * renames for clarity remove unused estimateContentLength setting * remove trackplayer selectors * fix migration for library filter settings * fixed shuffle order reporting wrong track/queue * removed the other selectors * don't actually need es6/react for our state * fix slow artist sort on star localeCompare is too slow for large lists
This commit is contained in:
+78
-106
@@ -1,27 +1,10 @@
|
||||
import { NoClientError } from '@app/models/error'
|
||||
import { Song } from '@app/models/music'
|
||||
import { Song } from '@app/models/library'
|
||||
import { Progress, QueueContextType, TrackExt } from '@app/models/trackplayer'
|
||||
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'
|
||||
|
||||
export type TrackExt = Track & {
|
||||
id: string
|
||||
coverArt?: string
|
||||
artistId?: string
|
||||
albumId?: string
|
||||
track?: number
|
||||
discNumber?: number
|
||||
}
|
||||
|
||||
export type Progress = {
|
||||
position: number
|
||||
duration: number
|
||||
buffered: number
|
||||
}
|
||||
|
||||
export type QueueContextType = 'album' | 'playlist' | 'song' | 'artist'
|
||||
import TrackPlayer, { PlayerOptions, RepeatMode, State } from 'react-native-track-player'
|
||||
import { GetStore, SetStore } from './store'
|
||||
|
||||
export type TrackPlayerSlice = {
|
||||
queueName?: string
|
||||
@@ -74,55 +57,26 @@ export type TrackPlayerSlice = {
|
||||
getPlayerOptions: () => PlayerOptions
|
||||
}
|
||||
|
||||
export const selectTrackPlayer = {
|
||||
queueName: (store: TrackPlayerSlice) => store.queueName,
|
||||
setQueueName: (store: TrackPlayerSlice) => store.setQueueName,
|
||||
|
||||
queueContextType: (store: TrackPlayerSlice) => store.queueContextType,
|
||||
setQueueContextType: (store: TrackPlayerSlice) => store.setQueueContextType,
|
||||
|
||||
queueContextId: (store: TrackPlayerSlice) => store.queueContextId,
|
||||
setQueueContextId: (store: TrackPlayerSlice) => store.setQueueContextId,
|
||||
|
||||
shuffleOrder: (store: TrackPlayerSlice) => store.shuffleOrder,
|
||||
shuffled: (store: TrackPlayerSlice) => !!store.shuffleOrder,
|
||||
toggleShuffle: (store: TrackPlayerSlice) => store.toggleShuffle,
|
||||
|
||||
repeatMode: (store: TrackPlayerSlice) => store.repeatMode,
|
||||
toggleRepeatMode: (store: TrackPlayerSlice) => store.toggleRepeatMode,
|
||||
|
||||
playerState: (store: TrackPlayerSlice) => store.playerState,
|
||||
setPlayerState: (store: TrackPlayerSlice) => store.setPlayerState,
|
||||
|
||||
currentTrack: (store: TrackPlayerSlice) => store.currentTrack,
|
||||
currentTrackIdx: (store: TrackPlayerSlice) => store.currentTrackIdx,
|
||||
setCurrentTrackIdx: (store: TrackPlayerSlice) => store.setCurrentTrackIdx,
|
||||
|
||||
queue: (store: TrackPlayerSlice) => store.queue,
|
||||
setQueue: (store: TrackPlayerSlice) => store.setQueue,
|
||||
|
||||
progress: (store: TrackPlayerSlice) => store.progress,
|
||||
setProgress: (store: TrackPlayerSlice) => store.setProgress,
|
||||
|
||||
scrobbleTrack: (store: TrackPlayerSlice) => store.scrobbleTrack,
|
||||
|
||||
setNetState: (store: TrackPlayerSlice) => store.setNetState,
|
||||
buildStreamUri: (store: TrackPlayerSlice) => store.buildStreamUri,
|
||||
|
||||
resetTrackPlayerState: (store: TrackPlayerSlice) => store.resetTrackPlayerState,
|
||||
}
|
||||
|
||||
export const trackPlayerCommands = new PromiseQueue(1)
|
||||
|
||||
export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store>): 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 +94,9 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
}
|
||||
|
||||
await TrackPlayer.add(tracks)
|
||||
set({ shuffleOrder })
|
||||
set(state => {
|
||||
state.shuffleOrder = shuffleOrder
|
||||
})
|
||||
} else {
|
||||
const tracks = unshuffleTracks(queue, queueShuffleOrder)
|
||||
|
||||
@@ -155,11 +111,18 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
await TrackPlayer.add(tracks)
|
||||
}
|
||||
|
||||
set({ shuffleOrder: undefined })
|
||||
set(state => {
|
||||
state.shuffleOrder = undefined
|
||||
})
|
||||
}
|
||||
|
||||
set({ queue: await getQueue() })
|
||||
get().setCurrentTrackIdx(await getCurrentTrack())
|
||||
const newQueue = await getQueue()
|
||||
const newCurrentTrackIdx = await getCurrentTrack()
|
||||
|
||||
set(state => {
|
||||
state.queue = newQueue
|
||||
})
|
||||
get().setCurrentTrackIdx(newCurrentTrackIdx)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -182,12 +145,17 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
}
|
||||
|
||||
await TrackPlayer.setRepeatMode(nextMode)
|
||||
set({ repeatMode: nextMode })
|
||||
set(state => {
|
||||
state.repeatMode = nextMode
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
playerState: State.None,
|
||||
setPlayerState: playerState => set({ playerState }),
|
||||
setPlayerState: playerState =>
|
||||
set(state => {
|
||||
state.playerState = playerState
|
||||
}),
|
||||
|
||||
currentTrack: undefined,
|
||||
currentTrackIdx: undefined,
|
||||
@@ -201,7 +169,10 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
},
|
||||
|
||||
duckPaused: false,
|
||||
setDuckPaused: duckPaused => set({ duckPaused }),
|
||||
setDuckPaused: duckPaused =>
|
||||
set(state => {
|
||||
state.duckPaused = duckPaused
|
||||
}),
|
||||
|
||||
queue: [],
|
||||
setQueue: async (songs, name, contextType, contextId, playTrack, shuffle) => {
|
||||
@@ -217,31 +188,27 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
|
||||
let queue = await get().mapSongstoTrackExts(songs)
|
||||
|
||||
try {
|
||||
for (const t of queue) {
|
||||
t.url = get().buildStreamUri(t.id)
|
||||
}
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
if (shuffled) {
|
||||
const { tracks, shuffleOrder } = shuffleTracks(queue, playTrack)
|
||||
set({ shuffleOrder })
|
||||
set(state => {
|
||||
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)
|
||||
|
||||
@@ -264,7 +231,10 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
},
|
||||
|
||||
progress: { position: 0, duration: 0, buffered: 0 },
|
||||
setProgress: progress => set({ progress }),
|
||||
setProgress: progress =>
|
||||
set(state => {
|
||||
state.progress = progress
|
||||
}),
|
||||
|
||||
scrobbleTrack: async id => {
|
||||
const client = get().client
|
||||
@@ -286,7 +256,9 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
if (netState === get().netState) {
|
||||
return
|
||||
}
|
||||
set({ netState })
|
||||
set(state => {
|
||||
state.netState = netState
|
||||
})
|
||||
get().rebuildQueue()
|
||||
},
|
||||
|
||||
@@ -298,7 +270,7 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
}
|
||||
|
||||
const currentTrack = await getCurrentTrack()
|
||||
const state = await getPlayerState()
|
||||
const playerState = await getPlayerState()
|
||||
const position = (await TrackPlayer.getPosition()) || 0
|
||||
|
||||
const queueName = get().queueName
|
||||
@@ -316,11 +288,11 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
return
|
||||
}
|
||||
|
||||
set({
|
||||
queue,
|
||||
queueName,
|
||||
queueContextId,
|
||||
queueContextType,
|
||||
set(state => {
|
||||
state.queue = queue
|
||||
state.queueName = queueName
|
||||
state.queueContextType = queueContextType
|
||||
state.queueContextId = queueContextId
|
||||
})
|
||||
get().setCurrentTrackIdx(currentTrack)
|
||||
|
||||
@@ -332,7 +304,7 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
|
||||
await TrackPlayer.seekTo(position)
|
||||
|
||||
if (state === State.Playing || forcePlay) {
|
||||
if (playerState === State.Playing || forcePlay) {
|
||||
await TrackPlayer.play()
|
||||
}
|
||||
})
|
||||
@@ -346,23 +318,23 @@ export const createTrackPlayerSlice = (set: SetState<Store>, get: GetState<Store
|
||||
|
||||
return client.streamUri({
|
||||
id,
|
||||
estimateContentLength: get().settings.estimateContentLength,
|
||||
estimateContentLength: true,
|
||||
maxBitRate: get().netState === 'mobile' ? get().settings.maxBitrateMobile : get().settings.maxBitrateWifi,
|
||||
})
|
||||
},
|
||||
|
||||
resetTrackPlayerState: () => {
|
||||
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 }
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user