Skip to content

Commit ec9a58b

Browse files
committed
feat(badge): adds support for progress badge
1 parent 06fb538 commit ec9a58b

File tree

10 files changed

+186
-37
lines changed

10 files changed

+186
-37
lines changed

src/components/views/settings/SettingsBadge.vue

+35-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
11
<script lang="ts" setup>
22
import { chromeRuntimeId } from '@dvcol/web-extension-utils/chrome/runtime';
3-
import { NSwitch } from 'naive-ui';
3+
import { NSelect, NSwitch } from 'naive-ui';
4+
5+
import { computed, ref } from 'vue';
46
57
import SettingsFormItem from '~/components/views/settings/SettingsFormItem.vue';
6-
import { useBadgeStoreRefs } from '~/stores/settings/badge.store';
8+
import { BadgeMode, useBadgeStoreRefs } from '~/stores/settings/badge.store';
9+
import { useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
710
import { useI18n } from '~/utils/i18n.utils';
11+
import { toSnakeCase } from '~/utils/string.utils';
812
913
const i18n = useI18n('settings', 'badge');
1014
11-
const { enableBadge } = useBadgeStoreRefs();
15+
const { enableBadge, badgeMode } = useBadgeStoreRefs();
16+
17+
const { isProgressEnabled } = useExtensionSettingsStoreRefs();
18+
19+
const options = computed(() =>
20+
Object.entries(BadgeMode).map(([key, value]) => ({
21+
label: i18n(toSnakeCase(key), 'common', 'badge', 'mode'),
22+
value,
23+
disabled: !isProgressEnabled.value && value === BadgeMode.Progress,
24+
})),
25+
);
26+
27+
const container = ref();
1228
</script>
1329

1430
<template>
15-
<div class="badge-container">
31+
<div ref="container" class="badge-container">
1632
<!-- Enable -->
1733
<SettingsFormItem :label="i18n('label_enable_badge')">
1834
<NSwitch
@@ -24,6 +40,17 @@ const { enableBadge } = useBadgeStoreRefs();
2440
<template #unchecked>{{ i18n('off', 'common', 'button') }}</template>
2541
</NSwitch>
2642
</SettingsFormItem>
43+
44+
<!-- Badge Mode -->
45+
<SettingsFormItem :label="i18n('label_badge_mode')">
46+
<NSelect
47+
v-model:value="badgeMode"
48+
class="form-select"
49+
:to="container"
50+
:options="options"
51+
:disabled="!enableBadge"
52+
/>
53+
</SettingsFormItem>
2754
</div>
2855
</template>
2956

@@ -33,4 +60,8 @@ const { enableBadge } = useBadgeStoreRefs();
3360
flex-direction: column;
3461
gap: 1.5rem;
3562
}
63+
64+
.form-select {
65+
min-width: 8rem;
66+
}
3667
</style>

src/components/views/settings/SettingsWatching.vue

