feat: implement better track view, fix virtual list issue, implement icons
This commit is contained in:
parent
a4999bb665
commit
ef1af77dff
@ -12,6 +12,8 @@
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/line-md": "^1.1.24",
|
||||
"@iconify-json/mdi": "^1.1.50",
|
||||
"@skeletonlabs/skeleton": "^1.2.0",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-static": "^2.0.2",
|
||||
@ -30,6 +32,7 @@
|
||||
"tailwindcss": "^3.3.1",
|
||||
"tslib": "^2.5.0",
|
||||
"typescript": "^5.0.4",
|
||||
"unplugin-icons": "^0.16.1",
|
||||
"vite": "^4.2.1"
|
||||
},
|
||||
"type": "module",
|
||||
|
166
pnpm-lock.yaml
166
pnpm-lock.yaml
@ -9,6 +9,12 @@ dependencies:
|
||||
version: 2.0.5
|
||||
|
||||
devDependencies:
|
||||
'@iconify-json/line-md':
|
||||
specifier: ^1.1.24
|
||||
version: 1.1.24
|
||||
'@iconify-json/mdi':
|
||||
specifier: ^1.1.50
|
||||
version: 1.1.50
|
||||
'@skeletonlabs/skeleton':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
@ -63,12 +69,26 @@ devDependencies:
|
||||
typescript:
|
||||
specifier: ^5.0.4
|
||||
version: 5.0.4
|
||||
unplugin-icons:
|
||||
specifier: ^0.16.1
|
||||
version: 0.16.1
|
||||
vite:
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1
|
||||
|
||||
packages:
|
||||
|
||||
/@antfu/install-pkg@0.1.1:
|
||||
resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==}
|
||||
dependencies:
|
||||
execa: 5.1.1
|
||||
find-up: 5.0.0
|
||||
dev: true
|
||||
|
||||
/@antfu/utils@0.7.2:
|
||||
resolution: {integrity: sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==}
|
||||
dev: true
|
||||
|
||||
/@esbuild/android-arm64@0.17.16:
|
||||
resolution: {integrity: sha512-QX48qmsEZW+gcHgTmAj+x21mwTz8MlYQBnzF6861cNdQGvj2jzzFjqH0EBabrIa/WVZ2CHolwMoqxVryqKt8+Q==}
|
||||
engines: {node: '>=12'}
|
||||
@ -324,6 +344,35 @@ packages:
|
||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||
dev: true
|
||||
|
||||
/@iconify-json/line-md@1.1.24:
|
||||
resolution: {integrity: sha512-vHQnRZ3ZVDnrFoj8BMU0iTYR9404TrePP4UhCjkfOqkH4gibFoyM6JGO5OiIHv5m/GQvu4nteTICjklsRFUKpA==}
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
dev: true
|
||||
|
||||
/@iconify-json/mdi@1.1.50:
|
||||
resolution: {integrity: sha512-SgbT5w5eHCdOG74ZWPz7HlTGk6VsifIJhNi6lAsxj/5Nlqt6Cz4LlQmSa9eecU9p075Jub2aAx/o7YI+GCahRQ==}
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
dev: true
|
||||
|
||||
/@iconify/types@2.0.0:
|
||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||
dev: true
|
||||
|
||||
/@iconify/utils@2.1.5:
|
||||
resolution: {integrity: sha512-6MvDI+I6QMvXn5rK9KQGdpEE4mmLTcuQdLZEiX5N+uZB+vc4Yw9K1OtnOgkl8mp4d9X0UrILREyZgF1NUwUt+Q==}
|
||||
dependencies:
|
||||
'@antfu/install-pkg': 0.1.1
|
||||
'@antfu/utils': 0.7.2
|
||||
'@iconify/types': 2.0.0
|
||||
debug: 4.3.4
|
||||
kolorist: 1.8.0
|
||||
local-pkg: 0.4.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@ -1028,6 +1077,21 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/execa@5.1.1:
|
||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
get-stream: 6.0.1
|
||||
human-signals: 2.1.0
|
||||
is-stream: 2.0.1
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 4.0.1
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
dev: true
|
||||
|
||||
/fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
@ -1111,6 +1175,11 @@ packages:
|
||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||
dev: true
|
||||
|
||||
/get-stream@6.0.1:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -1194,6 +1263,11 @@ packages:
|
||||
function-bind: 1.1.1
|
||||
dev: true
|
||||
|
||||
/human-signals@2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
dev: true
|
||||
|
||||
/ignore@5.2.4:
|
||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||
engines: {node: '>= 4'}
|
||||
@ -1262,6 +1336,11 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-stream@2.0.1:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
@ -1295,6 +1374,10 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/kolorist@1.8.0:
|
||||
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
|
||||
dev: true
|
||||
|
||||
/levn@0.4.1:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -1312,6 +1395,11 @@ packages:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: true
|
||||
|
||||
/local-pkg@0.4.3:
|
||||
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
||||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/locate-path@6.0.0:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
@ -1344,6 +1432,10 @@ packages:
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
dev: true
|
||||
|
||||
/merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
dev: true
|
||||
|
||||
/merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -1363,6 +1455,11 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/min-indent@1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
@ -1435,6 +1532,13 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/npm-run-path@4.0.1:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
dev: true
|
||||
|
||||
/object-assign@4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1451,6 +1555,13 @@ packages:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/onetime@5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
dev: true
|
||||
|
||||
/optionator@0.9.1:
|
||||
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -1732,6 +1843,10 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/signal-exit@3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
dev: true
|
||||
|
||||
/sirv@2.0.2:
|
||||
resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==}
|
||||
engines: {node: '>= 10'}
|
||||
@ -1773,6 +1888,11 @@ packages:
|
||||
ansi-regex: 5.0.1
|
||||
dev: true
|
||||
|
||||
/strip-final-newline@2.0.0:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/strip-indent@3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2026,6 +2146,43 @@ packages:
|
||||
busboy: 1.6.0
|
||||
dev: true
|
||||
|
||||
/unplugin-icons@0.16.1:
|
||||
resolution: {integrity: sha512-qTunFUkpAyDnwzwV7YV1ZgCWRYfLuURcCurhhXOWMy2ipY88qx1pADvral2hJu4Xymh0X0t3Zcll3BIru2AVLQ==}
|
||||
peerDependencies:
|
||||
'@svgr/core': '>=7.0.0'
|
||||
'@vue/compiler-sfc': ^3.0.2 || ^2.7.0
|
||||
vue-template-compiler: ^2.6.12
|
||||
vue-template-es2015-compiler: ^1.9.0
|
||||
peerDependenciesMeta:
|
||||
'@svgr/core':
|
||||
optional: true
|
||||
'@vue/compiler-sfc':
|
||||
optional: true
|
||||
vue-template-compiler:
|
||||
optional: true
|
||||
vue-template-es2015-compiler:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@antfu/install-pkg': 0.1.1
|
||||
'@antfu/utils': 0.7.2
|
||||
'@iconify/utils': 2.1.5
|
||||
debug: 4.3.4
|
||||
kolorist: 1.8.0
|
||||
local-pkg: 0.4.3
|
||||
unplugin: 1.3.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/unplugin@1.3.1:
|
||||
resolution: {integrity: sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
chokidar: 3.5.3
|
||||
webpack-sources: 3.2.3
|
||||
webpack-virtual-modules: 0.5.0
|
||||
dev: true
|
||||
|
||||
/update-browserslist-db@1.0.10(browserslist@4.21.5):
|
||||
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
|
||||
hasBin: true
|
||||
@ -2091,6 +2248,15 @@ packages:
|
||||
vite: 4.2.1
|
||||
dev: true
|
||||
|
||||
/webpack-sources@3.2.3:
|
||||
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
dev: true
|
||||
|
||||
/webpack-virtual-modules@0.5.0:
|
||||
resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
|
||||
dev: true
|
||||
|
||||
/which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
4
src/app.d.ts
vendored
4
src/app.d.ts
vendored
@ -1,5 +1,7 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
/// <reference types="unplugin-icons/types/svelte" />
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
@ -9,4 +11,4 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
export { };
|
||||
|
10
src/comms.ts
10
src/comms.ts
@ -16,6 +16,8 @@ interface Message {
|
||||
type MessageType = 'request' | 'response' | 'broadcast';
|
||||
type RequestCallback = (arg0: Message | null) => void;
|
||||
|
||||
type Category = 'album' | 'artist' | 'album_artist' | 'genre' | 'playlist';
|
||||
|
||||
interface Callbacks {
|
||||
onDisconnect: (authenticated: boolean, reason: string) => void;
|
||||
onConnect: (initial: Message) => void;
|
||||
@ -111,9 +113,11 @@ export class MetadataCommunicator {
|
||||
id: t.id,
|
||||
track: {
|
||||
title: t.title,
|
||||
album_id: t.album_id,
|
||||
artist_id: t.artist_id,
|
||||
track_num: t.track,
|
||||
album_title: t.album,
|
||||
album_id: t.album_id,
|
||||
artist_name: t.artist,
|
||||
artist_id: t.artist_id,
|
||||
thumbnail_id: t.thumbnail_id,
|
||||
}
|
||||
})));
|
||||
@ -159,7 +163,7 @@ export class MetadataCommunicator {
|
||||
);
|
||||
}
|
||||
|
||||
onConnect(cb: () => void) {
|
||||
onConnect(cb: () => Promise<void>) {
|
||||
if (!this.isClosed() && this.authenticated) {
|
||||
cb();
|
||||
} else {
|
||||
|
@ -6,6 +6,6 @@
|
||||
$: isOnPage = href === $page.route.id;
|
||||
</script>
|
||||
|
||||
<a {href} class="btn {isOnPage ? 'variant-ghost-primary' : 'hover:variant-soft-primary'}">
|
||||
<a {href} class="btn p-2 px-3 {isOnPage ? 'variant-ghost-primary' : 'hover:variant-soft-primary'}">
|
||||
<slot />
|
||||
</a>
|
||||
|
@ -1,10 +1,14 @@
|
||||
<script>
|
||||
import Link from './a.svelte';
|
||||
import IconMusic from '~icons/mdi/music';
|
||||
import IconSettings from '~icons/mdi/settings';
|
||||
import IconArtist from '~icons/mdi/artist';
|
||||
import IconAlbum from '~icons/mdi/album';
|
||||
</script>
|
||||
|
||||
<nav class="flex">
|
||||
<Link href="/">t</Link>
|
||||
<Link href="/albums">a</Link>
|
||||
<Link href="/artists">a</Link>
|
||||
<Link href="/settings">s</Link>
|
||||
<Link href="/"><IconMusic class="w-7 h-7" /></Link>
|
||||
<Link href="/albums"><IconAlbum class="w-7 h-7" /></Link>
|
||||
<Link href="/artists"><IconArtist class="w-7 h-7" /></Link>
|
||||
<Link href="/settings"><IconSettings class="w-7 h-7" /></Link>
|
||||
</nav>
|
||||
|
@ -1,20 +1,42 @@
|
||||
<script lang="ts">
|
||||
import type { Track } from '../types';
|
||||
import { address, token } from '../stores';
|
||||
import Spinnny from '~icons/line-md/loading-loop';
|
||||
import IconPlay from '~icons/mdi/play';
|
||||
|
||||
export let track: Track;
|
||||
|
||||
$: url = `http://${$address}/thumbnail/${track.thumbnail_id}?token=${$token}`;
|
||||
let showSpinner = false;
|
||||
let isError = false;
|
||||
</script>
|
||||
|
||||
<div class="card flex gap-2">
|
||||
<div class="card flex gap-4 m-2 p-2 w-fit max-w-full">
|
||||
<button class="relative w-12 h-12 invisible hover:visible">
|
||||
<div class="visible rounded placeholder w-12 h-12" />
|
||||
<Spinnny class="absolute top-1 left-1 w-10 h-10 {showSpinner ? 'visible' : 'hidden'}" />
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<div class="rounded placeholder w-12 h-12">
|
||||
<img
|
||||
src={url}
|
||||
loading="lazy"
|
||||
class="w-12 h-12"
|
||||
on:error={(ev) => (ev.target.style.display = 'none')}
|
||||
class="absolute top-0 left-0 rounded w-12 h-12 {showSpinner || isError
|
||||
? 'hidden'
|
||||
: 'visible'}"
|
||||
on:error={() => {
|
||||
isError = true;
|
||||
showSpinner = false;
|
||||
}}
|
||||
on:loadstart={() => (showSpinner = true)}
|
||||
on:load={() => (showSpinner = false)}
|
||||
/>
|
||||
<IconPlay
|
||||
class="absolute top-0 left-0 w-12 h-12 rounded variant-glass-surface backdrop-blur-sm"
|
||||
/>
|
||||
</button>
|
||||
<div class="whitespace-nowrap overflow-ellipsis overflow-hidden">
|
||||
#{track.track_num} - {track.title}
|
||||
<div class="text-sm whitespace-nowrap overflow-ellipsis overflow-hidden">
|
||||
<span class="opacity-70">{track.album_title ? `from ${track.album_title}` : ''}</span>
|
||||
<span class="opacity-40">{track.artist_name ? `by ${track.artist_name}` : ''}</span>
|
||||
</div>
|
||||
</div>
|
||||
{track.track_num} - {track.title}
|
||||
</div>
|
||||
|
@ -34,15 +34,13 @@
|
||||
}
|
||||
});
|
||||
comm.connect($address, $token);
|
||||
comm.onConnect(() => {
|
||||
comm
|
||||
.fetchTracksCount()
|
||||
.then((count) => {
|
||||
comm.onConnect(async () => {
|
||||
const count = await comm.fetchTracksCount();
|
||||
|
||||
let remaining = count;
|
||||
console.log(count);
|
||||
while (remaining > 0) {
|
||||
const offset = count - remaining;
|
||||
comm.fetchTracks(500, offset).then((ts) => {
|
||||
const ts = await comm.fetchTracks(500, offset);
|
||||
tracks.update((map) => {
|
||||
ts.forEach((t) => map.set(t.id, t.track));
|
||||
return map;
|
||||
@ -51,11 +49,8 @@
|
||||
ts.forEach((t, index) => map.set(index + offset, t.id));
|
||||
return map;
|
||||
});
|
||||
});
|
||||
remaining -= 500;
|
||||
}
|
||||
})
|
||||
.catch(() => null);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -1,14 +1,27 @@
|
||||
<script lang="ts">
|
||||
import VirtualList from 'svelte-tiny-virtual-list';
|
||||
import { tracks, tracksSorted } from '../stores';
|
||||
import Track from '../components/track.svelte';
|
||||
import TrackComponent from '../components/track.svelte';
|
||||
import type { Track } from '../types';
|
||||
|
||||
$: trackCount = $tracksSorted.size;
|
||||
let trackItemSize = 60;
|
||||
let trackItemSize = 72;
|
||||
let listHeight = 0;
|
||||
|
||||
function getTrack(index: number): Track {
|
||||
return $tracks.get($tracksSorted.get(index)!)!;
|
||||
}
|
||||
</script>
|
||||
|
||||
<VirtualList height={trackCount * trackItemSize} itemSize={trackItemSize} itemCount={trackCount}>
|
||||
<div class="h-full" bind:offsetHeight={listHeight}>
|
||||
<VirtualList
|
||||
height={listHeight}
|
||||
itemSize={trackItemSize}
|
||||
itemCount={trackCount}
|
||||
overscanCount={1}
|
||||
>
|
||||
<div slot="item" let:index let:style {style}>
|
||||
<Track track={$tracks.get($tracksSorted.get(index) ?? BigInt(0))} />
|
||||
<div class="pr-4 md:ml-32"><TrackComponent track={getTrack(index)} /></div>
|
||||
</div>
|
||||
</VirtualList>
|
||||
</VirtualList>
|
||||
</div>
|
||||
|
@ -3,7 +3,9 @@ export type ResourceId = bigint;
|
||||
export interface Track {
|
||||
title: string,
|
||||
track_num: number,
|
||||
album_title: string,
|
||||
album_id: ResourceId,
|
||||
artist_name: string,
|
||||
artist_id: ResourceId,
|
||||
thumbnail_id: ResourceId,
|
||||
}
|
||||
@ -20,5 +22,4 @@ export interface Artist {
|
||||
export interface Album {
|
||||
title: string,
|
||||
artist_id: ResourceId,
|
||||
thumbnail_id: ResourceId,
|
||||
}
|
@ -1,6 +1,12 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()]
|
||||
plugins: [
|
||||
sveltekit(),
|
||||
Icons({
|
||||
compiler: 'svelte',
|
||||
})
|
||||
]
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user