Skip to content

Commit 0157df6

Browse files
committed
feat(panel): implement list & collection updates
1 parent 553ade2 commit 0157df6

13 files changed

+510
-127
lines changed

src/components/views/panel/MoviePanel.vue

+76-9
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ import MoviePanelDetails from '~/components/views/panel/MoviePanelDetails.vue';
88
import MoviePanelOverview from '~/components/views/panel/MoviePanelOverview.vue';
99
import PanelPoster from '~/components/views/panel/PanelPoster.vue';
1010
11+
import {
12+
PanelButtonsOption,
13+
type PanelButtonsOptions,
14+
} from '~/components/views/panel/use-panel-buttons';
1115
import { ResolveExternalLinks } from '~/settings/external.links';
12-
import { useListsStoreRefs, useListStore } from '~/stores/data/list.store';
16+
import {
17+
DefaultLists,
18+
type ListEntity,
19+
ListType,
20+
useListsStoreRefs,
21+
useListStore,
22+
} from '~/stores/data/list.store';
1323
import { useMovieStore, useMovieStoreRefs } from '~/stores/data/movie.store';
1424
import { useExtensionSettingsStore } from '~/stores/settings/extension.store';
1525
import { useI18n } from '~/utils';
@@ -31,6 +41,8 @@ const {
3141
getMovieCollected,
3242
fetchMovieWatched,
3343
fetchMovieCollected,
44+
changeMovieWatched,
45+
changeMovieCollected,
3446
} = useMovieStore();
3547
3648
const { loadingCollected, loadingWatched } = useMovieStoreRefs();
@@ -63,20 +75,72 @@ onMounted(() => {
6375
});
6476
6577
const { lists } = useListsStoreRefs();
66-
const { isListLoading, isItemInList } = useListStore();
67-
68-
const listLoading = computed(() => {
69-
if (!movieId?.value) return;
70-
return isListLoading(movieId.value).value;
78+
const { isListTypeLoading, isItemInList, isItemListLoading, addToOrRemoveFromList } =
79+
useListStore();
80+
81+
const listLoading = computed(
82+
() =>
83+
isListTypeLoading(ListType.Watchlist).value || isListTypeLoading(ListType.List).value,
84+
);
85+
86+
const collectionLoading = computed(() => {
87+
if (loadingCollected.value) return true;
88+
if (movieId.value === undefined) return true;
89+
return isItemListLoading({
90+
listType: ListType.Collection,
91+
itemType: 'movie',
92+
itemId: movieId.value,
93+
}).value;
7194
});
7295
7396
const activeLists = computed(() => {
74-
if (!movieId?.value) return;
97+
if (movieId?.value === undefined) return;
7598
return lists.value
76-
?.filter(list => isItemInList(list.id, movieId.value).value)
99+
?.filter(list => isItemInList(list.id, 'movie', movieId.value).value)
77100
.map(list => list.id);
78101
});
79102
103+
const onListUpdate = async (value: ListEntity['id'], remove: boolean) => {
104+
if (!movie.value?.ids) return;
105+
106+
const _list = lists.value.find(list => list.id === value);
107+
if (!_list) return;
108+
109+
await addToOrRemoveFromList({
110+
list: _list,
111+
itemType: 'movie',
112+
itemIds: movie.value?.ids,
113+
remove,
114+
});
115+
};
116+
117+
const onCollectionUpdate = async (value: PanelButtonsOptions, date?: number) => {
118+
if (!movie.value?.ids) return;
119+
120+
await addToOrRemoveFromList({
121+
list: DefaultLists.ShowCollection,
122+
itemType: 'movie',
123+
itemIds: movie.value?.ids,
124+
date,
125+
remove: value === PanelButtonsOption.Remove,
126+
});
127+
128+
const _id = movie.value?.ids?.trakt;
129+
if (_id === undefined) return;
130+
changeMovieCollected(_id, value === PanelButtonsOption.Remove);
131+
};
132+
133+
const onWatchedUpdate = async (value: PanelButtonsOptions, date?: number) => {
134+
if (!movie.value?.ids) return;
135+
136+
// TODO : implement add/remove from history
137+
// addToOrRemoveFromList(DefaultLists.Watchlist, `${panelType.value}s`, activeItem.value.ids);
138+
139+
const _id = movie.value?.ids?.trakt;
140+
if (_id === undefined) return;
141+
changeMovieWatched(_id, value === PanelButtonsOption.Remove);
142+
};
143+
80144
const i18n = useI18n('movie', 'panel');
81145
82146
const title = computed(() => {
@@ -117,9 +181,12 @@ const { openTab } = useExtensionSettingsStore();
117181
:watched="watched"
118182
:watched-loading="loadingWatched"
119183
:collected="collected"
120-
:collected-loading="loadingCollected"
184+
:collected-loading="collectionLoading"
121185
:active-loading="listLoading"
122186
:active-lists="activeLists"
187+
@on-list-update="onListUpdate"
188+
@on-collection-update="onCollectionUpdate"
189+
@on-watched-update="onWatchedUpdate"
123190
/>
124191

125192
<MoviePanelOverview :movie="movie" />

src/components/views/panel/MoviePanelButtons.vue

+39-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import IconListEmpty from '~/components/icons/IconListEmpty.vue';
99
import IconPlay from '~/components/icons/IconPlay.vue';
1010
import IconPlayFilled from '~/components/icons/IconPlayFilled.vue';
1111
import PanelButtonProgress from '~/components/views/panel/PanelButtonProgress.vue';
12-
import { usePanelButtons } from '~/components/views/panel/use-panel-buttons';
12+
import {
13+
PanelButtonsOption,
14+
type PanelButtonsOptions,
15+
usePanelButtons,
16+
} from '~/components/views/panel/use-panel-buttons';
1317
import {
1418
type ListEntity,
1519
ListType,
@@ -45,7 +49,33 @@ const props = defineProps({
4549
},
4650
});
4751
48-
const { watched, collected, activeLoading } = toRefs(props);
52+
const emit = defineEmits<{
53+
(e: 'onListUpdate', value: ListEntity['id'], remove: boolean): void;
54+
(e: 'onCollectionUpdate', value: PanelButtonsOptions, date?: number): void;
55+
(e: 'onWatchedUpdate', value: PanelButtonsOptions, date?: number): void;
56+
}>();
57+
58+
const { watched, collected, activeLoading, activeLists } = toRefs(props);
59+
60+
const onListUpdate = (value: ListEntity['id'] | ListEntity['id'][]) => {
61+
const newList = Array.isArray(value) ? value : [value];
62+
const removed = activeLists?.value?.find(id => !newList.includes(id));
63+
if (removed) emit('onListUpdate', removed, true);
64+
const added = newList.find(id => !activeLists?.value?.includes(id));
65+
if (added) emit('onListUpdate', added, false);
66+
};
67+
68+
const onCollectionUpdate = (value: unknown, date?: number) => {
69+
if (value === PanelButtonsOption.Cancel) return;
70+
if (value === PanelButtonsOption.Now && date === undefined) date = Date.now();
71+
emit('onCollectionUpdate', value as PanelButtonsOptions, date);
72+
};
73+
74+
const onWatchedUpdate = (value: unknown, date?: number) => {
75+
if (value === PanelButtonsOption.Cancel) return;
76+
if (value === PanelButtonsOption.Now && date === undefined) date = Date.now();
77+
emit('onWatchedUpdate', value as PanelButtonsOptions, date);
78+
};
4979
5080
const i18n = useI18n('panel', 'buttons');
5181
@@ -63,11 +93,11 @@ const collectionOptions = computed(() => {
6393
return timeOptions;
6494
});
6595
66-
const { lists, loading } = useListsStoreRefs();
96+
const { lists, listsLoading } = useListsStoreRefs();
6797
const { fetchLists, getIcon } = useListsStore();
6898
69-
const listsLoading = computed(() => {
70-
return loading.value || activeLoading.value;
99+
const listLoading = computed(() => {
100+
return listsLoading.value || activeLoading.value;
71101
});
72102
73103
const listOptions = computed(() => {
@@ -105,8 +135,9 @@ onMounted(() => {
105135
}"
106136
:icon="activeLists?.length ? IconCheckedList : IconListEmpty"
107137
:filled="!!activeLists?.length"
108-
:disabled="listsLoading"
138+
:disabled="listLoading"
109139
type="warning"
140+
@on-select="onListUpdate"
110141
>
111142
<template #tooltip>
112143
<NFlex vertical size="small" align="center" justify="center">
@@ -128,6 +159,7 @@ onMounted(() => {
128159
:filled="collected"
129160
:disabled="collectedLoading"
130161
type="info"
162+
@on-select="onCollectionUpdate"
131163
>
132164
{{ i18n(`label__collection__${ collected ? 'remove' : 'add' }`) }}
133165
</PanelButtonProgress>
@@ -142,6 +174,7 @@ onMounted(() => {
142174
:icon="watched ? IconPlayFilled : IconPlay"
143175
:filled="watched"
144176
:disabled="watchedLoading"
177+
@on-select="onWatchedUpdate"
145178
>
146179
{{ i18n(`label__history__${ watched ? 'remove' : 'add' }`) }}
147180
</PanelButtonProgress>

src/components/views/panel/ShowPanel.vue

+88-17
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ import ShowPanelButtons from '~/components/views/panel/ShowPanelButtons.vue';
88
import ShowPanelDetails from '~/components/views/panel/ShowPanelDetails.vue';
99
import ShowPanelOverview from '~/components/views/panel/ShowPanelOverview.vue';
1010
import ShowPanelPicker from '~/components/views/panel/ShowPanelPicker.vue';
11+
import {
12+
PanelButtonsOption,
13+
type PanelButtonsOptions,
14+
} from '~/components/views/panel/use-panel-buttons';
1115
import { ResolveExternalLinks } from '~/settings/external.links';
12-
import { useListsStoreRefs, useListStore } from '~/stores/data/list.store';
16+
import {
17+
DefaultLists,
18+
type ListEntity,
19+
ListType,
20+
useListsStoreRefs,
21+
useListStore,
22+
} from '~/stores/data/list.store';
1323
import { useShowStore } from '~/stores/data/show.store';
1424
import { useExtensionSettingsStore } from '~/stores/settings/extension.store';
1525
import { useI18n } from '~/utils';
@@ -35,6 +45,8 @@ const { showId, seasonNumber, episodeNumber } = toRefs(props);
3545
const {
3646
getShow,
3747
fetchShow,
48+
fetchShowProgress,
49+
fetchShowCollectionProgress,
3850
getShowSeasons,
3951
fetchShowSeasons,
4052
getShowSeasonEpisodes,
@@ -64,11 +76,6 @@ const collectionProgress = computed(() => {
6476
return getShowCollectionProgress(showId.value).value;
6577
});
6678
67-
const collectionLoading = computed(() => {
68-
if (!showId?.value) return;
69-
return getShowCollectionLoading(showId.value).value;
70-
});
71-
7279
const seasonNb = computed(() => {
7380
if (seasonNumber?.value === undefined) return;
7481
const _seasonNumber = Number(seasonNumber.value);
@@ -83,12 +90,6 @@ const episodeNb = computed(() => {
8390
return _episodeNumber;
8491
});
8592
86-
const panelType = computed<'show' | 'season' | 'episode'>(() => {
87-
if (episodeNb?.value !== undefined && seasonNb?.value !== undefined) return 'episode';
88-
if (seasonNb?.value !== undefined) return 'season';
89-
return 'show';
90-
});
91-
9293
const show = computed(() => {
9394
if (!showId?.value) return;
9495
return getShow(showId.value).value;
@@ -119,6 +120,18 @@ const season = computed(() => {
119120
return seasons.value?.[seasonNb.value];
120121
});
121122
123+
const panelType = computed<'show' | 'season' | 'episode'>(() => {
124+
if (episodeNb?.value !== undefined && seasonNb?.value !== undefined) return 'episode';
125+
if (seasonNb?.value !== undefined) return 'season';
126+
return 'show';
127+
});
128+
129+
const activeItem = computed(() => {
130+
if (panelType.value === 'episode') return episode.value;
131+
if (panelType.value === 'season') return season.value;
132+
return show.value;
133+
});
134+
122135
const watchedProgressEntity = computed(() => {
123136
if (!watchedProgress?.value) return;
124137
@@ -156,17 +169,36 @@ const collectionProgressEntity = computed(() => {
156169
});
157170
158171
const { lists } = useListsStoreRefs();
159-
const { isListLoading, isItemInList } = useListStore();
172+
const { isListTypeLoading, isItemInList, addToOrRemoveFromList, isItemListLoading } =
173+
useListStore();
174+
175+
const listLoading = computed(
176+
() =>
177+
isListTypeLoading(ListType.Watchlist).value || isListTypeLoading(ListType.List).value,
178+
);
179+
180+
const activeItemCollectionLoading = computed(() => {
181+
const _id = activeItem.value?.ids?.trakt;
182+
if (_id === undefined) return;
183+
return isItemListLoading({
184+
listType: ListType.Collection,
185+
itemType: panelType.value,
186+
itemId: _id,
187+
}).value;
188+
});
160189
161-
const listLoading = computed(() => {
190+
const collectionLoading = computed(() => {
162191
if (!showId?.value) return;
163-
return isListLoading(showId.value).value;
192+
if (activeItemCollectionLoading.value) return true;
193+
return getShowCollectionLoading(showId.value).value;
164194
});
165195
166196
const activeLists = computed(() => {
167-
if (!showId?.value) return;
197+
const _id = activeItem?.value?.ids?.trakt;
198+
const _type = panelType.value;
199+
if (_id === undefined || !_type) return;
168200
return lists.value
169-
?.filter(list => isItemInList(list.id, showId.value).value)
201+
?.filter(list => isItemInList(list.id, _type, _id).value)
170202
.map(list => list.id);
171203
});
172204
@@ -184,6 +216,42 @@ const titleUrl = computed(() => {
184216
});
185217
});
186218
219+
const onListUpdate = async (value: ListEntity['id'], remove: boolean) => {
220+
if (!panelType.value || !activeItem.value?.ids) return;
221+
const _list = lists.value.find(list => list.id === value);
222+
if (!_list) return;
223+
224+
await addToOrRemoveFromList({
225+
list: _list,
226+
itemType: panelType.value,
227+
itemIds: activeItem.value.ids,
228+
remove,
229+
});
230+
};
231+
232+
const onCollectionUpdate = async (value: PanelButtonsOptions, date?: number) => {
233+
if (!panelType.value || !activeItem.value?.ids) return;
234+
235+
await addToOrRemoveFromList({
236+
list: DefaultLists.ShowCollection,
237+
itemType: panelType.value,
238+
itemIds: activeItem.value.ids,
239+
date,
240+
remove: value === PanelButtonsOption.Remove,
241+
});
242+
if (!showId.value) return;
243+
await fetchShowCollectionProgress(showId.value, { force: true });
244+
};
245+
246+
const onWatchedUpdate = async (value: PanelButtonsOptions, date?: number) => {
247+
if (!panelType.value || !activeItem.value?.ids) return;
248+
249+
// TODO : implement add/remove from history
250+
// addToOrRemoveFromList(DefaultLists.Watchlist, `${panelType.value}s`, activeItem.value.ids);
251+
if (!showId.value) return;
252+
await fetchShowProgress(showId.value, { force: true });
253+
};
254+
187255
onMounted(() => {
188256
watch(
189257
[showId, seasonNb, episodeNb],
@@ -244,6 +312,9 @@ const { openTab } = useExtensionSettingsStore();
244312
:collection-loading="collectionLoading"
245313
:active-loading="listLoading"
246314
:active-lists="activeLists"
315+
@on-list-update="onListUpdate"
316+
@on-collection-update="onCollectionUpdate"
317+
@on-watched-update="onWatchedUpdate"
247318
/>
248319

249320
<ShowPanelPicker

0 commit comments

Comments
 (0)