mirror of
https://github.com/austinried/subtracks.git
synced 2026-02-10 06:52:43 +01:00
remove unused + (slightly) rework search
This commit is contained in:
@@ -21,12 +21,6 @@ export interface Album extends AlbumListItem {
|
||||
year?: number
|
||||
}
|
||||
|
||||
export interface SearchResults {
|
||||
artists: Artist[]
|
||||
albums: AlbumListItem[]
|
||||
songs: Song[]
|
||||
}
|
||||
|
||||
export interface PlaylistListItem {
|
||||
itemType: 'playlist'
|
||||
id: string
|
||||
|
||||
@@ -5,9 +5,8 @@ import ListItem from '@app/components/ListItem'
|
||||
import NothingHere from '@app/components/NothingHere'
|
||||
import TextInput from '@app/components/TextInput'
|
||||
import { useActiveServerRefresh } from '@app/hooks/server'
|
||||
import { ListableItem, SearchResults, Song } from '@app/models/music'
|
||||
import { selectMusic } from '@app/state/music'
|
||||
import { useStore } from '@app/state/store'
|
||||
import { Album, Artist, mapById, SearchResults, Song } from '@app/state/library'
|
||||
import { useStore, useStoreDeep } from '@app/state/store'
|
||||
import { selectTrackPlayer } from '@app/state/trackplayer'
|
||||
import colors from '@app/styles/colors'
|
||||
import font from '@app/styles/font'
|
||||
@@ -42,8 +41,27 @@ const SongItem = React.memo<{ item: Song }>(({ item }) => {
|
||||
const ResultsCategory = React.memo<{
|
||||
name: string
|
||||
query: string
|
||||
items: ListableItem[]
|
||||
}>(({ name, query, items }) => {
|
||||
ids: string[]
|
||||
type: 'artist' | 'album' | 'song'
|
||||
}>(({ name, query, type, ids }) => {
|
||||
const items: (Album | Artist | Song)[] = useStoreDeep(
|
||||
useCallback(
|
||||
store => {
|
||||
switch (type) {
|
||||
case 'album':
|
||||
return mapById(store.entities.albums, ids)
|
||||
case 'artist':
|
||||
return mapById(store.entities.artists, ids)
|
||||
case 'song':
|
||||
return mapById(store.entities.songs, ids)
|
||||
default:
|
||||
return []
|
||||
}
|
||||
},
|
||||
[ids, type],
|
||||
),
|
||||
)
|
||||
|
||||
const navigation = useNavigation()
|
||||
|
||||
if (items.length === 0) {
|
||||
@@ -54,8 +72,8 @@ const ResultsCategory = React.memo<{
|
||||
<>
|
||||
<Header>{name}</Header>
|
||||
{items.map(a =>
|
||||
a.itemType === 'song' ? (
|
||||
<SongItem key={a.id} item={a} />
|
||||
type === 'song' ? (
|
||||
<SongItem key={a.id} item={a as Song} />
|
||||
) : (
|
||||
<ListItem key={a.id} item={a} showArt={true} showStar={false} />
|
||||
),
|
||||
@@ -78,15 +96,15 @@ const Results = React.memo<{
|
||||
}>(({ results, query }) => {
|
||||
return (
|
||||
<>
|
||||
<ResultsCategory name="Artists" query={query} items={results.artists} />
|
||||
<ResultsCategory name="Albums" query={query} items={results.albums} />
|
||||
<ResultsCategory name="Songs" query={query} items={results.songs} />
|
||||
<ResultsCategory name="Artists" query={query} type={'artist'} ids={results.artists} />
|
||||
<ResultsCategory name="Albums" query={query} type={'album'} ids={results.albums} />
|
||||
<ResultsCategory name="Songs" query={query} type={'song'} ids={results.songs} />
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
const Search = () => {
|
||||
const fetchSearchResults = useStore(selectMusic.fetchSearchResults)
|
||||
const fetchSearchResults = useStore(store => store.fetchLibrarySearchResults)
|
||||
const [results, setResults] = useState<SearchResults>({ artists: [], albums: [], songs: [] })
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
const [text, setText] = useState('')
|
||||
@@ -118,7 +136,7 @@ const Search = () => {
|
||||
() =>
|
||||
debounce(async (query: string) => {
|
||||
setRefreshing(true)
|
||||
setResults(await fetchSearchResults(query))
|
||||
setResults(await fetchSearchResults({ query, albumCount: 5, artistCount: 5, songCount: 5 }))
|
||||
setRefreshing(false)
|
||||
}, 400),
|
||||
[fetchSearchResults],
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import GradientFlatList from '@app/components/GradientFlatList'
|
||||
import ListItem from '@app/components/ListItem'
|
||||
import { useFetchPaginatedList } from '@app/hooks/list'
|
||||
import { AlbumListItem, Artist, Song } from '@app/models/music'
|
||||
import { selectMusic } from '@app/state/music'
|
||||
import { useStore } from '@app/state/store'
|
||||
import { Album, Artist, Song, mapById } from '@app/state/library'
|
||||
import { useStore, useStoreDeep } from '@app/state/store'
|
||||
import { selectTrackPlayer } from '@app/state/trackplayer'
|
||||
import { Search3Params } from '@app/subsonic/params'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import { StyleSheet } from 'react-native'
|
||||
|
||||
type SearchListItemType = AlbumListItem | Song | Artist
|
||||
type SearchListItemType = Album | Song | Artist
|
||||
|
||||
const ResultsListItem: React.FC<{ item: SearchListItemType }> = ({ item }) => {
|
||||
const setQueue = useStore(selectTrackPlayer.setQueue)
|
||||
@@ -40,27 +40,62 @@ const SearchResultsView: React.FC<{
|
||||
type: 'album' | 'artist' | 'song'
|
||||
}> = ({ query, type }) => {
|
||||
const navigation = useNavigation()
|
||||
const fetchSearchResults = useStore(selectMusic.fetchSearchResults)
|
||||
const { list, refreshing, refresh, fetchNextPage } = useFetchPaginatedList<SearchListItemType>(
|
||||
const fetchSearchResults = useStore(store => store.fetchLibrarySearchResults)
|
||||
const { list, refreshing, refresh, fetchNextPage } = useFetchPaginatedList(
|
||||
useCallback(
|
||||
(size, offset) =>
|
||||
fetchSearchResults(query, type, size, offset).then(results => {
|
||||
switch (type) {
|
||||
case 'album':
|
||||
return results.albums
|
||||
case 'artist':
|
||||
return results.artists
|
||||
case 'song':
|
||||
return results.songs
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}),
|
||||
async (size, offset) => {
|
||||
const params: Search3Params = { query }
|
||||
if (type === 'album') {
|
||||
params.albumCount = size
|
||||
params.albumOffset = offset
|
||||
} else if (type === 'artist') {
|
||||
params.artistCount = size
|
||||
params.artistOffset = offset
|
||||
} else if (type === 'song') {
|
||||
params.songCount = size
|
||||
params.songOffset = offset
|
||||
} else {
|
||||
params.albumCount = 5
|
||||
params.artistCount = 5
|
||||
params.songCount = 5
|
||||
}
|
||||
|
||||
const results = await fetchSearchResults(params)
|
||||
|
||||
switch (type) {
|
||||
case 'album':
|
||||
return results.albums
|
||||
case 'artist':
|
||||
return results.artists
|
||||
case 'song':
|
||||
return results.songs
|
||||
default:
|
||||
return []
|
||||
}
|
||||
},
|
||||
[fetchSearchResults, query, type],
|
||||
),
|
||||
100,
|
||||
)
|
||||
|
||||
const items: SearchListItemType[] = useStoreDeep(
|
||||
useCallback(
|
||||
store => {
|
||||
switch (type) {
|
||||
case 'album':
|
||||
return mapById(store.entities.albums, list)
|
||||
case 'artist':
|
||||
return mapById(store.entities.artists, list)
|
||||
case 'song':
|
||||
return mapById(store.entities.songs, list)
|
||||
default:
|
||||
return []
|
||||
}
|
||||
},
|
||||
[list, type],
|
||||
),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
title: `Search: "${query}"`,
|
||||
@@ -70,7 +105,7 @@ const SearchResultsView: React.FC<{
|
||||
|
||||
return (
|
||||
<GradientFlatList
|
||||
data={list}
|
||||
data={items}
|
||||
renderItem={SearchResultsRenderItem}
|
||||
keyExtractor={(item, i) => i.toString()}
|
||||
onRefresh={refresh}
|
||||
|
||||
@@ -1,23 +1,10 @@
|
||||
import { AlbumListItem, Artist, PlaylistListItem, SearchResults, StarrableItemType } from '@app/models/music'
|
||||
import { StarrableItemType } from '@app/models/music'
|
||||
import { Store } from '@app/state/store'
|
||||
import { GetAlbumList2Params, Search3Params, StarParams } from '@app/subsonic/params'
|
||||
import { StarParams } from '@app/subsonic/params'
|
||||
import produce from 'immer'
|
||||
import { GetState, SetState } from 'zustand'
|
||||
|
||||
export type MusicSlice = {
|
||||
//
|
||||
// lists-style state
|
||||
//
|
||||
fetchArtists: (size?: number, offset?: number) => Promise<Artist[]>
|
||||
fetchPlaylists: () => Promise<PlaylistListItem[]>
|
||||
fetchAlbums: () => Promise<AlbumListItem[]>
|
||||
fetchSearchResults: (
|
||||
query: string,
|
||||
type?: 'album' | 'song' | 'artist',
|
||||
size?: number,
|
||||
offset?: number,
|
||||
) => Promise<SearchResults>
|
||||
|
||||
//
|
||||
// actions, etc.
|
||||
//
|
||||
@@ -33,11 +20,6 @@ export type MusicSlice = {
|
||||
}
|
||||
|
||||
export const selectMusic = {
|
||||
fetchArtists: (store: MusicSlice) => store.fetchArtists,
|
||||
fetchPlaylists: (store: MusicSlice) => store.fetchPlaylists,
|
||||
fetchAlbums: (store: MusicSlice) => store.fetchAlbums,
|
||||
fetchSearchResults: (store: MusicSlice) => store.fetchSearchResults,
|
||||
|
||||
starItem: (store: MusicSlice) => store.starItem,
|
||||
}
|
||||
|
||||
@@ -55,141 +37,6 @@ function reduceStarred(
|
||||
}
|
||||
|
||||
export const createMusicSlice = (set: SetState<Store>, get: GetState<Store>): MusicSlice => ({
|
||||
fetchArtists: async () => {
|
||||
const client = get().client
|
||||
if (!client) {
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.getArtists()
|
||||
const artists = response.data.artists.map(get().mapArtistID3toArtist)
|
||||
|
||||
set(
|
||||
produce<MusicSlice>(state => {
|
||||
state.starredArtists = reduceStarred(state.starredArtists, artists)
|
||||
}),
|
||||
)
|
||||
|
||||
return artists
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
},
|
||||
|
||||
fetchPlaylists: async () => {
|
||||
const client = get().client
|
||||
if (!client) {
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.getPlaylists()
|
||||
return response.data.playlists.map(get().mapPlaylistListItem)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
},
|
||||
|
||||
fetchAlbums: async (size = 500, offset = 0) => {
|
||||
const client = get().client
|
||||
if (!client) {
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
const filter = get().settings.screens.library.albums
|
||||
|
||||
let params: GetAlbumList2Params
|
||||
switch (filter.type) {
|
||||
case 'byYear':
|
||||
params = {
|
||||
size,
|
||||
offset,
|
||||
type: filter.type,
|
||||
fromYear: filter.fromYear,
|
||||
toYear: filter.toYear,
|
||||
}
|
||||
break
|
||||
case 'byGenre':
|
||||
params = {
|
||||
size,
|
||||
offset,
|
||||
type: filter.type,
|
||||
genre: filter.genre,
|
||||
}
|
||||
break
|
||||
default:
|
||||
params = {
|
||||
size,
|
||||
offset,
|
||||
type: filter.type,
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
const response = await client.getAlbumList2(params)
|
||||
const albums = response.data.albums.map(get().mapAlbumID3toAlbumListItem)
|
||||
|
||||
set(
|
||||
produce<MusicSlice>(state => {
|
||||
state.starredAlbums = reduceStarred(state.starredAlbums, albums)
|
||||
}),
|
||||
)
|
||||
|
||||
return albums
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
},
|
||||
|
||||
fetchSearchResults: async (query, type, size, offset) => {
|
||||
if (query.length < 2) {
|
||||
return { artists: [], albums: [], songs: [] }
|
||||
}
|
||||
|
||||
const client = get().client
|
||||
if (!client) {
|
||||
return { artists: [], albums: [], songs: [] }
|
||||
}
|
||||
|
||||
try {
|
||||
const params: Search3Params = { query }
|
||||
if (type === 'album') {
|
||||
params.albumCount = size
|
||||
params.albumOffset = offset
|
||||
} else if (type === 'artist') {
|
||||
params.artistCount = size
|
||||
params.artistOffset = offset
|
||||
} else if (type === 'song') {
|
||||
params.songCount = size
|
||||
params.songOffset = offset
|
||||
} else {
|
||||
params.albumCount = 5
|
||||
params.artistCount = 5
|
||||
params.songCount = 5
|
||||
}
|
||||
|
||||
const response = await client.search3(params)
|
||||
|
||||
const artists = response.data.artists.map(get().mapArtistID3toArtist)
|
||||
const albums = response.data.albums.map(get().mapAlbumID3toAlbumListItem)
|
||||
const songs = await get().mapChildrenToSongs(response.data.songs)
|
||||
|
||||
set(
|
||||
produce<MusicSlice>(state => {
|
||||
state.starredSongs = reduceStarred(state.starredSongs, songs)
|
||||
state.starredArtists = reduceStarred(state.starredArtists, artists)
|
||||
state.starredAlbums = reduceStarred(state.starredAlbums, albums)
|
||||
}),
|
||||
)
|
||||
|
||||
return { artists, albums, songs }
|
||||
} catch {
|
||||
return { artists: [], albums: [], songs: [] }
|
||||
}
|
||||
},
|
||||
|
||||
starredSongs: {},
|
||||
starredAlbums: {},
|
||||
starredArtists: {},
|
||||
|
||||
Reference in New Issue
Block a user