+1-6
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,12 @@ import SettingsFormItem from '~/components/views/settings/SettingsFormItem.vue';
77
import { PollingIntervals } from '~/models/polling.model';
88
import { useWatchingStoreRefs } from '~/stores/data/watching.store';
99
import { useI18n } from '~/utils/i18n.utils';
10+
import { toSnakeCase } from '~/utils/string.utils';
1011
1112
const i18n = useI18n('settings', 'watching');
1213
1314
const { polling, override } = useWatchingStoreRefs();
1415
15-
const toSnakeCase = (str: string) =>
16-
str
17-
.replace(/([A-Z])/g, '_$1')
18-
.toLowerCase()
19-
.slice(1);
20-
2116
const options = Object.entries(PollingIntervals).map(([key, value]) => ({
2217
label: i18n(toSnakeCase(key), 'common', 'polling', 'interval'),
2318
value,

src/i18n/en/common/badge-mode.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"common__badge__mode__calendar": {
3+
"message": "Calendar",
4+
"description": "Badge mode calendar."
5+
},
6+
"common__badge__mode__progress": {
7+
"message": "Progress",
8+
"description": "Badge mode progress."
9+
}
10+
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"settings__badge__label_enable_badge": {
33
"message": "Enable badge (daily calendar releases)",
44
"description": "Label for enabling badge."
5+
},
6+
"settings__badge__label_badge_mode": {
7+
"message": "Badge mode",
8+
"description": "Label for badge mode."
59
}
610
}

src/models/list-scroll.model.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export const ListScrollItemType = {
8787
placeholder: 'placeholder',
8888
} as const;
8989

90-
export type ListScrollItemMeta = {
90+
export type ListScrollItemMeta<T = { [key: string]: unknown }> = {
9191
source: ListScrollSourceItem | ProgressItem;
9292
ids: {
9393
movie?: Partial<TraktMovie['ids']>;
@@ -101,8 +101,7 @@ export type ListScrollItemMeta = {
101101
season?: number;
102102
episode?: number;
103103
};
104-
[key: string]: unknown;
105-
};
104+
} & T;
106105

107106
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- meta is intentionally weakly typed
108107
export type ListScrollItem<T extends Record<string, any> = ListScrollItemMeta> = Omit<PosterItem, 'type'> & {

src/stores/data/progress.store.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,24 @@ import { ref } from 'vue';
44

55
import type { TraktEpisode, TraktShow } from '@dvcol/trakt-http-client/models';
66

7+
import type { ListScrollItem, ListScrollItemMeta, ListScrollSourceItem } from '~/models/list-scroll.model';
8+
79
import { getContent, getTags, getTitle } from '~/components/common/list/use-list-scroll';
8-
import { type ListScrollItem, type ListScrollSourceItem } from '~/models/list-scroll.model';
910
import { type ProgressItem } from '~/models/progress.model';
1011
import { Logger } from '~/services/logger.service';
1112
import { NotificationService } from '~/services/notification.service';
1213
import { TraktService } from '~/services/trakt.service';
1314
import { debounceLoading, useLoadingPlaceholder } from '~/utils/store.utils';
1415

15-
type ProgressListItem = Omit<ListScrollItem, 'posterRef' | 'progressRef'>;
16+
export type ProgressListItem = Omit<
17+
ListScrollItem<
18+
ListScrollItemMeta<{
19+
episode: ListScrollSourceItem['episode'];
20+
show: ListScrollSourceItem['show'];
21+
}>
22+
>,
23+
'posterRef' | 'progressRef'
24+
>;
1625

1726
const titleRegex = /(.*)\s\d+x\d+\s"([^"]+)"/;
1827

@@ -77,6 +86,11 @@ export const progressToListItem = (progress: ProgressItem, index: number): Progr
7786
};
7887
};
7988

89+
export const fetchProgressData = async (): Promise<ProgressListItem[]> => {
90+
const items = await TraktService.progress.onDeck();
91+
return items.map<ProgressListItem>(progressToListItem);
92+
};
93+
8094
export const useProgressStore = defineStore('data.progress', () => {
8195
const firstLoad = ref(true);
8296
const loading = ref(true);
@@ -100,8 +114,7 @@ export const useProgressStore = defineStore('data.progress', () => {
100114
loading.value = true;
101115
const timeout = debounceLoading(progress, loadingPlaceholder, true);
102116
try {
103-
const items = await TraktService.progress.onDeck();
104-
progress.value = items.map<ProgressListItem>(progressToListItem);
117+
progress.value = await fetchProgressData();
105118
} catch (error) {
106119
progress.value = [];
107120
loading.value = false;

src/stores/data/releases.store.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export const useReleasesStore = defineStore(ReleasesStoreConstants.Store, () =>
189189

190190
newData.sort((a: CalendarItem, b: CalendarItem) => a.date.getTime() - b.date.getTime());
191191

192-
const spacedData = spaceDate(newData, startDate, endDate);
192+
const spacedData = spaceDate(newData, { startDate, endDate, days: days.value });
193193

194194
if (mode === 'reload') {
195195
releases.value = [...spacedData];

0 commit comments

Comments
 (0)