Skip to content

Commit 0154260

Browse files
committed
fix(store): correctly clear reactive proxy when clearing states
1 parent 39ec0a8 commit 0154260

File tree

10 files changed

+86
-38
lines changed

10 files changed

+86
-38
lines changed

src/components/views/progress/ProgressComponent.vue

+6-4
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 { onActivated, onMounted, toRefs, Transition, watch } from 'vue';
3+
import { onMounted, toRefs, 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';
@@ -11,6 +11,7 @@ import { usePanelItem } from '~/components/views/panel/use-panel-item';
1111
import { ExternaLinks } from '~/settings/external.links';
1212
import { useProgressStore, useProgressStoreRefs } from '~/stores/data/progress.store';
1313
import { useI18n } from '~/utils';
14+
import { watchUserChange } from '~/utils/store.utils';
1415
1516
const props = defineProps({
1617
panel: {
@@ -24,10 +25,11 @@ const { panel } = toRefs(props);
2425
const i18n = useI18n('progress');
2526
2627
const { progress, loading, loggedOut } = useProgressStoreRefs();
27-
const { fetchProgress } = useProgressStore();
28+
const { fetchProgress, clearState } = useProgressStore();
2829
29-
onActivated(async () => {
30-
await fetchProgress();
30+
watchUserChange({
31+
fetch: fetchProgress,
32+
clear: clearState,
3133
});
3234
3335
onMounted(() => {

src/components/views/settings/SettingsComponent.vue

+3-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ onDeactivated(() => {
9292
:key="section.title"
9393
class="card"
9494
:class="{ target: focus?.title === section.title }"
95-
:style="{ '--index': sections.length - index }"
95+
:style="{ '--length': sections.length, '--index': index }"
9696
:title="i18n(section.title)"
9797
@mouseenter="onEnter(section)"
9898
@mouseleave="onLeave(section)"
@@ -116,10 +116,11 @@ onDeactivated(() => {
116116
.card {
117117
@include mixin.hover-background($from: var(--bg-black-50), $to: var(--bg-color-80));
118118
119-
z-index: var(--index);
119+
z-index: var(--length);
120120
scroll-margin-top: calc(#{layout.$header-navbar-height} + 1rem);
121121
122122
&:not(:last-child) {
123+
z-index: calc(var(--length) - var(--index));
123124
margin-bottom: 1rem;
124125
}
125126

src/components/views/settings/SettingsLogs.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import { NSelect } from 'naive-ui';
44
import { ref } from 'vue';
55
66
import SettingsFormItem from '~/components/views/settings/SettingsFormItem.vue';
7-
import { LogLevel, useLogStore } from '~/stores/settings/log.store';
7+
import { LogLevel, useLogStoreRefs } from '~/stores/settings/log.store';
88
import { useI18n } from '~/utils';
99
1010
const i18n = useI18n('settings', 'logs');
1111
12-
const { logLevel } = useLogStore();
12+
const { logLevel } = useLogStoreRefs();
1313
1414
const options = Object.entries(LogLevel)
1515
.filter(([_, v]) => typeof v === 'number')

src/stores/data/list.store.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { useUserSettingsStoreRefs } from '~/stores/settings/user.store';
2222
import { useI18n } from '~/utils';
2323
import { storage } from '~/utils/browser/browser-storage.utils';
2424
import { debounceLoading, useBelowThreshold, useLoadingPlaceholder, useSearchFilter } from '~/utils/store.utils';
25+
import { clearProxy } from '~/utils/vue.utils';
2526

2627
export type AnyList =
2728
| TraktListItem
@@ -215,11 +216,11 @@ export const useListStore = defineStore('data.list', () => {
215216
pagination.value = undefined;
216217
searchList.value = '';
217218

218-
Object.assign(typeLoading, {});
219-
Object.assign(typeItemLoading, {});
219+
clearProxy(typeLoading);
220+
clearProxy(typeItemLoading);
220221

221-
Object.assign(listDictionary, {});
222-
Object.assign(listDictionaryLoading, {});
222+
clearProxy(listDictionary);
223+
clearProxy(listDictionaryLoading);
223224
};
224225

225226
const updateDictionary = (list: ListEntity, item: MinimalItem, remove?: boolean) => {

src/stores/data/movie.store.ts

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { defineStore, storeToRefs } from 'pinia';
22

3-
import { computed, reactive, ref } from 'vue';
3+
import { computed, reactive, ref, watch } from 'vue';
44

55
import type { TraktMovieExtended } from '~/models/trakt/trakt-movie.model';
66

77
import { NotificationService } from '~/services/notification.service';
88
import { TraktService } from '~/services/trakt.service';
99
import { logger } from '~/stores/settings/log.store';
10+
import { useUserSettingsStoreRefs } from '~/stores/settings/user.store';
11+
import { clearProxy } from '~/utils/vue.utils';
1012

1113
type MovieDictionary = Record<string, TraktMovieExtended>;
1214
type MovieWatchedDictionary = Record<string, boolean>;
@@ -23,16 +25,20 @@ export const useMovieStore = defineStore('data.movie', () => {
2325
const loadingWatched = ref(false);
2426
const loadingCollected = ref(false);
2527

26-
const clearState = () => {
27-
Object.assign(movies, {});
28-
Object.assign(moviesWatched, {});
29-
Object.assign(moviesCollected, {});
28+
const clearProgressState = () => {
29+
clearProxy(moviesWatched);
30+
clearProxy(moviesCollected);
3031

31-
Object.assign(loading, {});
3232
loadingWatched.value = false;
3333
loadingCollected.value = false;
3434
};
3535

36+
const clearState = () => {
37+
clearProxy(movies);
38+
clearProxy(loading);
39+
clearProgressState();
40+
};
41+
3642
const fetchMovie = async (id: string | number) => {
3743
if (loading[id]) {
3844
logger.warn('Already fetching movie', id);
@@ -117,8 +123,17 @@ export const useMovieStore = defineStore('data.movie', () => {
117123
moviesCollected[id.toString()] = !remove;
118124
};
119125

126+
const { user } = useUserSettingsStoreRefs();
127+
const initMovieStore = () => {
128+
watch(user, () => {
129+
clearProgressState();
130+
});
131+
};
132+
120133
return {
134+
initMovieStore,
121135
clearState,
136+
clearProgressState,
122137
fetchMovie,
123138
getMovie,
124139
getMovieLoading,

src/stores/data/person.store.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { TraktPersonExtended } from '~/models/trakt/trakt-people.model';
77
import { NotificationService } from '~/services/notification.service';
88
import { TraktService } from '~/services/trakt.service';
99
import { logger } from '~/stores/settings/log.store';
10-
import { asyncRefGetter } from '~/utils/vue.utils';
10+
import { asyncRefGetter, clearProxy } from '~/utils/vue.utils';
1111

1212
type PersonDictionary = Record<string, TraktPersonExtended>;
1313
type LoadingDictionary = Record<string, boolean>;
@@ -17,8 +17,8 @@ export const usePersonStore = defineStore('data.person', () => {
1717
const loading = reactive<LoadingDictionary>({});
1818

1919
const clearState = () => {
20-
Object.assign(people, {});
21-
Object.assign(loading, {});
20+
clearProxy(people);
21+
clearProxy(loading);
2222
};
2323

2424
const fetchPerson = async (id: string | number) => {

src/stores/data/show.store.ts

+31-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defineStore, storeToRefs } from 'pinia';
22

3-
import { computed, reactive } from 'vue';
3+
import { computed, reactive, watch } from 'vue';
44

55
import type { TraktEpisodeExtended, TraktEpisodeShort } from '~/models/trakt/trakt-episode.model';
66
import type { TraktCollectionProgress, TraktWatchedProgress } from '~/models/trakt/trakt-progress.model';
@@ -13,6 +13,8 @@ import { type ShowProgress, ShowProgressType } from '~/models/list-scroll.model'
1313
import { NotificationService } from '~/services/notification.service';
1414
import { TraktService } from '~/services/trakt.service';
1515
import { logger } from '~/stores/settings/log.store';
16+
import { useUserSettingsStoreRefs } from '~/stores/settings/user.store';
17+
import { clearProxy } from '~/utils/vue.utils';
1618

1719
export type ShowSeasons = Record<number, TraktSeasonExtended>;
1820

@@ -76,20 +78,25 @@ export const useShowStore = defineStore('data.show', () => {
7678
const showWatchedProgressLoading = reactive<LoadingDictionary>({});
7779
const showCollectionProgressLoading = reactive<LoadingDictionary>({});
7880

81+
const clearProgressState = () => {
82+
clearProxy(showsWatchedProgress);
83+
clearProxy(showsCollectionProgress);
84+
85+
clearProxy(showWatchedProgressLoading);
86+
clearProxy(showCollectionProgressLoading);
87+
};
88+
7989
const clearState = () => {
80-
Object.assign(shows, {});
81-
Object.assign(showsSeasons, {});
82-
Object.assign(showsSeasonEpisodes, {});
83-
Object.assign(showsEpisodes, {});
84-
Object.assign(showsWatchedProgress, {});
85-
Object.assign(showsCollectionProgress, {});
86-
87-
Object.assign(showsLoading, {});
88-
Object.assign(showsSeasonsLoading, {});
89-
Object.assign(showsSeasonEpisodesLoading, {});
90-
Object.assign(showsEpisodesLoading, {});
91-
Object.assign(showWatchedProgressLoading, {});
92-
Object.assign(showCollectionProgressLoading, {});
90+
clearProxy(shows);
91+
clearProxy(showsSeasons);
92+
clearProxy(showsSeasonEpisodes);
93+
clearProxy(showsEpisodes);
94+
95+
clearProxy(showsLoading);
96+
clearProxy(showsSeasonsLoading);
97+
clearProxy(showsSeasonEpisodesLoading);
98+
clearProxy(showsEpisodesLoading);
99+
clearProgressState();
93100
};
94101

95102
const fetchShow = async (id: string) => {
@@ -273,8 +280,18 @@ export const useShowStore = defineStore('data.show', () => {
273280
});
274281
};
275282

283+
const { user } = useUserSettingsStoreRefs();
284+
const initShowStore = () => {
285+
watch(user, () => {
286+
clearProgressState();
287+
console.info('user change, clearing state', user.value, showsWatchedProgress);
288+
});
289+
};
290+
276291
return {
292+
initShowStore,
277293
clearState,
294+
clearProgressState,
278295
getShow,
279296
fetchShow,
280297
fetchShowProgress,

src/stores/settings/links.store.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { logger } from '~/stores/settings/log.store';
77
import { storage } from '~/utils/browser/browser-storage.utils';
88
import { createTab } from '~/utils/browser/browser.utils';
99
import { debounce } from '~/utils/debounce.utils';
10+
import { clearProxy } from '~/utils/vue.utils';
1011

1112
export const CustomLinkScope = {
1213
Movie: 'movie' as const,
@@ -68,9 +69,9 @@ export const useLinksStore = defineStore('settings.links', () => {
6869
const linkScopeDictionary = reactive<CustomLinkScopeDictionary>({});
6970

7071
const clearState = () => {
71-
Object.assign(aliasDictionary, {});
72-
Object.assign(linkDictionary, {});
73-
Object.assign(linkScopeDictionary, {});
72+
clearProxy(aliasDictionary);
73+
clearProxy(linkDictionary);
74+
clearProxy(linkScopeDictionary);
7475
};
7576

7677
const saveState = debounce(() => storage.sync.set('settings.links', { enabled: enabled.value, backgroundLink: backgroundLink.value }), 1000);

src/utils/vue.utils.ts

+7
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ export const asyncRefGetter = <T>(fn: () => Promise<T>, loading: Ref<boolean>, r
2727
},
2828
};
2929
};
30+
31+
export const clearProxy = (proxy: Record<string, unknown>) => {
32+
// Reassign the proxy object to a new empty object
33+
Object.keys(proxy).forEach(key => {
34+
delete proxy[key];
35+
});
36+
};

src/web/init-services.ts

+4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { useActivityStore } from '~/stores/data/activity.store';
44
import { useHistoryStore } from '~/stores/data/history.store';
55
import { useImageStore } from '~/stores/data/image.store';
66
import { useListsStore, useListStore } from '~/stores/data/list.store';
7+
import { useMovieStore } from '~/stores/data/movie.store';
78
import { useSearchStore } from '~/stores/data/search.store';
9+
import { useShowStore } from '~/stores/data/show.store';
810
import { useAuthSettingsStore } from '~/stores/settings/auth.store';
911
import { useExtensionSettingsStore } from '~/stores/settings/extension.store';
1012
import { useLinksStore } from '~/stores/settings/links.store';
@@ -44,6 +46,8 @@ export const initServices = async () => {
4446
useListStore().initListStore(),
4547
useHistoryStore().initHistoryStore(),
4648
useSearchStore().initSearchStore(),
49+
useShowStore().initShowStore(),
50+
useMovieStore().initMovieStore(),
4751
]);
4852

4953
setAppReady(true);

0 commit comments

Comments
 (0)