Skip to content

Commit dc43e28

Browse files
committed
feat(history): adds basic history infinite scroll
1 parent 3c8bc2c commit dc43e28

File tree

8 files changed

+100
-15
lines changed

8 files changed

+100
-15
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"dependencies": {
5454
"@dvcol/web-extension-utils": "^2.3.4",
5555
"@vue/devtools": "^7.0.15",
56-
"naive-ui": "^2.37.3",
56+
"naive-ui": "^2.38.1",
5757
"pinia": "^2.1.7",
5858
"vue": "^3.4.14",
5959
"vue-router": "^4.2.5"

pnpm-lock.yaml

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/AppComponent.vue

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ const { isAuthenticated } = useAuthSettingsStoreRefs();
1818
<RouterView v-slot="{ Component, route }">
1919
<GridBackground v-if="!Component" :size="20" />
2020
<Transition name="scale" mode="out-in">
21-
<component :is="Component ?? PageLoading" :key="route.path" />
21+
<KeepAlive>
22+
<component :is="Component ?? PageLoading" :key="route.path" />
23+
</KeepAlive>
2224
</Transition>
2325
</RouterView>
2426
</main>
@@ -33,12 +35,13 @@ const { isAuthenticated } = useAuthSettingsStoreRefs();
3335
$header-height: 2.75rem;
3436
3537
header {
36-
position: sticky;
38+
position: fixed;
3739
top: 0;
3840
z-index: layers.$layer-ui;
3941
display: flex;
4042
flex-direction: column;
4143
justify-content: center;
44+
width: 100%;
4245
height: $header-height;
4346
4447
> :first-child {
@@ -51,6 +54,6 @@ main {
5154
align-items: center;
5255
justify-content: center;
5356
min-height: calc(100% - #{$header-height});
54-
padding: 0 2rem;
57+
margin-top: $header-height;
5558
}
5659
</style>

src/components/common/navbar/NavbarComponent.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const navElement = ref<HTMLElement>();
5555

5656
<style lang="scss" scoped>
5757
nav {
58-
margin: 0 0.25rem;
58+
padding: 0 0.25rem;
5959
font-size: 12px;
6060
text-align: center;
6161

src/components/views/history/HistoryComponent.vue

+82-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,89 @@
11
<script lang="ts" setup>
2-
// TODO
2+
import { NTimeline, NTimelineItem, NVirtualList } from 'naive-ui';
3+
import { onActivated, onMounted, ref } from 'vue';
4+
5+
import type { VirtualListInst } from 'naive-ui';
6+
7+
import type { TraktClientPagination } from '~/models/trakt/trakt-client.model';
8+
import type { TraktHistory } from '~/models/trakt/trakt-history.model';
9+
10+
import { TraktService } from '~/services/trakt.service';
11+
12+
const history = ref<TraktHistory[]>([]);
13+
const pagination = ref<TraktClientPagination>();
14+
const virtualList = ref<VirtualListInst>();
15+
16+
const fetchData = async (
17+
page = pagination.value?.page ? pagination.value.page + 1 : 0,
18+
) => {
19+
const response = await TraktService.traktClient.sync.history.get.cached({
20+
pagination: {
21+
page,
22+
limit: 30,
23+
},
24+
});
25+
26+
const data = await response.json();
27+
pagination.value = response.pagination;
28+
history.value = [...history.value, ...data];
29+
};
30+
31+
const onScroll = async (e: Event) => {
32+
if (!e?.target) return;
33+
const { scrollTop, scrollHeight, clientHeight } = e.target as HTMLDivElement;
34+
if (!scrollTop || scrollHeight !== scrollTop + clientHeight) return;
35+
if (pagination.value?.page === pagination.value?.pageCount) return;
36+
37+
const key = history.value[history.value.length - 1].id;
38+
await fetchData();
39+
virtualList.value?.scrollTo({ key, debounce: true });
40+
};
41+
42+
onMounted(() => {
43+
console.info('History mounted');
44+
fetchData();
45+
});
46+
47+
onActivated(() => {
48+
console.info('History activated');
49+
});
50+
51+
const getTitle = (media: TraktHistory) => {
52+
if ('movie' in media) return media.movie.title;
53+
return `${media.episode.season}x${media.episode.number.toString().padStart(2, '0')} - ${
54+
media.episode.title
55+
}`;
56+
};
357
</script>
458

559
<template>
6-
<span>This is a history component</span>
60+
<NVirtualList
61+
ref="virtualList"
62+
style="max-height: calc(100dvh - 8px); margin-top: -44px; margin-bottom: 8px"
63+
:item-size="80"
64+
:data-length="history.length"
65+
:items="history"
66+
:visible-items-tag="NTimeline"
67+
:visible-items-tag-props="{ size: 'large' }"
68+
:padding-top="56"
69+
:padding-bottom="16"
70+
@scroll="onScroll"
71+
>
72+
<template #default="{ item }">
73+
<NTimelineItem
74+
:key="item.id"
75+
:data-key="item.id"
76+
:style="{
77+
fontVariantNumeric: 'tabular-nums',
78+
margin: '0 1rem',
79+
}"
80+
type="success"
81+
:title="getTitle(item)"
82+
:content="item.show?.title"
83+
:time="new Date(item.watched_at).toLocaleString()"
84+
/>
85+
</template>
86+
</NVirtualList>
787
</template>
888

989
<style lang="scss" scoped>

src/models/trakt/trakt-client.model.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ export class TraktClientEndpoint<
103103
Parameter extends TraktApiParams = Record<string, never>,
104104
Response = unknown,
105105
Cache extends boolean = true,
106-
> extends ClientEndpoint<Parameter, Response, Cache, TraktApiTemplateOptions<keyof Parameter>> {}
106+
> extends ClientEndpoint<Parameter, Response, Cache, TraktApiTemplateOptions<keyof Parameter>> {
107+
declare cached: Cache extends true ? Omit<this, 'cached'> & TraktClientEndpoint<Parameter, Response> : never;
108+
}
107109

108110
export type TraktApiRequest = BaseRequest;
109111

src/services/common/base-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ type ClientEndpointCall<Parameter extends Record<string, never> = Record<string,
9696
init?: BaseInit,
9797
) => Promise<ResponseOrTypedResponse<Response>>;
9898

99-
export interface ClientEndpoint<Parameter extends RecursiveRecord = Record<string, never>> {
100-
(param?: Parameter, init?: BaseInit): Promise<ResponseOrTypedResponse>;
99+
export interface ClientEndpoint<Parameter extends RecursiveRecord = Record<string, never>, Response = unknown> {
100+
(param?: Parameter, init?: BaseInit): Promise<ResponseOrTypedResponse<Response>>;
101101
}
102102
type BaseCacheOption = { force?: boolean; retention?: number };
103103

src/styles/base.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
--vt-c-text-dark-2: rgb(235 235 235 / 64%);
1818

1919
/* ui color variables */
20-
--bg-blue: 2px;
20+
--bg-blur: 2px;
2121
--bg-blur-black: rgb(0 0 0 / 30%);
2222
--bg-blur-black-hover: rgb(0 0 0 / 60%);
2323

0 commit comments

Comments
 (0)