+90
-88
src/lib/components/layout/main/card/MusicStatusCard.svelte
+90
-88
src/lib/components/layout/main/card/MusicStatusCard.svelte
···
75
75
{@const safeMusicStatus = musicStatus}
76
76
<Card variant="elevated" padding="md">
77
77
{#snippet children()}
78
-
<div class="flex items-start gap-3">
79
-
<!-- Artwork -->
80
-
<div class="shrink-0">
81
-
{#if safeMusicStatus.artworkUrl && !artworkError}
82
-
<img
83
-
src={safeMusicStatus.artworkUrl}
84
-
alt="Album artwork for {safeMusicStatus.releaseName || safeMusicStatus.trackName}"
85
-
class="h-20 w-20 rounded-lg object-cover shadow-md"
86
-
loading="lazy"
87
-
onerror={handleImageError}
88
-
/>
89
-
{:else}
90
-
<div
91
-
class="flex h-20 w-20 items-center justify-center rounded-lg bg-canvas-200 shadow-md dark:bg-canvas-700"
92
-
>
93
-
<Disc3 class="h-10 w-10 text-ink-500 dark:text-ink-400" aria-hidden="true" />
94
-
</div>
95
-
{/if}
78
+
<div>
79
+
<!-- Header (Now Listening / Last Played) -->
80
+
<div class="mb-4 flex items-center gap-2">
81
+
<Music class="h-4 w-4 text-primary-600 dark:text-primary-400" aria-hidden="true" />
82
+
<span
83
+
class="text-xs font-semibold tracking-wide text-ink-800 uppercase dark:text-ink-100"
84
+
>
85
+
{safeMusicStatus.$type === 'fm.teal.alpha.actor.status'
86
+
? 'Now Listening'
87
+
: 'Last Played'}
88
+
</span>
96
89
</div>
97
90
98
-
<!-- Info -->
99
-
<div class="min-w-0 flex-1">
100
-
<!-- Header (Now Listening / Last Played) -->
101
-
<div class="mb-4 flex items-center gap-2">
102
-
<Music class="h-4 w-4 text-primary-600 dark:text-primary-400" aria-hidden="true" />
103
-
<span
104
-
class="text-xs font-semibold tracking-wide text-ink-800 uppercase dark:text-ink-100"
105
-
>
106
-
{safeMusicStatus.$type === 'fm.teal.alpha.actor.status'
107
-
? 'Now Listening'
108
-
: 'Last Played'}
109
-
</span>
110
-
</div>
111
-
112
-
<!-- Content -->
113
-
<div class="mb-4">
114
-
<!-- Track Name -->
115
-
<a
116
-
href={safeMusicStatus.originUrl || '#'}
117
-
target="_blank"
118
-
rel="noopener noreferrer"
119
-
class="block max-w-full text-lg font-semibold wrap-break-word whitespace-normal text-primary-600 transition-colors hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300"
120
-
class:pointer-events-none={!safeMusicStatus.originUrl}
121
-
class:cursor-default={!safeMusicStatus.originUrl}
122
-
class:opacity-70={!safeMusicStatus.originUrl}
123
-
>
124
-
{safeMusicStatus.trackName}
125
-
</a>
126
-
127
-
<!-- Artists -->
128
-
<p
129
-
class="mt-1 flex max-w-full items-start gap-1.5 text-base wrap-break-word whitespace-normal text-ink-800 dark:text-ink-100"
130
-
>
131
-
<Users class="mt-0.5 h-4 w-4 flex-shrink-0 text-ink-600 dark:text-ink-300" />
132
-
{formatArtists(safeMusicStatus.artists)}
133
-
</p>
134
-
135
-
<!-- Album + Duration -->
136
-
{#if safeMusicStatus.releaseName}
137
-
<p
138
-
class="mt-1 flex max-w-full items-start gap-1.5 text-sm wrap-break-word whitespace-normal text-ink-700 dark:text-ink-200"
91
+
<div class="flex items-start gap-3">
92
+
<!-- Artwork -->
93
+
<div class="shrink-0">
94
+
{#if safeMusicStatus.artworkUrl && !artworkError}
95
+
<img
96
+
src={safeMusicStatus.artworkUrl}
97
+
alt="Album artwork for {safeMusicStatus.releaseName || safeMusicStatus.trackName}"
98
+
class="h-20 w-20 rounded-lg object-cover shadow-md"
99
+
loading="lazy"
100
+
onerror={handleImageError}
101
+
/>
102
+
{:else}
103
+
<div
104
+
class="flex h-20 w-20 items-center justify-center rounded-lg bg-canvas-200 shadow-md dark:bg-canvas-700"
139
105
>
140
-
<Album class="mt-0.5 h-4 w-4 flex-shrink-0 text-ink-500 dark:text-ink-400" />
141
-
<span>
142
-
{safeMusicStatus.releaseName}
143
-
144
-
{#if safeMusicStatus.duration}
145
-
<span
146
-
class="ml-1 inline-flex items-center gap-1 text-ink-600 dark:text-ink-300"
147
-
>
148
-
· <Clock class="h-3 w-3" />
149
-
{formatDuration(safeMusicStatus.duration)}
150
-
</span>
151
-
{/if}
152
-
</span>
153
-
</p>
106
+
<Disc3 class="h-10 w-10 text-ink-500 dark:text-ink-400" aria-hidden="true" />
107
+
</div>
154
108
{/if}
155
109
</div>
156
110
157
-
<!-- Footer / Meta -->
158
-
<div class="flex items-center gap-2 text-xs text-ink-700 dark:text-ink-200">
159
-
<time datetime={safeMusicStatus.playedTime}>
160
-
{formatRelativeTime(safeMusicStatus.playedTime)}
161
-
</time>
162
-
163
-
{#if safeMusicStatus.musicServiceBaseDomain}
164
-
<span class="text-ink-600 dark:text-ink-300">·</span>
165
-
111
+
<!-- Info -->
112
+
<div class="min-w-0 flex-1">
113
+
<!-- Content -->
114
+
<div class="mb-4">
115
+
<!-- Track Name -->
166
116
<a
167
-
href="https://teal.fm"
117
+
href={safeMusicStatus.originUrl || '#'}
168
118
target="_blank"
169
119
rel="noopener noreferrer"
170
-
class="inline-flex items-center gap-1 transition-colors hover:text-primary-600 dark:hover:text-primary-400"
171
-
title="Powered by teal.fm"
120
+
class="block max-w-full text-lg font-semibold wrap-break-word whitespace-normal text-primary-600 transition-colors hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300"
121
+
class:pointer-events-none={!safeMusicStatus.originUrl}
122
+
class:cursor-default={!safeMusicStatus.originUrl}
123
+
class:opacity-70={!safeMusicStatus.originUrl}
172
124
>
173
-
<Radio class="h-3 w-3" />
174
-
{formatServiceName(safeMusicStatus.musicServiceBaseDomain)} via {safeMusicStatus.submissionClientAgent}
125
+
{safeMusicStatus.trackName}
175
126
</a>
176
-
{/if}
127
+
128
+
<!-- Artists -->
129
+
<p
130
+
class="mt-1 flex max-w-full items-start gap-1.5 text-base wrap-break-word whitespace-normal text-ink-800 dark:text-ink-100"
131
+
>
132
+
<Users class="mt-0.5 h-4 w-4 flex-shrink-0 text-ink-600 dark:text-ink-300" />
133
+
{formatArtists(safeMusicStatus.artists)}
134
+
</p>
135
+
136
+
<!-- Album + Duration -->
137
+
{#if safeMusicStatus.releaseName}
138
+
<p
139
+
class="mt-1 flex max-w-full items-start gap-1.5 text-sm wrap-break-word whitespace-normal text-ink-700 dark:text-ink-200"
140
+
>
141
+
<Album class="mt-0.5 h-4 w-4 flex-shrink-0 text-ink-500 dark:text-ink-400" />
142
+
<span>
143
+
{safeMusicStatus.releaseName}
144
+
145
+
{#if safeMusicStatus.duration}
146
+
<span
147
+
class="ml-1 inline-flex items-center gap-1 text-ink-600 dark:text-ink-300"
148
+
>
149
+
· <Clock class="h-3 w-3" />
150
+
{formatDuration(safeMusicStatus.duration)}
151
+
</span>
152
+
{/if}
153
+
</span>
154
+
</p>
155
+
{/if}
156
+
</div>
157
+
158
+
<!-- Footer / Meta -->
159
+
<div class="flex items-center gap-2 text-xs text-ink-700 dark:text-ink-200">
160
+
<time datetime={safeMusicStatus.playedTime}>
161
+
{formatRelativeTime(safeMusicStatus.playedTime)}
162
+
</time>
163
+
164
+
{#if safeMusicStatus.musicServiceBaseDomain}
165
+
<span class="text-ink-600 dark:text-ink-300">·</span>
166
+
167
+
<a
168
+
href="https://teal.fm"
169
+
target="_blank"
170
+
rel="noopener noreferrer"
171
+
class="inline-flex items-center gap-1 transition-colors hover:text-primary-600 dark:hover:text-primary-400"
172
+
title="Powered by teal.fm"
173
+
>
174
+
<Radio class="h-3 w-3" />
175
+
{formatServiceName(safeMusicStatus.musicServiceBaseDomain)} via {safeMusicStatus.submissionClientAgent}
176
+
</a>
177
+
{/if}
178
+
</div>
177
179
</div>
178
180
</div>
179
181
</div>
+1
-1
src/lib/components/layout/main/card/ProfileCard.svelte
+1
-1
src/lib/components/layout/main/card/ProfileCard.svelte
···
109
109
110
110
{#if safeProfile.description}
111
111
<p
112
-
class="mb-4 wrap-break-words break-all whitespace-pre-wrap text-ink-700 dark:text-ink-200"
112
+
class="wrap-break-words mb-4 break-all whitespace-pre-wrap text-ink-700 dark:text-ink-200"
113
113
>
114
114
{safeProfile.description}
115
115
</p>