Skip to content

Commit c6e5c01

Browse files
committed
feat(panel): move panel state to app store & support dirty state
1 parent 5fab4b1 commit c6e5c01

12 files changed

+94
-99
lines changed

src/components/AppComponent.vue

+24-9
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ import NavbarComponent from '~/components/common/navbar/NavbarComponent.vue';
1717
import IconChevronLeft from '~/components/icons/IconChevronLeft.vue';
1818
import IconClose from '~/components/icons/IconClose.vue';
1919
import CheckinComponent from '~/components/views/checkin/CheckinComponent.vue';
20+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
2021
import { useAuthSettingsStoreRefs } from '~/stores/settings/auth.store';
2122
2223
const { isAuthenticated } = useAuthSettingsStoreRefs();
2324
const { currentRoute, push, back } = useRouter();
2425
25-
const panel = ref(false);
26+
const { footerOpen, panelOpen, panelDirty } = useAppStateStoreRefs();
27+
2628
const base = ref();
27-
const footer = ref(false);
2829
2930
const appRef = ref();
3031
const mainRef = ref();
@@ -33,20 +34,25 @@ const footerRef = ref();
3334
watch(
3435
currentRoute,
3536
(_next, _prev) => {
36-
panel.value = !!_next.meta?.panel;
37+
panelOpen.value = !!_next.meta?.panel;
3738
base.value = _next.meta?.base;
3839
},
3940
{
4041
immediate: true,
4142
},
4243
);
44+
4345
const onAfterLeave = () => {
4446
if (!base.value) return;
4547
push({ name: base.value });
4648
};
4749
50+
const onAfterEnter = () => {
51+
panelDirty.value = false;
52+
};
53+
4854
const onClose = () => {
49-
panel.value = false;
55+
panelOpen.value = false;
5056
};
5157
5258
const onBack = () => {
@@ -58,9 +64,9 @@ const onBack = () => {
5864
<template>
5965
<div ref="appRef">
6066
<NDialogProvider :to="appRef">
61-
<header :class="{ open: panel }">
67+
<header :class="{ open: panelOpen }">
6268
<RouterView v-slot="{ Component }" name="navbar">
63-
<NavbarComponent v-if="isAuthenticated" :disabled="panel">
69+
<NavbarComponent v-if="isAuthenticated" :disabled="panelOpen">
6470
<template v-if="Component" #drawer="{ parentElement }">
6571
<Transition name="scale" mode="out-in">
6672
<KeepAlive>
@@ -76,20 +82,25 @@ const onBack = () => {
7682
<GridBackground v-if="!Component" :size="20" />
7783
<Transition name="scale" mode="out-in">
7884
<KeepAlive>
79-
<component :is="Component ?? PageLoading" :panel="panel" :footer="footer" />
85+
<component
86+
:is="Component ?? PageLoading"
87+
:panel="panelOpen"
88+
:footer="footerOpen"
89+
/>
8090
</KeepAlive>
8191
</Transition>
8292
</main>
8393
<aside>
8494
<RouterView v-slot="{ Component: PanelComponent }">
8595
<NDrawer
86-
v-model:show="panel"
96+
v-model:show="panelOpen"
8797
:to="mainRef"
8898
width="100%"
8999
class="panel"
90100
close-on-esc
91101
auto-focus
92102
:on-after-leave="onAfterLeave"
103+
:on-after-enter="onAfterEnter"
93104
>
94105
<NDrawerContent :native-scrollbar="false">
95106
<!-- Header -->
@@ -118,7 +129,11 @@ const onBack = () => {
118129
</NDrawer>
119130
</RouterView>
120131
</aside>
121-
<footer ref="footerRef" @mouseenter="footer = true" @mouseleave="footer = false">
132+
<footer
133+
ref="footerRef"
134+
@mouseenter="footerOpen = true"
135+
@mouseleave="footerOpen = false"
136+
>
122137
<CheckinComponent :parent-element="footerRef" />
123138
</footer>
124139
<DebugProvider />

src/components/common/list/use-list-scroll.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export const useListScroll = <T extends ListScrollSourceItemWithDate<D>, D exten
212212
};
213213

214214
if (_item.type === 'episode' || _item.type === 'season') {
215-
_item.meta.number = {
215+
_item.meta!.number = {
216216
season: item.episode?.season ?? item.season?.number,
217217
episode: item.episode?.number,
218218
};

src/components/views/calendar/CalendarComponent.vue

+4-8
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,16 @@ import ListScroll from '~/components/common/list/ListScroll.vue';
66
import { useListScroll } from '~/components/common/list/use-list-scroll';
77
88
import { usePanelItem } from '~/components/views/panel/use-panel-item';
9+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
910
import { useCalendarStore, useCalendarStoreRefs } from '~/stores/data/calendar.store';
1011
import { useCalendar, useCenterButton } from '~/utils/calendar.utils';
1112
import { useI18n } from '~/utils/i18n.utils';
1213
import { watchUserChange } from '~/utils/store.utils';
1314
14-
defineProps({
15-
footer: {
16-
type: Boolean,
17-
required: false,
18-
},
19-
});
20-
2115
const i18n = useI18n('calendar');
2216
17+
const { footerOpen } = useAppStateStoreRefs();
18+
2319
const { loading, center, filteredCalendar } = useCalendarStoreRefs();
2420
const { fetchCalendar, clearState } = useCalendarStore();
2521
@@ -71,7 +67,7 @@ const { onItemClick } = usePanelItem();
7167
</template>
7268
</ListScroll>
7369
<FloatingButton
74-
:show="!footer && scrolledOut"
70+
:show="!footerOpen && scrolledOut"
7571
:width="centerIsToday ? '2.5rem' : '3.5rem'"
7672
:icon="recenterIcon"
7773
@on-click="onClick"

src/components/views/history/HistoryComponent.vue

+6-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts" setup>
2-
import { onMounted, toRefs, watch } from 'vue';
2+
import { onMounted, watch } from 'vue';
33
44
import FloatingButton from '~/components/common/buttons/FloatingButton.vue';
55
import { useBackToTop } from '~/components/common/buttons/use-back-to-top';
@@ -10,22 +10,12 @@ import {
1010
useListScrollEvents,
1111
} from '~/components/common/list/use-list-scroll';
1212
import { usePanelItem } from '~/components/views/panel/use-panel-item';
13+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
1314
import { useHistoryStore, useHistoryStoreRefs } from '~/stores/data/history.store';
1415
import { useI18n } from '~/utils/i18n.utils';
1516
import { watchUserChange } from '~/utils/store.utils';
1617
17-
const props = defineProps({
18-
panel: {
19-
type: Boolean,
20-
required: false,
21-
},
22-
footer: {
23-
type: Boolean,
24-
required: false,
25-
},
26-
});
27-
28-
const { panel } = toRefs(props);
18+
const { footerOpen, panelOpen, panelDirty } = useAppStateStoreRefs();
2919
3020
const { filteredHistory, pagination, loading, pageSize, belowThreshold, searchHistory } =
3121
useHistoryStoreRefs();
@@ -39,8 +29,8 @@ watchUserChange({
3929
});
4030
4131
onMounted(() => {
42-
watch(panel, async value => {
43-
if (!value) await fetchHistory();
32+
watch(panelOpen, async value => {
33+
if (!value && panelDirty.value) await fetchHistory();
4434
});
4535
});
4636
@@ -79,7 +69,7 @@ const { onItemClick } = usePanelItem();
7969
<!-- TODO buttons here-->
8070
</template>
8171
</ListScroll>
82-
<FloatingButton :show="!footer && scrolled" @on-click="onClick">
72+
<FloatingButton :show="!footerOpen && scrolled" @on-click="onClick">
8373
{{ i18n('back_to_top', 'common', 'button') }}
8474
</FloatingButton>
8575
</div>

src/components/views/panel/MoviePanel.vue

+9-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from '~/components/views/panel/use-panel-buttons';
1616
import { NotificationService } from '~/services/notification.service';
1717
import { ResolveExternalLinks } from '~/settings/external.links';
18+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
1819
import {
1920
DefaultListId,
2021
DefaultLists,
@@ -147,6 +148,8 @@ const onListUpdate = async (value: ListEntity['id'], remove: boolean) => {
147148
148149
const releaseDate = computed(() => movie.value?.released);
149150
151+
const { panelDirty } = useAppStateStoreRefs();
152+
150153
const onCollectionUpdate = async (
151154
value: PanelButtonsOptions,
152155
date?: string | number | Date,
@@ -156,6 +159,7 @@ const onCollectionUpdate = async (
156159
date = releaseDate.value;
157160
}
158161
162+
panelDirty.value = true;
159163
await addToOrRemoveFromList({
160164
list: DefaultLists.ShowCollection,
161165
itemType: 'movie',
@@ -178,6 +182,7 @@ const onWatchedUpdate = async (
178182
date = releaseDate.value;
179183
}
180184
185+
panelDirty.value = true;
181186
await addToOrRemoveFromList({
182187
list: {
183188
id: DefaultListId.History,
@@ -232,7 +237,10 @@ const onCheckin = async (cancel: boolean) => {
232237
i18n('checkin_failed', 'watching'),
233238
new Error('No movie id'),
234239
);
235-
} else await checkin({ movie: { ids: movie.value.ids } });
240+
} else {
241+
panelDirty.value = true;
242+
await checkin({ movie: { ids: movie.value.ids } });
243+
}
236244
237245
await fetchMovieWatched(true);
238246
};

src/components/views/panel/ShowPanel.vue

+22-10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from '~/components/views/panel/use-panel-buttons';
1717
import { NotificationService } from '~/services/notification.service';
1818
import { ResolveExternalLinks } from '~/settings/external.links';
19+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
1920
import {
2021
DefaultListId,
2122
DefaultLists,
@@ -249,11 +250,14 @@ const titleUrl = computed(() => {
249250
250251
const releaseDate = computed(() => activeItem.value?.first_aired);
251252
253+
const { panelDirty } = useAppStateStoreRefs();
254+
252255
const onListUpdate = async (value: ListEntity['id'], remove: boolean) => {
253256
if (!panelType.value || !activeItem.value?.ids) return;
254257
const _list = myLists.value.find(list => list.id === value);
255258
if (!_list) return;
256259
260+
panelDirty.value = true;
257261
await addToOrRemoveFromList({
258262
list: _list,
259263
itemType: panelType.value,
@@ -271,15 +275,19 @@ const onCollectionUpdate = async (
271275
date = releaseDate.value;
272276
}
273277
274-
await addToOrRemoveFromList({
275-
list: DefaultLists.ShowCollection,
276-
itemType: panelType.value,
277-
itemIds: activeItem.value.ids,
278-
date,
279-
remove: value === PanelButtonsOption.Remove,
280-
});
281-
if (!showId.value) return;
282-
await fetchShowCollectionProgress(showId.value, { force: true });
278+
try {
279+
await addToOrRemoveFromList({
280+
list: DefaultLists.ShowCollection,
281+
itemType: panelType.value,
282+
itemIds: activeItem.value.ids,
283+
date,
284+
remove: value === PanelButtonsOption.Remove,
285+
});
286+
if (!showId.value) return;
287+
await fetchShowCollectionProgress(showId.value, { force: true });
288+
} finally {
289+
panelDirty.value = true;
290+
}
283291
};
284292
285293
const onWatchedUpdate = async (
@@ -291,6 +299,7 @@ const onWatchedUpdate = async (
291299
date = releaseDate.value;
292300
}
293301
302+
panelDirty.value = true;
294303
await addToOrRemoveFromList({
295304
list: {
296305
id: DefaultListId.History,
@@ -328,7 +337,10 @@ const onCheckin = async (cancel: boolean) => {
328337
i18n('checkin_failed', 'watching'),
329338
new Error('No episode id'),
330339
);
331-
} else await checkin({ episode: { ids: episode.value.ids } });
340+
} else {
341+
panelDirty.value = true;
342+
await checkin({ episode: { ids: episode.value.ids } });
343+
}
332344
333345
if (!showId.value) return;
334346
await fetchShowProgress(showId.value, { force: true });

src/components/views/progress/ProgressComponent.vue

+7-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts" setup>
22
import { NFlex } from 'naive-ui';
3-
import { onMounted, toRefs, Transition, watch } from 'vue';
3+
import { onMounted, Transition, watch } from 'vue';
44
55
import FloatingButton from '~/components/common/buttons/FloatingButton.vue';
66
import { useBackToTop } from '~/components/common/buttons/use-back-to-top';
@@ -9,25 +9,15 @@ import ListScroll from '~/components/common/list/ListScroll.vue';
99
import LoginCard from '~/components/views/login/LoginCard.vue';
1010
import { usePanelItem } from '~/components/views/panel/use-panel-item';
1111
import { ExternaLinks } from '~/settings/external.links';
12+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
1213
import { useProgressStore, useProgressStoreRefs } from '~/stores/data/progress.store';
1314
import { useI18n } from '~/utils/i18n.utils';
1415
import { watchUserChange } from '~/utils/store.utils';
1516
16-
const props = defineProps({
17-
panel: {
18-
type: Boolean,
19-
required: false,
20-
},
21-
footer: {
22-
type: Boolean,
23-
required: false,
24-
},
25-
});
26-
27-
const { panel } = toRefs(props);
28-
2917
const i18n = useI18n('progress');
3018
19+
const { footerOpen, panelOpen, panelDirty } = useAppStateStoreRefs();
20+
3121
const { progress, loading, loggedOut } = useProgressStoreRefs();
3222
const { fetchProgress, clearState } = useProgressStore();
3323
@@ -37,8 +27,8 @@ watchUserChange({
3727
});
3828
3929
onMounted(() => {
40-
watch(panel, async value => {
41-
if (!value) await fetchProgress();
30+
watch(panelOpen, async value => {
31+
if (!value && panelDirty.value) await fetchProgress();
4232
});
4333
});
4434
@@ -79,7 +69,7 @@ const { onItemClick } = usePanelItem();
7969
</ListScroll>
8070
</Transition>
8171

82-
<FloatingButton :show="!footer && scrolled" @on-click="onClick">
72+
<FloatingButton :show="!footerOpen && scrolled" @on-click="onClick">
8373
{{ i18n('back_to_top', 'common', 'button') }}
8474
</FloatingButton>
8575
</div>

src/components/views/releases/ReleasesComponent.vue

+4-8
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,16 @@ import { useListScroll } from '~/components/common/list/use-list-scroll';
1010
1111
import { usePanelItem } from '~/components/views/panel/use-panel-item';
1212
import { TraktService } from '~/services/trakt.service';
13+
import { useAppStateStoreRefs } from '~/stores/app-state.store';
1314
import { useReleasesStore, useReleasesStoreRefs } from '~/stores/data/releases.store';
1415
import { useCalendar, useCenterButton } from '~/utils/calendar.utils';
1516
import { useI18n } from '~/utils/i18n.utils';
1617
import { watchUserChange } from '~/utils/store.utils';
1718
18-
defineProps({
19-
footer: {
20-
type: Boolean,
21-
required: false,
22-
},
23-
});
24-
2519
const i18n = useI18n('releases');
2620
21+
const { footerOpen } = useAppStateStoreRefs();
22+
2723
const { releases, loading, center } = useReleasesStoreRefs();
2824
const { fetchReleases, clearState } = useReleasesStore();
2925
@@ -86,7 +82,7 @@ const onMovieClick = async ({ item }: { item: ListScrollItem }) => {
8682
</template>
8783
</ListScroll>
8884
<FloatingButton
89-
:show="!footer && scrolledOut"
85+
:show="!footerOpen && scrolledOut"
9086
:width="centerIsToday ? '2.5rem' : '3.5rem'"
9187
:icon="recenterIcon"
9288
@on-click="onClick"

0 commit comments

Comments
 (0)