mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
added artist filters
This commit is contained in:
parent
43d8cc7fa7
commit
22b6524e8c
@ -14,14 +14,18 @@ export const useFetchList = <T>(fetchList: () => Promise<T[]>) => {
|
|||||||
})
|
})
|
||||||
}, [fetchList])
|
}, [fetchList])
|
||||||
|
|
||||||
|
const reset = useCallback(() => {
|
||||||
|
setList([])
|
||||||
|
refresh()
|
||||||
|
}, [refresh])
|
||||||
|
|
||||||
useActiveServerRefresh(
|
useActiveServerRefresh(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
setList([])
|
reset()
|
||||||
refresh()
|
}, [reset]),
|
||||||
}, [refresh]),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return { list, refreshing, refresh }
|
return { list, refreshing, refresh, reset }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useFetchPaginatedList = <T>(
|
export const useFetchPaginatedList = <T>(
|
||||||
|
|||||||
@ -8,13 +8,19 @@ export interface Server {
|
|||||||
salt: string
|
salt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FilterSettings {
|
export interface AlbumFilterSettings {
|
||||||
type: GetAlbumList2Type
|
type: GetAlbumList2Type
|
||||||
fromYear: number
|
fromYear: number
|
||||||
toYear: number
|
toYear: number
|
||||||
genre: string
|
genre: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ArtistFilterType = 'random' | 'starred' | 'alphabeticalByName'
|
||||||
|
|
||||||
|
export interface ArtistFilterSettings {
|
||||||
|
type: ArtistFilterType
|
||||||
|
}
|
||||||
|
|
||||||
export interface AppSettings {
|
export interface AppSettings {
|
||||||
servers: Server[]
|
servers: Server[]
|
||||||
screens: {
|
screens: {
|
||||||
@ -22,7 +28,8 @@ export interface AppSettings {
|
|||||||
lists: string[]
|
lists: string[]
|
||||||
}
|
}
|
||||||
library: {
|
library: {
|
||||||
albums: FilterSettings
|
albums: AlbumFilterSettings
|
||||||
|
artists: ArtistFilterSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
activeServer?: string
|
activeServer?: string
|
||||||
|
|||||||
@ -73,9 +73,7 @@ const AlbumsList = () => {
|
|||||||
const size = layout.width / 3 - styles.itemWrapper.marginHorizontal * 2
|
const size = layout.width / 3 - styles.itemWrapper.marginHorizontal * 2
|
||||||
const height = size + 36
|
const height = size + 36
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => reset(), [reset, filter])
|
||||||
reset()
|
|
||||||
}, [reset, filter])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|||||||
@ -1,34 +1,78 @@
|
|||||||
|
import FilterButton, { OptionData } from '@app/components/FilterButton'
|
||||||
import GradientFlatList from '@app/components/GradientFlatList'
|
import GradientFlatList from '@app/components/GradientFlatList'
|
||||||
import ListItem from '@app/components/ListItem'
|
import ListItem from '@app/components/ListItem'
|
||||||
import { useFetchList } from '@app/hooks/list'
|
import { useFetchList } from '@app/hooks/list'
|
||||||
import { Artist } from '@app/models/music'
|
import { Artist } from '@app/models/music'
|
||||||
|
import { ArtistFilterType } from '@app/models/settings'
|
||||||
import { selectMusic } from '@app/state/music'
|
import { selectMusic } from '@app/state/music'
|
||||||
|
import { selectSettings } from '@app/state/settings'
|
||||||
import { useStore } from '@app/state/store'
|
import { useStore } from '@app/state/store'
|
||||||
import React from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { StyleSheet } from 'react-native'
|
import { StyleSheet, View } from 'react-native'
|
||||||
|
|
||||||
const ArtistRenderItem: React.FC<{ item: Artist }> = ({ item }) => (
|
const ArtistRenderItem: React.FC<{ item: Artist }> = ({ item }) => (
|
||||||
<ListItem item={item} showArt={true} showStar={false} listStyle="big" />
|
<ListItem item={item} showArt={true} showStar={false} listStyle="big" />
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const filterOptions: OptionData[] = [
|
||||||
|
{ text: 'By name', value: 'alphabeticalByName' },
|
||||||
|
{ text: 'Starred', value: 'starred' },
|
||||||
|
{ text: 'Random', value: 'random' },
|
||||||
|
]
|
||||||
|
|
||||||
const ArtistsList = () => {
|
const ArtistsList = () => {
|
||||||
const fetchArtists = useStore(selectMusic.fetchArtists)
|
const fetchArtists = useStore(selectMusic.fetchArtists)
|
||||||
const { list, refreshing, refresh } = useFetchList(fetchArtists)
|
const { list, refreshing, refresh } = useFetchList(fetchArtists)
|
||||||
|
const filter = useStore(selectSettings.libraryArtistFilter)
|
||||||
|
const setFilter = useStore(selectSettings.setLibraryArtistFiler)
|
||||||
|
const [sortedList, setSortedList] = useState<Artist[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
switch (filter.type) {
|
||||||
|
case 'alphabeticalByName':
|
||||||
|
setSortedList([...list].sort((a, b) => a.name.localeCompare(b.name)))
|
||||||
|
break
|
||||||
|
case 'random':
|
||||||
|
setSortedList([...list].sort(() => Math.random() - 0.5))
|
||||||
|
break
|
||||||
|
case 'starred':
|
||||||
|
setSortedList([...list].sort((a, b) => a.name.localeCompare(b.name)).filter(a => a.starred))
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
setSortedList([...list])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}, [list, filter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GradientFlatList
|
<View style={styles.container}>
|
||||||
contentContainerStyle={styles.listContent}
|
<GradientFlatList
|
||||||
data={list}
|
contentContainerStyle={styles.listContent}
|
||||||
renderItem={ArtistRenderItem}
|
data={sortedList}
|
||||||
keyExtractor={item => item.id}
|
renderItem={ArtistRenderItem}
|
||||||
onRefresh={refresh}
|
keyExtractor={item => item.id}
|
||||||
refreshing={refreshing}
|
onRefresh={refresh}
|
||||||
overScrollMode="never"
|
refreshing={refreshing}
|
||||||
/>
|
overScrollMode="never"
|
||||||
|
/>
|
||||||
|
<FilterButton
|
||||||
|
data={filterOptions}
|
||||||
|
value={filter.type}
|
||||||
|
onSelect={selection => {
|
||||||
|
setFilter({
|
||||||
|
...filter,
|
||||||
|
type: selection as ArtistFilterType,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
listContent: {
|
listContent: {
|
||||||
minHeight: '100%',
|
minHeight: '100%',
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { AppSettings, FilterSettings, Server } from '@app/models/settings'
|
import { AppSettings, ArtistFilterSettings, AlbumFilterSettings, Server } from '@app/models/settings'
|
||||||
import { Store } from '@app/state/store'
|
import { Store } from '@app/state/store'
|
||||||
import { SubsonicApiClient } from '@app/subsonic/api'
|
import { SubsonicApiClient } from '@app/subsonic/api'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
@ -23,7 +23,8 @@ export type SettingsSlice = {
|
|||||||
|
|
||||||
pingServer: (server?: Server) => Promise<boolean>
|
pingServer: (server?: Server) => Promise<boolean>
|
||||||
|
|
||||||
setLibraryAlbumFilter: (filter: FilterSettings) => void
|
setLibraryAlbumFilter: (filter: AlbumFilterSettings) => void
|
||||||
|
setLibraryArtistFiler: (filter: ArtistFilterSettings) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectSettings = {
|
export const selectSettings = {
|
||||||
@ -59,6 +60,8 @@ export const selectSettings = {
|
|||||||
|
|
||||||
setLibraryAlbumFilter: (state: SettingsSlice) => state.setLibraryAlbumFilter,
|
setLibraryAlbumFilter: (state: SettingsSlice) => state.setLibraryAlbumFilter,
|
||||||
libraryAlbumFilter: (state: SettingsSlice) => state.settings.screens.library.albums,
|
libraryAlbumFilter: (state: SettingsSlice) => state.settings.screens.library.albums,
|
||||||
|
setLibraryArtistFiler: (state: SettingsSlice) => state.setLibraryArtistFiler,
|
||||||
|
libraryArtistFilter: (state: SettingsSlice) => state.settings.screens.library.artists,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createSettingsSlice = (set: SetState<Store>, get: GetState<Store>): SettingsSlice => ({
|
export const createSettingsSlice = (set: SetState<Store>, get: GetState<Store>): SettingsSlice => ({
|
||||||
@ -75,6 +78,9 @@ export const createSettingsSlice = (set: SetState<Store>, get: GetState<Store>):
|
|||||||
toYear: 9999,
|
toYear: 9999,
|
||||||
genre: '',
|
genre: '',
|
||||||
},
|
},
|
||||||
|
artists: {
|
||||||
|
type: 'alphabeticalByName',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
scrobble: false,
|
scrobble: false,
|
||||||
@ -249,6 +255,14 @@ export const createSettingsSlice = (set: SetState<Store>, get: GetState<Store>):
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setLibraryArtistFiler: filter => {
|
||||||
|
set(
|
||||||
|
produce<SettingsSlice>(state => {
|
||||||
|
state.settings.screens.library.artists = filter
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function replaceIndex<T>(array: T[], index: number, replacement: T): T[] {
|
function replaceIndex<T>(array: T[], index: number, replacement: T): T[] {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user