zaphyra's git: domsonic

subsonic web-client

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 import { ref, watch } from 'vue'

import type { SearchMode, Artist, Album, Track } from '../types'
import { useSubsonicApi } from '../subsonicApi'
import { useMainStore } from '../store/main'

import { AlbumList } from '../components/AlbumList.vine'
import { ArtistList } from '../components/ArtistList.vine'
import { TrackList } from '../components/TrackList.vine'

interface State {
  artists: Artist[],
  albums: Album[],
  tracks: Track[],
  hasMore: boolean,
}

export const SearchResultView = ({ query, mode = null }: { query: string, mode?: SearchMode }) => {
  const
    subsonicApi = useSubsonicApi(),
    mainStore = useMainStore(),
    pageSize = 20,
    state = ref<State>({
      artists: [],
      albums: [],
      tracks: [],
      hasMore: true,
    } as State),

    loadMore = async() => {
      try {
        mainStore.isLoading = true

        subsonicApi.search(
          query,
          mode,
          pageSize,
          (state.value.albums.length + state.value.artists.length + state.value.tracks.length)
        ).then(
          result => {
            const numResults = result.albums.length + result.artists.length + result.tracks.length;

            state.value.artists.push(...result.artists)
            state.value.albums.push(...result.albums)
            state.value.tracks.push(...result.tracks)
            state.value.hasMore = (
              (numResults >= pageSize)
              ? true
              : false
            )
          }
        )
      } finally {
        mainStore.isLoading = false
      }
    }

  watch(
    () => [ query, mode ],
    () => {
      state.value = {
        artists: [],
        albums: [],
        tracks: [],
        hasMore: true,
      } as State;
      loadMore()
    }
  )

  return vine`
    <template v-if="!!state.artists.length">
      <router-link v-if="!mode" :to="{ params: { mode: 'artist' }, query: $route.query }" class="section-title">
        <Icon icon="artists" class="title-color" />
        Artists <small>({{ state.artists.length }})</small>
      </router-link>
      <ArtistList :items="state.artists" />
    </template>

    <template v-if="!!state.albums.length">
      <router-link v-if="!mode" :to="{ params: { mode: 'album' }, query: $route.query }" class="section-title">
        <Icon icon="albums" />
        Albums <small>({{ state.albums.length }})</small>
      </router-link>
      <AlbumList :items="state.albums" />
    </template>

    <template v-if="!!state.tracks.length">
      <router-link :to="{ params: { mode: 'track' }, query: $route.query }" class="section-title">
        <Icon icon="tracks" class="title-color" />
        Tracks <small>({{ state.tracks.length }}{{ state.hasMore ? "+" : "" }})</small>
      </router-link>
      <TrackList :tracks="state.tracks" />
    </template>

    <EmptyIndicator v-if="!mainStore.isLoading && !state.hasMore && !state.artists.length && !state.albums.length && !state.tracks.length" label="No results" />
    <InfiniteLoader :is-loading="mainStore.isLoading" :has-more="state.hasMore" @load-more="loadMore" />
  `;
}