Skip to content
This repository was archived by the owner on Feb 28, 2026. It is now read-only.

Commit df1107b

Browse files
authored
Merge pull request #16 from NuclearPlayer/feat/artist-page
Artist page
2 parents 1073380 + c58687a commit df1107b

File tree

70 files changed

+2821
-572
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2821
-572
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.0.8",
44
"private": true,
55
"type": "module",
6-
"packageManager": "pnpm@10.14.0",
6+
"packageManager": "pnpm@10.16.1",
77
"scripts": {
88
"dev": "turbo dev --filter=@nuclearplayer/player --filter=@nuclearplayer/ui",
99
"build": "turbo build",

packages/model/src/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,29 @@ export type ArtworkSet = {
2626

2727
export type ArtistRef = {
2828
name: string;
29+
disambiguation?: string;
30+
artwork?: ArtworkSet;
2931
source: ProviderRef;
3032
};
3133

3234
export type AlbumRef = {
3335
title: string;
3436
artists?: ArtistRef[];
37+
artwork?: ArtworkSet;
3538
source: ProviderRef;
3639
};
3740

3841
export type TrackRef = {
3942
title: string;
4043
artists: ArtistRef[];
44+
artwork?: ArtworkSet;
45+
source: ProviderRef;
46+
};
47+
48+
export type PlaylistRef = {
49+
id: string;
50+
name: string;
51+
artwork?: ArtworkSet;
4152
source: ProviderRef;
4253
};
4354

@@ -95,6 +106,8 @@ export type Album = {
95106
export type Artist = {
96107
name: string;
97108
disambiguation?: string;
109+
bio?: string;
110+
onTour?: boolean;
98111
artwork?: ArtworkSet;
99112
tags?: string[];
100113
source: ProviderRef;

packages/player/src/__snapshots__/App.test.tsx.snap

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ exports[`App > should render snapshot 1`] = `
66
class="grid h-screen w-screen grid-rows-[auto_1fr_auto] overflow-hidden"
77
>
88
<header
9-
class="bg-background border-border flex h-12 items-center border-b-2 px-4"
9+
class="bg-background-secondary border-border flex h-12 items-center border-b-2 px-4"
1010
>
1111
<svg
1212
class="inline-flex h-6 w-6"
@@ -36,7 +36,7 @@ exports[`App > should render snapshot 1`] = `
3636
</svg>
3737
<div>
3838
<input
39-
class="bg-background border-border ml-4 w-80 rounded border-2 px-3 py-1 outline-none"
39+
class="bg-background border-border ml-4 w-80 rounded-md border-2 px-3 py-1 outline-none"
4040
data-testid="search-box"
4141
placeholder="Search"
4242
value=""
@@ -116,7 +116,7 @@ exports[`App > should render snapshot 1`] = `
116116
class="mb-4 flex flex-row items-center justify-end"
117117
>
118118
<button
119-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center top-2 px-2 right-1"
119+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center top-2 px-2 right-1"
120120
data-headlessui-state=""
121121
data-testid="sidebar-toggle-left"
122122
type="submit"
@@ -161,7 +161,7 @@ exports[`App > should render snapshot 1`] = `
161161
class="mb-4 flex w-full flex-col text-sm"
162162
>
163163
<button
164-
class="cursor-pointer rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
164+
class="cursor-pointer rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
165165
data-headlessui-state=""
166166
type="submit"
167167
>
@@ -220,7 +220,7 @@ exports[`App > should render snapshot 1`] = `
220220
class="mb-4 flex w-full flex-col text-sm"
221221
>
222222
<button
223-
class="cursor-pointer rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
223+
class="cursor-pointer rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
224224
data-headlessui-state=""
225225
type="submit"
226226
>
@@ -279,7 +279,7 @@ exports[`App > should render snapshot 1`] = `
279279
class="mb-4 flex w-full flex-col text-sm"
280280
>
281281
<button
282-
class="cursor-pointer rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
282+
class="cursor-pointer rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent h-9 px-3 inline-flex flex-row items-center justify-between"
283283
data-headlessui-state=""
284284
type="submit"
285285
>
@@ -359,7 +359,7 @@ exports[`App > should render snapshot 1`] = `
359359
transition="[object Object]"
360360
>
361361
<div
362-
class="relative flex h-full w-full flex-col items-start justify-start px-6 pt-6"
362+
class="bg-background relative flex h-full w-full flex-col items-start justify-start px-6 pt-6"
363363
>
364364
<h1
365365
class="mb-6 flex w-full flex-0 flex-row text-center text-3xl font-bold"
@@ -384,7 +384,7 @@ exports[`App > should render snapshot 1`] = `
384384
class="mb-4 flex flex-row items-center justify-start"
385385
>
386386
<button
387-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center top-2 px-2 left-1"
387+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center top-2 px-2 left-1"
388388
data-headlessui-state=""
389389
data-testid="sidebar-toggle-right"
390390
type="submit"
@@ -428,7 +428,7 @@ exports[`App > should render snapshot 1`] = `
428428
</div>
429429
</div>
430430
<footer
431-
class="bg-background border-border flex h-16 items-center border-t-2 px-4"
431+
class="bg-background-secondary border-border flex h-16 items-center border-t-2 px-4"
432432
>
433433
<div
434434
class="grid w-full grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-4"
@@ -440,11 +440,11 @@ exports[`App > should render snapshot 1`] = `
440440
class="flex min-w-0 items-center gap-3"
441441
>
442442
<div
443-
class="border-border bg-background-secondary size-12 shrink-0 overflow-hidden rounded border-2"
443+
class="border-border bg-background-secondary size-12 shrink-0 overflow-hidden rounded-md border-2"
444444
>
445445
<img
446446
alt=""
447-
class="size-full object-cover"
447+
class="size-full object-cover select-none"
448448
src="https://picsum.photos/64"
449449
/>
450450
</div>
@@ -471,7 +471,7 @@ exports[`App > should render snapshot 1`] = `
471471
class="flex items-center justify-center gap-2"
472472
>
473473
<button
474-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
474+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
475475
data-headlessui-state=""
476476
type="submit"
477477
>
@@ -506,7 +506,7 @@ exports[`App > should render snapshot 1`] = `
506506
</svg>
507507
</button>
508508
<button
509-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
509+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
510510
data-headlessui-state=""
511511
type="submit"
512512
>
@@ -532,7 +532,7 @@ exports[`App > should render snapshot 1`] = `
532532
</svg>
533533
</button>
534534
<button
535-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center"
535+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-primary border-border shadow-shadow hover:translate-x-shadow-x hover:translate-y-shadow-y border-2 hover:shadow-none size-10 justify-center"
536536
data-headlessui-state=""
537537
type="submit"
538538
>
@@ -555,7 +555,7 @@ exports[`App > should render snapshot 1`] = `
555555
</svg>
556556
</button>
557557
<button
558-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
558+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
559559
data-headlessui-state=""
560560
type="submit"
561561
>
@@ -581,7 +581,7 @@ exports[`App > should render snapshot 1`] = `
581581
</svg>
582582
</button>
583583
<button
584-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
584+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
585585
data-headlessui-state=""
586586
type="submit"
587587
>
@@ -621,7 +621,7 @@ exports[`App > should render snapshot 1`] = `
621621
class="flex items-center gap-2"
622622
>
623623
<button
624-
class="inline-flex cursor-pointer items-center rounded transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
624+
class="inline-flex cursor-pointer items-center rounded-md transition-all disabled:cursor-not-allowed disabled:opacity-50 text-foreground bg-transparent size-10 justify-center"
625625
data-headlessui-state=""
626626
type="submit"
627627
>
@@ -662,7 +662,7 @@ exports[`App > should render snapshot 1`] = `
662662
class="pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2"
663663
>
664664
<div
665-
class="border-border bg-background-input relative h-3 w-full rounded border-2"
665+
class="border-border bg-background-input relative h-3 w-full rounded-md border-2"
666666
>
667667
<div
668668
class="bg-primary absolute top-0 left-0 h-full rounded-l"

packages/player/src/routeTree.gen.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Route as SearchRouteImport } from './routes/search'
1515
import { Route as PluginsRouteImport } from './routes/plugins'
1616
import { Route as DashboardRouteImport } from './routes/dashboard'
1717
import { Route as IndexRouteImport } from './routes/index'
18+
import { Route as ArtistProviderIdArtistIdRouteImport } from './routes/artist/$providerId/$artistId'
1819

1920
const ThemesRoute = ThemesRouteImport.update({
2021
id: '/themes',
@@ -46,6 +47,12 @@ const IndexRoute = IndexRouteImport.update({
4647
path: '/',
4748
getParentRoute: () => rootRouteImport,
4849
} as any)
50+
const ArtistProviderIdArtistIdRoute =
51+
ArtistProviderIdArtistIdRouteImport.update({
52+
id: '/artist/$providerId/$artistId',
53+
path: '/artist/$providerId/$artistId',
54+
getParentRoute: () => rootRouteImport,
55+
} as any)
4956

5057
export interface FileRoutesByFullPath {
5158
'/': typeof IndexRoute
@@ -54,6 +61,7 @@ export interface FileRoutesByFullPath {
5461
'/search': typeof SearchRoute
5562
'/settings': typeof SettingsRoute
5663
'/themes': typeof ThemesRoute
64+
'/artist/$providerId/$artistId': typeof ArtistProviderIdArtistIdRoute
5765
}
5866
export interface FileRoutesByTo {
5967
'/': typeof IndexRoute
@@ -62,6 +70,7 @@ export interface FileRoutesByTo {
6270
'/search': typeof SearchRoute
6371
'/settings': typeof SettingsRoute
6472
'/themes': typeof ThemesRoute
73+
'/artist/$providerId/$artistId': typeof ArtistProviderIdArtistIdRoute
6574
}
6675
export interface FileRoutesById {
6776
__root__: typeof rootRouteImport
@@ -71,6 +80,7 @@ export interface FileRoutesById {
7180
'/search': typeof SearchRoute
7281
'/settings': typeof SettingsRoute
7382
'/themes': typeof ThemesRoute
83+
'/artist/$providerId/$artistId': typeof ArtistProviderIdArtistIdRoute
7484
}
7585
export interface FileRouteTypes {
7686
fileRoutesByFullPath: FileRoutesByFullPath
@@ -81,8 +91,16 @@ export interface FileRouteTypes {
8191
| '/search'
8292
| '/settings'
8393
| '/themes'
94+
| '/artist/$providerId/$artistId'
8495
fileRoutesByTo: FileRoutesByTo
85-
to: '/' | '/dashboard' | '/plugins' | '/search' | '/settings' | '/themes'
96+
to:
97+
| '/'
98+
| '/dashboard'
99+
| '/plugins'
100+
| '/search'
101+
| '/settings'
102+
| '/themes'
103+
| '/artist/$providerId/$artistId'
86104
id:
87105
| '__root__'
88106
| '/'
@@ -91,6 +109,7 @@ export interface FileRouteTypes {
91109
| '/search'
92110
| '/settings'
93111
| '/themes'
112+
| '/artist/$providerId/$artistId'
94113
fileRoutesById: FileRoutesById
95114
}
96115
export interface RootRouteChildren {
@@ -100,6 +119,7 @@ export interface RootRouteChildren {
100119
SearchRoute: typeof SearchRoute
101120
SettingsRoute: typeof SettingsRoute
102121
ThemesRoute: typeof ThemesRoute
122+
ArtistProviderIdArtistIdRoute: typeof ArtistProviderIdArtistIdRoute
103123
}
104124

105125
declare module '@tanstack/react-router' {
@@ -146,6 +166,13 @@ declare module '@tanstack/react-router' {
146166
preLoaderRoute: typeof IndexRouteImport
147167
parentRoute: typeof rootRouteImport
148168
}
169+
'/artist/$providerId/$artistId': {
170+
id: '/artist/$providerId/$artistId'
171+
path: '/artist/$providerId/$artistId'
172+
fullPath: '/artist/$providerId/$artistId'
173+
preLoaderRoute: typeof ArtistProviderIdArtistIdRouteImport
174+
parentRoute: typeof rootRouteImport
175+
}
149176
}
150177
}
151178

@@ -156,6 +183,7 @@ const rootRouteChildren: RootRouteChildren = {
156183
SearchRoute: SearchRoute,
157184
SettingsRoute: SettingsRoute,
158185
ThemesRoute: ThemesRoute,
186+
ArtistProviderIdArtistIdRoute: ArtistProviderIdArtistIdRoute,
159187
}
160188
export const routeTree = rootRouteImport
161189
._addFileChildren(rootRouteChildren)

packages/player/src/routes/__root.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const SearchBox = () => {
5555
}
5656
}}
5757
placeholder="Search"
58-
className="bg-background border-border ml-4 w-80 rounded border-2 px-3 py-1 outline-none"
58+
className="bg-background border-border ml-4 w-80 rounded-md border-2 px-3 py-1 outline-none"
5959
/>
6060
</div>
6161
);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { createFileRoute } from '@tanstack/react-router';
2+
import z from 'zod';
3+
4+
import { Artist } from '../../../views/Artist/Artist';
5+
6+
export const Route = createFileRoute('/artist/$providerId/$artistId')({
7+
params: {
8+
parse: (params) => ({
9+
providerId: z.string().parse(params.providerId),
10+
artistId: z.string().parse(params.artistId),
11+
}),
12+
stringify: ({ providerId, artistId }) => ({
13+
providerId: `${providerId}`,
14+
artistId: `${artistId}`,
15+
}),
16+
},
17+
component: Artist,
18+
});

packages/player/src/services/advancedThemeDirService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
BaseDirectory,
44
readDir,
55
readTextFile,
6-
watch,
6+
watchImmediate,
77
} from '@tauri-apps/plugin-fs';
88

99
import { parseAdvancedTheme } from '@nuclearplayer/themes';
@@ -81,7 +81,7 @@ export const startAdvancedThemeWatcher = async (): Promise<void> => {
8181
return;
8282
}
8383
try {
84-
unwatch = await watch(
84+
unwatch = await watchImmediate(
8585
dir,
8686
async (event) => {
8787
await refreshAdvancedThemeList();
@@ -98,7 +98,7 @@ export const startAdvancedThemeWatcher = async (): Promise<void> => {
9898
return;
9999
}
100100

101-
if (!event.paths.some((p) => p === currentPath)) {
101+
if (!event.paths.some((p) => p.endsWith(currentPath))) {
102102
return;
103103
}
104104

0 commit comments

Comments
 (0)