Skip to content

Commit 107bf2a

Browse files
committed
feat(brand): adds support for new branding
1 parent 43ad21b commit 107bf2a

30 files changed

+426
-61
lines changed

src/assets/brand/apple-touch-icon.png

16.4 KB
Loading

src/assets/brand/favicon-128x128.png

11.9 KB
Loading

src/assets/brand/favicon-16x16.png

1.25 KB
Loading

src/assets/brand/favicon-32x32.png

2.73 KB
Loading

src/assets/brand/favicon-48x48.png

4.05 KB
Loading

src/assets/brand/favicon.svg

+34
Loading

src/assets/brand/icon-512.png

51.9 KB
Loading
9.7 KB
Loading

src/assets/favicon/favicon-48x48.png

6.24 KB
Loading

src/assets/favicon/icon-512.png

24 KB
Loading
5.34 KB
Binary file not shown.

src/components/common/list/ListItem.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { PosterItem } from '~/models/poster.model';
1616
import ListItemPanel from '~/components/common/list/ListItemPanel.vue';
1717
import PosterComponent from '~/components/common/poster/PosterComponent.vue';
1818
import { type ListScrollItem, ListScrollItemType } from '~/models/list-scroll.model';
19-
import { Colors } from '~/styles/colors.style';
19+
import { BrandColors } from '~/styles/colors.style';
2020
import { useI18n } from '~/utils/i18n.utils';
2121
2222
const props = defineProps({
@@ -43,7 +43,7 @@ const props = defineProps({
4343
color: {
4444
type: String,
4545
required: false,
46-
default: Colors.traktRedDark,
46+
default: BrandColors.traktDark,
4747
},
4848
lineType: {
4949
type: String as PropType<'dashed' | 'default'>,

src/components/common/navbar/NavbarComponent.vue

+3
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ nav {
358358
:deep(.n-tabs-capsule) {
359359
height: calc(#{layout.$header-navbar-height} - 0.75rem) !important;
360360
border-radius: 0.5rem !important;
361+
transition:
362+
background-color 0.3s var(--n-bezier),
363+
transform 0.3s var(--n-bezier);
361364
}
362365
363366
:deep(.tab) {

src/components/common/poster/PosterComponent.vue

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ import {
77
type PropType,
88
reactive,
99
ref,
10-
toRaw,
1110
toRefs,
1211
watch,
1312
} from 'vue';
1413
1514
import type { PosterItem } from '~/models/poster.model';
1615
16+
import PosterPlaceholderNew from '~/assets/images/poster-placeholder-new.webp';
1717
import PosterPlaceholder from '~/assets/images/poster-placholder.webp';
18+
1819
import { Logger } from '~/services/logger.service';
1920
import { type ImageStoreMedias, useImageStore } from '~/stores/data/image.store';
21+
import { Brand, useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
2022
2123
const props = defineProps({
2224
item: {
@@ -88,6 +90,12 @@ const onLoad = () => {
8890
imgLoaded.value = true;
8991
};
9092
93+
const { brand } = useExtensionSettingsStoreRefs();
94+
const placeholder = computed(() => {
95+
if (brand.value === Brand.New) return PosterPlaceholderNew;
96+
return PosterPlaceholder;
97+
});
98+
9199
const { getImageUrl } = useImageStore();
92100
93101
const timeout = ref();
@@ -121,7 +129,6 @@ const getPosters = async (
121129
if (!_item?.key || !response) return;
122130
const key = [item.value.key, backdrop.value, type?.value].filter(Boolean).join('-');
123131
cache[key] = response;
124-
console.info('caching', query, key, response, toRaw(cache));
125132
} catch (error) {
126133
Logger.error('Failed to fetch poster', error);
127134
}
@@ -150,7 +157,7 @@ onBeforeUnmount(() => {
150157
lazy
151158
preview-disabled
152159
:src="resolvedPoster"
153-
:fallback-src="PosterPlaceholder"
160+
:fallback-src="placeholder"
154161
:on-load="onLoad"
155162
/>
156163
<NImage
@@ -164,8 +171,8 @@ onBeforeUnmount(() => {
164171
width="100%"
165172
lazy
166173
preview-disabled
167-
:src="PosterPlaceholder"
168-
:fallback-src="PosterPlaceholder"
174+
:src="placeholder"
175+
:fallback-src="placeholder"
169176
/>
170177
</template>
171178

src/components/container/ContainerComponent.ce.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const override: GlobalThemeOverrides = {
3131
};
3232
3333
const { drawer, open, dropdown } = NavbarService;
34-
const { enabledRoutes, backgroundColor } = useExtensionSettingsStoreRefs();
34+
const { enabledRoutes, backgroundColor, brand } = useExtensionSettingsStoreRefs();
3535
const { root, floating, reverse } = useAppStateStoreRefs();
3636
const { isWatching } = useWatchingStoreRefs();
3737
@@ -46,6 +46,7 @@ onBeforeMount(() => addCustomProgressProperty());
4646
'--tab-count': enabledRoutes.length + 1,
4747
'--background-color': backgroundColor,
4848
}"
49+
:data-brand="brand"
4950
>
5051
<NConfigProvider :theme="theme" :theme-overrides="override" abstract>
5152
<AppComponent />

src/components/icons/IconTraktNew.vue

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<template>
2+
<svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
3+
<defs>
4+
<radialGradient
5+
id="radial-gradient"
6+
cx="48.46"
7+
cy="-.95"
8+
fx="48.46"
9+
fy="-.95"
10+
r="64.84"
11+
gradientUnits="userSpaceOnUse"
12+
>
13+
<stop offset="0" stop-color="#9f42c6" />
14+
<stop offset=".27" stop-color="#a041c3" />
15+
<stop offset=".42" stop-color="#a43ebb" />
16+
<stop offset=".53" stop-color="#aa39ad" />
17+
<stop offset=".64" stop-color="#b4339a" />
18+
<stop offset=".73" stop-color="#c02b81" />
19+
<stop offset=".82" stop-color="#cf2061" />
20+
<stop offset=".9" stop-color="#e1143c" />
21+
<stop offset=".97" stop-color="#f50613" />
22+
<stop offset="1" stop-color="red" />
23+
</radialGradient>
24+
</defs>
25+
<g id="_x2D_-production">
26+
<g id="logomark.square.gradient">
27+
<path
28+
id="background"
29+
fill="url(#radial-gradient)"
30+
d="M48,11.26v25.47c0,6.22-5.05,11.27-11.27,11.27H11.26c-6.22,0-11.26-5.05-11.26-11.27V11.26C0,5.04,5.04,0,11.26,0h25.47c3.32,0,6.3,1.43,8.37,3.72.47.52.89,1.08,1.25,1.68.18.29.34.59.5.89.33.68.6,1.39.79,2.14.1.37.18.76.23,1.15.09.54.13,1.11.13,1.68Z"
31+
/>
32+
<g id="checkbox">
33+
<path
34+
fill="#fff"
35+
d="M13.62,17.97l7.92,7.92,1.47-1.47-7.92-7.92-1.47,1.47ZM28.01,32.37l1.47-1.46-2.16-2.16,20.32-20.32c-.19-.75-.46-1.46-.79-2.14l-22.46,22.46,3.62,3.62ZM12.92,18.67l-1.46,1.46,14.4,14.4,1.46-1.47-4.32-4.31L46.35,5.4c-.36-.6-.78-1.16-1.25-1.68l-23.56,23.56-8.62-8.61ZM47.87,9.58l-19.17,19.17,1.47,1.46,17.83-17.83v-1.12c0-.57-.04-1.14-.13-1.68ZM25.16,22.27l-7.92-7.92-1.47,1.47,7.92,7.92,1.47-1.47ZM41.32,35.12c0,3.42-2.78,6.2-6.2,6.2H12.88c-3.42,0-6.2-2.78-6.2-6.2V12.88c0-3.42,2.78-6.21,6.2-6.21h20.78v-2.07H12.88c-4.56,0-8.28,3.71-8.28,8.28v22.24c0,4.56,3.71,8.28,8.28,8.28h22.24c4.56,0,8.28-3.71,8.28-8.28v-3.51h-2.07v3.51Z"
36+
/>
37+
</g>
38+
</g>
39+
</g>
40+
</svg>
41+
</template>

src/components/views/panel/PanelLinks.vue

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
isKnownSource,
2222
} from '~/models/source.model';
2323
import { type TagLink } from '~/models/tag.model';
24+
import { useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
2425
import { resolveLinkUrl, useLinksStore } from '~/stores/settings/links.store';
2526
import { useI18n } from '~/utils/i18n.utils';
2627
@@ -96,6 +97,8 @@ const customLinks = computed(() => {
9697
});
9798
});
9899
100+
const { brand } = useExtensionSettingsStoreRefs();
101+
99102
const links = computed(() => {
100103
if (!ids?.value) return;
101104
const _links: TagLink[] = [];
@@ -110,7 +113,7 @@ const links = computed(() => {
110113
season: season?.value,
111114
episode: episode?.value,
112115
}),
113-
icon: getIconFromSource(key),
116+
icon: getIconFromSource(key, brand.value),
114117
});
115118
});
116119
if (customLinks.value) _links.push(...customLinks.value);

src/components/views/panel/PanelRatings.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { RatingItem } from '~/models/rating.model';
1010
import IconStarFilledHalf from '~/components/icons/IconStarFilledHalf.vue';
1111
import PanelRating from '~/components/views/panel/PanelRating.vue';
1212
import { getIconFromSource } from '~/models/source.model';
13+
import { useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
1314
1415
const props = defineProps({
1516
ratings: {
@@ -20,13 +21,16 @@ const props = defineProps({
2021
2122
const { ratings } = toRefs(props);
2223
24+
const { brand } = useExtensionSettingsStoreRefs();
2325
const getIcon = (icon: RatingItem['icon']): DropdownOption['icon'] => {
2426
if (!icon) return undefined;
2527
return () =>
2628
h(NIcon, {
2729
style: { marginRight: '-0.25rem' },
2830
component:
29-
typeof icon === 'string' ? getIconFromSource(icon, IconStarFilledHalf) : icon,
31+
typeof icon === 'string'
32+
? getIconFromSource(icon, brand.value, IconStarFilledHalf)
33+
: icon,
3034
});
3135
};
3236

src/components/views/settings/SettingsTabs.vue

+18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { useRatingsStoreRefs } from '~/stores/data/ratings.store';
2929
import { useSearchStoreRefs } from '~/stores/data/search.store';
3030
import { useAuthSettingsStoreRefs } from '~/stores/settings/auth.store';
3131
import {
32+
Brand,
3233
useExtensionSettingsStore,
3334
useExtensionSettingsStoreRefs,
3435
} from '~/stores/settings/extension.store';
@@ -54,6 +55,7 @@ const {
5455
loadingHysteresis,
5556
navbarPosition,
5657
iconOnly,
58+
brand,
5759
} = useExtensionSettingsStoreRefs();
5860
5961
const { getIcon, fetchLists } = useListsStore();
@@ -151,6 +153,10 @@ const onColor = () => {
151153
picker.value?.focus();
152154
picker.value?.click();
153155
};
156+
157+
const toggleBrand = () => {
158+
brand.value = brand.value === Brand.New ? Brand.Old : Brand.New;
159+
};
154160
</script>
155161

156162
<template>
@@ -223,6 +229,18 @@ const onColor = () => {
223229
</div>
224230
</SettingsFormItem>
225231

232+
<!-- Brand -->
233+
<SettingsFormItem :label="i18n('label_brand')">
234+
<NSwitch
235+
class="form-switch"
236+
:value="brand === Brand.New"
237+
@update:value="toggleBrand()"
238+
>
239+
<template #checked>{{ i18n('new', 'common', 'button') }}</template>
240+
<template #unchecked>{{ i18n('old', 'common', 'button') }}</template>
241+
</NSwitch>
242+
</SettingsFormItem>
243+
226244
<!-- Icon Only -->
227245
<SettingsFormItem :label="i18n('label_icon_only')">
228246
<NSwitch v-model:value="iconOnly" class="form-switch">

src/i18n/en/common/button.json

+8
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,13 @@
9494
"common__button__watched": {
9595
"message": "Watched",
9696
"description": "Button to mark as watched."
97+
},
98+
"common__button__new": {
99+
"message": "New",
100+
"description": "New button."
101+
},
102+
"common__button__old": {
103+
"message": "Old",
104+
"description": "Old button."
97105
}
98106
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
"message": "Background Color",
44
"description": "Label for the 'Background Color' setting"
55
},
6+
"settings__tabs__label_brand": {
7+
"message": "Branding",
8+
"description": "Label for the 'Branding' setting"
9+
},
610
"settings__tabs__label_loading_bar": {
711
"message": "Loading Bar Hysteresis",
812
"description": "Label for the 'Loading Bar Hysteresis' setting"

src/index.html

+12-8
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@
44
<meta charset="UTF-8" />
55
<base target="_blank" />
66
<title>Side Trakt Web</title>
7-
<link rel="icon" href="./assets/logo.svg" type="image/svg+xml" />
8-
<link rel="fluid-icon" href="./assets/logo.svg" type="image/svg+xml" />
9-
<link rel="mask-icon" href="./assets/logo.svg" color="#181818" />
107

11-
<link rel="apple-touch-icon" sizes="180x180" href="./assets/favicon/apple-touch-icon.png" />
12-
<link rel="icon" type="image/png" sizes="32x32" href="./assets/favicon/favicon-32x32.png" />
13-
<link rel="icon" type="image/png" sizes="16x16" href="./assets/favicon/favicon-16x16.png" />
14-
<link rel="mask-icon" href="./assets/favicon/safari-pinned-tab.svg" color="#5bbad5" />
8+
<link id="svg-icon" rel="icon" href="./assets/logo.svg" type="image/svg+xml" />
9+
<link id="svg-fluid-icon" rel="fluid-icon" href="./assets/logo.svg" type="image/svg+xml" />
10+
<link id="svg-mask-icon" rel="mask-icon" href="./assets/logo.svg" type="image/svg+xml" color="#181818" />
11+
12+
<link id="png-icon-16x16" rel="icon" type="image/png" sizes="16x16" href="./assets/favicon/favicon-16x16.png" />
13+
<link id="png-icon-32x32" rel="icon" type="image/png" sizes="32x32" href="./assets/favicon/favicon-32x32.png" />
14+
<link id="png-icon-48x48" rel="icon" type="image/png" sizes="48x48" href="./assets/favicon/favicon-48x48.png" />
15+
16+
<link id="apple-icon" rel="apple-touch-icon" sizes="180x180" href="./assets/favicon/apple-touch-icon.png" />
17+
18+
<meta id="theme-color" name="theme-color" content="#80000a" />
19+
1520
<meta name="msapplication-TileColor" content="#da532c" />
16-
<meta name="theme-color" content="#80000a" />
1721
<meta name="mobile-web-app-capable" content="yes">
1822
<meta name="apple-mobile-web-app-capable" content="yes">
1923
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

src/models/message/message-type.model.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const MessageType = {
66
VersionUpdate: 'version-update',
77
AppReady: 'app-ready',
88
BadgeUpdate: 'badge-update',
9+
IconUpdate: 'icon-update',
910
} as const;
1011

1112
export type MessageTypes = (typeof MessageType)[keyof typeof MessageType];
@@ -28,4 +29,6 @@ export type MessagePayload<T extends MessageTypes = MessageTypes> = T extends ty
2829
? boolean
2930
: T extends typeof MessageType.BadgeUpdate
3031
? BadgeUpdatePayload
31-
: MessageTypes;
32+
: T extends typeof MessageType.IconUpdate
33+
? string
34+
: never;

src/models/source.model.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@ import type { Component } from 'vue';
22

33
import type { I18nFunction } from '~/models/i18n.model';
44

5+
import type { Brands } from '~/stores/settings/extension.store';
6+
57
import IconExternalLinkRounded from '~/components/icons/IconExternalLinkRounded.vue';
68
import IconIMDb from '~/components/icons/IconIMDb.vue';
79
import IconMyAnimeList from '~/components/icons/IconMyAnimeList.vue';
810
import IconSimkl from '~/components/icons/IconSimkl.vue';
911
import IconTMDb from '~/components/icons/IconTMDb.vue';
1012
import IconTVDb from '~/components/icons/IconTVDb.vue';
1113
import IconTrakt from '~/components/icons/IconTrakt.vue';
14+
import IconTraktNew from '~/components/icons/IconTraktNew.vue';
1215
import { ResolveExternalLinks } from '~/settings/external.links';
16+
import { Brand } from '~/stores/settings/extension.store';
1317

1418
export const DataSource = {
1519
Trakt: 'trakt',
@@ -25,10 +29,10 @@ export type DataSources = (typeof DataSource)[keyof typeof DataSource];
2529
export const AllDataSources = Object.keys(DataSource).map(key => key.toLowerCase());
2630
export const isKnownSource = (source: string): source is DataSources => AllDataSources.includes(source);
2731

28-
export const getIconFromSource = (source: DataSources | string, fallback: Component = IconExternalLinkRounded): Component => {
32+
export const getIconFromSource = (source: DataSources | string, brand?: Brands, fallback: Component = IconExternalLinkRounded): Component => {
2933
switch (source) {
3034
case DataSource.Trakt:
31-
return IconTrakt;
35+
return brand === Brand.New ? IconTraktNew : IconTrakt;
3236
case DataSource.Tmdb:
3337
return IconTMDb;
3438
case DataSource.Imdb:

0 commit comments

Comments
 (0)