Skip to content

Commit df26938

Browse files
committed
fix(pagination): creates constant and fix settings page sizes
1 parent 09363cc commit df26938

File tree

10 files changed

+125
-29
lines changed

10 files changed

+125
-29
lines changed

src/components/views/settings/SettingsExport.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import IconDownload from '~/components/icons/IconDownload.vue';
1313
import IconLoadingDots from '~/components/icons/IconLoadingDots.vue';
1414
import SettingsFormItem from '~/components/views/settings/SettingsFormItem.vue';
1515
16+
import { PageSize } from '~/models/page-size.model';
1617
import { Logger } from '~/services/logger.service';
1718
import { NotificationService } from '~/services/notification.service';
1819
import { TraktService } from '~/services/trakt.service';
@@ -113,7 +114,7 @@ const fetchData = (type: ListTypes, name: string, entity?: ListEntity) => {
113114
id: user.value,
114115
list_id: entity.id.toString(),
115116
extended: TraktApiExtended.Full,
116-
pagination: { limit: 1000 },
117+
pagination: { limit: PageSize.p1000 },
117118
},
118119
writer,
119120
});

src/components/views/settings/SettingsTabs.vue

+45-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { NIcon, NSelect, NSwitch, type SelectOption } from 'naive-ui';
55
import { type Component, computed, h, onBeforeMount, ref } from 'vue';
66
77
import SettingsFormItem from '~/components/views/settings/SettingsFormItem.vue';
8-
import { pageSizeOptions } from '~/models/page-size.model';
8+
import { pageSizeOptions, pageSizeOptionsWithZero } from '~/models/page-size.model';
99
import { ProgressType } from '~/models/progress-type.model';
1010
import { Route } from '~/models/router.model';
1111
import { useCalendarStoreRefs } from '~/stores/data/calendar.store';
@@ -17,6 +17,7 @@ import {
1717
useListsStoreRefs,
1818
useListStoreRefs,
1919
} from '~/stores/data/list.store';
20+
import { useRatingsStoreRefs } from '~/stores/data/ratings.store';
2021
import { useSearchStoreRefs } from '~/stores/data/search.store';
2122
import {
2223
useExtensionSettingsStore,
@@ -78,6 +79,13 @@ onBeforeMount(() => {
7879
const { pageSize: historyPageSize } = useHistoryStoreRefs();
7980
const { pageSize: listPageSize } = useListStoreRefs();
8081
const { pageSize: searchPageSize } = useSearchStoreRefs();
82+
const { pageSize: ratingPageSize } = useRatingsStoreRefs();
83+
84+
const pageSizeLoadListWarning = computed(() => {
85+
if (!loadLists.value.length) return i18n('label_load_lists_warning');
86+
if (!loadListsPageSize.value) return i18n('label_page_size_warning');
87+
return undefined;
88+
});
8189
8290
const tabsOptions = computed(() =>
8391
enabledTabs.value.map(([route, state]) => ({
@@ -146,17 +154,6 @@ const container = ref();
146154
</NSwitch>
147155
</SettingsFormItem>
148156

149-
<!-- Enable Ratings -->
150-
<SettingsFormItem
151-
:label="i18n('label_enable_ratings')"
152-
:warning="enableRatings ? i18n('label_enable_ratings_warning') : undefined"
153-
>
154-
<NSwitch v-model:value="enableRatings" class="form-switch">
155-
<template #checked>{{ i18n('on', 'common', 'button') }}</template>
156-
<template #unchecked>{{ i18n('off', 'common', 'button') }}</template>
157-
</NSwitch>
158-
</SettingsFormItem>
159-
160157
<!-- Enable tabs -->
161158
<template v-for="[route, state] of enabledTabs" :key="route">
162159
<SettingsFormItem
@@ -224,17 +221,32 @@ const container = ref();
224221
</SettingsFormItem>
225222
</template>
226223

227-
<!-- Page Size -->
228-
<SettingsFormItem :label="i18n('label_load_lists_page_size')">
224+
<!-- Enable Ratings -->
225+
<SettingsFormItem
226+
:label="i18n('label_enable_ratings')"
227+
:warning="enableRatings ? i18n('label_enable_ratings_warning') : undefined"
228+
>
229+
<NSwitch v-model:value="enableRatings" class="form-switch">
230+
<template #checked>{{ i18n('on', 'common', 'button') }}</template>
231+
<template #unchecked>{{ i18n('off', 'common', 'button') }}</template>
232+
</NSwitch>
233+
</SettingsFormItem>
234+
235+
<!-- Rating Page Sizes -->
236+
<SettingsFormItem
237+
:label="i18n('label_ratings_page_size')"
238+
:warning="!ratingPageSize ? i18n('label_page_size_warning') : undefined"
239+
>
229240
<NSelect
230-
v-model:value="loadListsPageSize"
231-
:disabled="!loadLists.length"
241+
v-model:value="ratingPageSize"
242+
:disabled="!enableRatings"
232243
class="form-select"
233244
:to="container"
234-
:options="pageSizeOptions"
245+
:options="pageSizeOptionsWithZero"
235246
/>
236247
</SettingsFormItem>
237248

249+
<!-- History Page Sizes -->
238250
<SettingsFormItem :label="i18n('label_history_page_size')">
239251
<NSelect
240252
v-model:value="historyPageSize"
@@ -245,6 +257,7 @@ const container = ref();
245257
/>
246258
</SettingsFormItem>
247259

260+
<!-- List Page Sizes -->
248261
<SettingsFormItem :label="i18n('label_list_page_size')">
249262
<NSelect
250263
v-model:value="listPageSize"
@@ -255,6 +268,21 @@ const container = ref();
255268
/>
256269
</SettingsFormItem>
257270

271+
<!-- Load List Page Sizes -->
272+
<SettingsFormItem
273+
:label="i18n('label_load_lists_page_size')"
274+
:warning="pageSizeLoadListWarning"
275+
>
276+
<NSelect
277+
v-model:value="loadListsPageSize"
278+
:disabled="!loadLists.length"
279+
class="form-select"
280+
:to="container"
281+
:options="pageSizeOptionsWithZero"
282+
/>
283+
</SettingsFormItem>
284+
285+
<!-- Search page size -->
258286
<SettingsFormItem :label="i18n('label_search_page_size')">
259287
<NSelect
260288
v-model:value="searchPageSize"

src/i18n/en/settings/settings-tabs.json

+17-1
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,26 @@
5959
"message": "Lists to load when opening panels",
6060
"description": "Label for the 'Load lists' setting"
6161
},
62+
"settings__tabs__label_ratings_page_size": {
63+
"message": "Ratings page size",
64+
"description": "Label for the 'Page size for ratings' setting"
65+
},
6266
"settings__tabs__label_load_lists_page_size": {
63-
"message": "Page size for lists",
67+
"message": "Panel list page size",
6468
"description": "Label for the 'Page size for lists' setting"
6569
},
70+
"settings__tabs__label_load_lists_warning": {
71+
"message": "No lists found. Please create at least one list to use this feature.",
72+
"description": "Label for the 'No lists found' warning"
73+
},
74+
"settings__tabs__label_page_size_warning": {
75+
"message": "An unlimited page size may impact performance.",
76+
"description": "Label for the 'An unlimited page size' warning"
77+
},
78+
"settings__tabs__label_page_size_none": {
79+
"message": "None",
80+
"description": "Label for the 'None' page size"
81+
},
6682
"settings__tabs__label_progress_type": {
6783
"message": "Progress type",
6884
"description": "Label for the 'Progress type' setting"

src/models/page-size.model.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import type { SelectOption } from 'naive-ui';
22

3+
export const PageSize: Record<string, number> = {
4+
p0: 0,
5+
p50: 50,
6+
p100: 100,
7+
p200: 200,
8+
p500: 500,
9+
p1000: 1000,
10+
} as const;
11+
312
export const pageSizeOptions: SelectOption[] = [
413
{ label: '50', value: 50 },
514
{ label: '100', value: 100 },
615
{ label: '200', value: 200 },
716
{ label: '500', value: 500 },
817
{ label: '1000', value: 1000 },
9-
];
18+
] as const;
19+
20+
export const pageSizeOptionsWithZero: SelectOption[] = [{ label: '0', value: 0 }, ...pageSizeOptions] as const;

src/stores/data/history.store.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { computed, reactive, ref, watch } from 'vue';
44

55
import type { ErrorDictionary } from '~/utils/retry.utils';
66

7+
import { PageSize } from '~/models/page-size.model';
78
import { ErrorService } from '~/services/error.service';
89
import { Logger } from '~/services/logger.service';
910
import { NotificationService } from '~/services/notification.service';
@@ -26,7 +27,7 @@ type HistoryState = {
2627
export const useHistoryStore = defineStore(HistoryStoreConstants.Store, () => {
2728
const firstLoad = ref(true);
2829
const loading = ref(true);
29-
const pageSize = ref(100);
30+
const pageSize = ref(PageSize.p100);
3031
const history = ref<TraktHistory[]>([]);
3132
const pagination = ref<TraktClientPagination>();
3233
const extended = ref(false);

src/stores/data/list.store.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import IconGrid from '~/components/icons/IconGrid.vue';
2020
import IconHeart from '~/components/icons/IconHeart.vue';
2121
import IconList from '~/components/icons/IconList.vue';
2222
import { ListScrollItemType } from '~/models/list-scroll.model';
23+
import { PageSize } from '~/models/page-size.model';
2324
import { ErrorService } from '~/services/error.service';
2425
import { Logger } from '~/services/logger.service';
2526
import { NotificationService } from '~/services/notification.service';
@@ -230,7 +231,7 @@ const ListStoreConstants = {
230231
export const useListStore = defineStore(ListStoreConstants.Store, () => {
231232
const firstLoad = ref(true);
232233
const loading = ref(true);
233-
const pageSize = ref(100);
234+
const pageSize = ref(PageSize.p100);
234235
const pagination = ref<TraktClientPagination>();
235236

236237
const typeLoading = reactive<ListTypeLoading>({});

src/stores/data/ratings.store.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import {
88
type TraktSyncRatingValue,
99
} from '@dvcol/trakt-http-client/models';
1010
import { defineStore, storeToRefs } from 'pinia';
11-
import { reactive, ref } from 'vue';
11+
import { computed, reactive, ref } from 'vue';
1212

13+
import { PageSize } from '~/models/page-size.model';
1314
import { ErrorService } from '~/services/error.service';
1415
import { Logger } from '~/services/logger.service';
1516
import { NotificationService } from '~/services/notification.service';
1617
import { TraktService } from '~/services/trakt.service';
18+
import { storage } from '~/utils/browser/browser-storage.utils';
1719
import { useI18n } from '~/utils/i18n.utils';
1820
import { ErrorCount, type ErrorDictionary, shouldRetry } from '~/utils/retry.utils';
1921

@@ -62,6 +64,10 @@ const createRatings = <T extends 'movie' | 'show' | 'season' | 'episode'>(
6264
} as never;
6365
};
6466

67+
type RatingsState = {
68+
pageSize: number;
69+
};
70+
6571
const RatingsStoreConstants = {
6672
Store: 'data.ratings',
6773
} as const;
@@ -71,13 +77,22 @@ export const useRatingsStore = defineStore(RatingsStoreConstants.Store, () => {
7177
const loading = reactive<RatingsLoadingDictionary>({});
7278
const errors = reactive<ErrorDictionary>({});
7379

74-
const pageSize = ref(500);
80+
const pageSize = ref(PageSize.p500);
7581
const paginations = reactive<RatingsPaginationDictionary>({});
7682

7783
ErrorService.registerDictionary('ratings', errors);
7884

7985
const i18n = useI18n('rating');
8086

87+
const saveState = async () =>
88+
storage.local.set<RatingsState>(RatingsStoreConstants.Store, {
89+
pageSize: pageSize.value,
90+
});
91+
const restoreState = async () => {
92+
const restored = await storage.local.get<RatingsState>(RatingsStoreConstants.Store);
93+
if (restored?.pageSize) pageSize.value = restored.pageSize;
94+
};
95+
8196
const clearState = () => {
8297
clearProxy(ratings);
8398
clearProxy(loading);
@@ -227,14 +242,26 @@ export const useRatingsStore = defineStore(RatingsStoreConstants.Store, () => {
227242
return getRatings(type, id);
228243
};
229244

245+
const initListStore = async () => {
246+
await restoreState();
247+
};
248+
230249
return {
250+
pageSize: computed({
251+
get: () => pageSize.value,
252+
set: (value: number) => {
253+
pageSize.value = value;
254+
saveState().catch(err => Logger.error('Failed to save ratings settings', { value, err }));
255+
},
256+
}),
231257
clearState,
232258
fetchRatings,
233259
getLoading,
234260
getRatings,
235261
loadRatings,
236262
addRating,
237263
removeRating,
264+
initListStore,
238265
};
239266
});
240267

src/stores/data/search.store.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import type { TraktClientPagination, TraktSearch, TraktSearchResult, TraktSearch
77
import type { ErrorDictionary } from '~/utils/retry.utils';
88

99
import { type ListScrollItem, ListScrollItemType } from '~/models/list-scroll.model';
10+
import { PageSize } from '~/models/page-size.model';
1011
import { ErrorService } from '~/services/error.service';
12+
1113
import { Logger } from '~/services/logger.service';
1214
import { NotificationService } from '~/services/notification.service';
1315

@@ -40,7 +42,7 @@ export const useSearchStore = defineStore(SearchStoreConstants.Store, () => {
4042
const searchErrors = reactive<ErrorDictionary>({});
4143
ErrorService.registerDictionary('search', searchErrors);
4244

43-
const pageSize = ref(100);
45+
const pageSize = ref(PageSize.p100);
4446
const pagination = ref<TraktClientPagination>();
4547

4648
const loading = ref(false);

src/stores/settings/extension.store.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CacheRetention } from '@dvcol/common-utils/common/cache';
22
import { defineStore, storeToRefs } from 'pinia';
33
import { computed, reactive, ref, toRaw } from 'vue';
44

5+
import { PageSize } from '~/models/page-size.model';
56
import { ProgressType, type ProgressTypes } from '~/models/progress-type.model';
67
import { Route } from '~/models/router.model';
78
import { Logger } from '~/services/logger.service';
@@ -55,7 +56,7 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
5556
const restoreRoute = ref<ExtensionSettings['restoreRoute']>(true);
5657
const restorePanel = ref<ExtensionSettings['restorePanel']>(false);
5758
const loadLists = ref<ExtensionSettings['loadLists']>([]);
58-
const loadListsPageSize = ref<ExtensionSettings['loadListsPageSize']>(500);
59+
const loadListsPageSize = ref<ExtensionSettings['loadListsPageSize']>(PageSize.p500);
5960
const defaultTab = ref<Route>(Route.Calendar);
6061
const initialized = ref<Promise<boolean>>();
6162
const progressType = ref<ExtensionSettings['progressType']>(ProgressType.Show);
@@ -158,7 +159,13 @@ export const useExtensionSettingsStore = defineStore(ExtensionSettingsConstants.
158159
saveState().catch(err => Logger.error('Failed to save load lists extension settings', { value, err }));
159160
},
160161
}),
161-
loadListsPageSize,
162+
loadListsPageSize: computed({
163+
get: () => loadListsPageSize.value,
164+
set: (value: number) => {
165+
loadListsPageSize.value = value;
166+
saveState().catch(err => Logger.error('Failed to save load lists page size extension settings', { value, err }));
167+
},
168+
}),
162169
toggleTab,
163170
routeDictionary,
164171
defaultTab: computed({

src/utils/trakt-service.utils.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import { reactive, ref, type Ref } from 'vue';
1212
import type { RecursiveRecord } from '@dvcol/common-utils/common';
1313
import type { JsonWriterOptions } from '@dvcol/common-utils/common/save';
1414

15+
import { PageSize } from '~/models/page-size.model';
16+
1517
type PaginatedQuery = TraktApiParamsExtended & TraktApiParamsPagination;
1618
export const paginatedWriteJson = async <Q extends PaginatedQuery = PaginatedQuery, T extends RecursiveRecord = RecursiveRecord>(
1719
fetch: (query: Q) => Promise<TraktApiResponse<T>>,
18-
query: Q = { extended: TraktApiExtended.Full, pagination: { limit: 1000 } } as Q,
20+
query: Q = { extended: TraktApiExtended.Full, pagination: { limit: PageSize.p1000 } } as Q,
1921
writerOptions?: JsonWriterOptions,
2022
cancel?: Ref<boolean>,
2123
pagination?: Partial<TraktClientPagination>,
@@ -46,7 +48,7 @@ export const paginatedWriteJson = async <Q extends PaginatedQuery = PaginatedQue
4648
export type CancellableWritePromise<T> = Promise<T> & { cancel: () => Promise<T>; pagination: Partial<TraktClientPagination> };
4749
export const cancellablePaginatedWriteJson = <Q extends PaginatedQuery = PaginatedQuery, T extends RecursiveRecord = RecursiveRecord>(
4850
fetch: (query: Q) => Promise<TraktApiResponse<T>>,
49-
query: Q = { extended: TraktApiExtended.Full, pagination: { limit: 1000 } } as Q,
51+
query: Q = { extended: TraktApiExtended.Full, pagination: { limit: PageSize.p1000 } } as Q,
5052
writerOptions?: JsonWriterOptions & { separator?: string },
5153
): CancellableWritePromise<FileSystemFileHandle> => {
5254
const cancel = ref(false);

0 commit comments

Comments
 (0)