From 098ac487ec7383d4121a225640b4edd0707a43fb Mon Sep 17 00:00:00 2001 From: Eclypsed Date: Mon, 29 Jan 2024 12:29:32 -0500 Subject: [PATCH] More components --- src/app.d.ts | 49 ++++++++ src/lib/components/navbar/navTab.svelte | 40 +++++++ src/lib/components/navbar/playlistTab.svelte | 38 +++++++ src/lib/components/util/navbarFoot.svelte | 80 ------------- src/lib/server/users.ts | 24 ++-- src/routes/(app)/+layout.svelte | 114 ++++++------------- src/routes/(app)/+layout.ts | 70 +++++------- 7 files changed, 206 insertions(+), 209 deletions(-) create mode 100644 src/lib/components/navbar/navTab.svelte create mode 100644 src/lib/components/navbar/playlistTab.svelte delete mode 100644 src/lib/components/util/navbarFoot.svelte diff --git a/src/app.d.ts b/src/app.d.ts index 19204d5..aa2c951 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -16,6 +16,55 @@ declare global { username: string password?: string } + + type ServiceType = 'jellyfin' | 'youtube-music' + + interface MediaItem { + connectionId: string + serviceType: string + id: string + name: string + duration: number + thumbnail: string + } + + interface Song extends MediaItem { + artists: { + id: string + name: string + }[] + album?: { + id: string + name: string + artists: { + id: string + name: string + }[] + } + audio: string + video?: string + releaseDate: string + } + + interface Album extends MediaItem { + artists: { + id: string + name: string + }[] + songs: Song[] + releaseDate: string + } + + interface Playlist extends MediaItem { + songs: Song[] + description?: string + } + + interface Artist { + id: string + name: string + // Add more here in the future + } } export {} diff --git a/src/lib/components/navbar/navTab.svelte b/src/lib/components/navbar/navTab.svelte new file mode 100644 index 0000000..2781c63 --- /dev/null +++ b/src/lib/components/navbar/navTab.svelte @@ -0,0 +1,40 @@ + + + + + + + \ No newline at end of file diff --git a/src/lib/components/navbar/playlistTab.svelte b/src/lib/components/navbar/playlistTab.svelte new file mode 100644 index 0000000..6becbff --- /dev/null +++ b/src/lib/components/navbar/playlistTab.svelte @@ -0,0 +1,38 @@ + + + + +
+ + {playlist.name} +
+ + \ No newline at end of file diff --git a/src/lib/components/util/navbarFoot.svelte b/src/lib/components/util/navbarFoot.svelte deleted file mode 100644 index bcc4649..0000000 --- a/src/lib/components/util/navbarFoot.svelte +++ /dev/null @@ -1,80 +0,0 @@ - - - - -
- {#each navTabs as tabData} - - {/each} - {#if navTabs.some((tab) => tab.pathname === currentPathname)} -
- {/if} -
- - diff --git a/src/lib/server/users.ts b/src/lib/server/users.ts index f1e523f..66c6649 100644 --- a/src/lib/server/users.ts +++ b/src/lib/server/users.ts @@ -15,9 +15,7 @@ type UserQueryParams = { includePassword?: boolean } -type ServiceType = 'jellyfin' | 'youtube-music' - -interface Service { +interface DBServiceData { id: string type: ServiceType userId: string @@ -31,10 +29,10 @@ interface DBServiceRow { url: string } -interface Connection { +interface DBConnectionData { id: string user: User - service: Service + service: DBServiceData accessToken: string refreshToken: string | null expiry: number | null @@ -81,13 +79,13 @@ export class Users { } export class Services { - static getService = (id: string): Service => { + static getService = (id: string): DBServiceData => { const { type, userId, url } = db.prepare('SELECT * FROM Users WHERE id = ?').get(id) as DBServiceRow - const service: Service = { id, type: type as ServiceType, userId, url: new URL(url) } + const service: DBServiceData = { id, type: type as ServiceType, userId, url: new URL(url) } return service } - static addService = (type: ServiceType, userId: string, url: URL): Service => { + static addService = (type: ServiceType, userId: string, url: URL): DBServiceData => { const serviceId = generateUUID() db.prepare('INSERT INTO Services(id, type, userId, url) VALUES(?, ?, ?, ?)').run(serviceId, type, userId, url.origin) return this.getService(serviceId) @@ -100,15 +98,15 @@ export class Services { } export class Connections { - static getConnection = (id: string): Connection => { + static getConnection = (id: string): DBConnectionData => { const { userId, serviceId, accessToken, refreshToken, expiry } = db.prepare('SELECT * FROM Connections WHERE id = ?').get(id) as DBConnectionRow - const connection: Connection = { id, user: Users.getUser(userId)!, service: Services.getService(serviceId), accessToken, refreshToken, expiry } + const connection: DBConnectionData = { id, user: Users.getUser(userId)!, service: Services.getService(serviceId), accessToken, refreshToken, expiry } return connection } - static getUserConnections = (userId: string): Connection[] => { + static getUserConnections = (userId: string): DBConnectionData[] => { const connectionRows = db.prepare('SELECT * FROM Connections WHERE userId = ?').all(userId) as DBConnectionRow[] - const connections: Connection[] = [] + const connections: DBConnectionData[] = [] const user = Users.getUser(userId)! connectionRows.forEach((row) => { const { id, serviceId, accessToken, refreshToken, expiry } = row @@ -117,7 +115,7 @@ export class Connections { return connections } - static addConnection = (userId: string, serviceId: string, accessToken: string, refreshToken: string | null, expiry: number | null): Connection => { + static addConnection = (userId: string, serviceId: string, accessToken: string, refreshToken: string | null, expiry: number | null): DBConnectionData => { const connectionId = generateUUID() db.prepare('INSERT INTO Connections(id, userId, serviceId, accessToken, refreshToken, expiry) VALUES(?, ?, ?, ?, ?, ?)').run(connectionId, userId, serviceId, accessToken, refreshToken, expiry) return this.getConnection(connectionId) diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index cb745d1..1111c42 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -3,8 +3,9 @@ import { goto, beforeNavigate } from '$app/navigation' import { pageWidth } from '$lib/stores' import type { LayoutData } from './$types' - import type { Tab } from './+layout' import { onMount } from 'svelte' + import NavTabComponent, { type NavTab } from '$lib/components/navbar/navTab.svelte' + import PlaylistTabComponent, { type PlaylistTab } from '$lib/components/navbar/playlistTab.svelte' export let data: LayoutData @@ -21,81 +22,55 @@ return (pathname.startsWith(rootPathname) && rootPathname !== '/') || (pathname === '/' && rootPathname === '/') } - const calculateDirection = (newTab: Tab): void => { - const newTabIndex = data.tabs.findIndex((tab) => tab === newTab) - directionMultiplier = newTabIndex > currentTabIndex ? -1 : 1 - currentTabIndex = newTabIndex - } + // const calculateDirection = (newTab: Tab): void => { + // const newTabIndex = data.tabs.findIndex((tab) => tab === newTab) + // directionMultiplier = newTabIndex > currentTabIndex ? -1 : 1 + // currentTabIndex = newTabIndex + // } - const navigate = (newPathname: string): void => { - const newTabIndex = data.tabs.findIndex((tab) => inPathnameHeirarchy(newPathname, tab.pathname)) + // const navigate = (newPathname: string): void => { + // const newTabIndex = data.tabs.findIndex((tab) => inPathnameHeirarchy(newPathname, tab.pathname)) - if (newTabIndex < 0) indicatorBar.style.opacity = '0' + // if (newTabIndex < 0) indicatorBar.style.opacity = '0' - const newTab = data.tabs[newTabIndex] - if (!newTab?.button) return + // const newTab = data.tabs[newTabIndex] + // if (!newTab?.button) return - const tabRec = newTab.button.getBoundingClientRect(), - listRect = tabList.getBoundingClientRect() + // const tabRec = newTab.button.getBoundingClientRect(), + // listRect = tabList.getBoundingClientRect() - const shiftTop = () => (indicatorBar.style.top = `${tabRec.top - listRect.top}px`), - shiftBottom = () => (indicatorBar.style.bottom = `${listRect.bottom - tabRec.bottom}px`) + // const shiftTop = () => (indicatorBar.style.top = `${tabRec.top - listRect.top}px`), + // shiftBottom = () => (indicatorBar.style.bottom = `${listRect.bottom - tabRec.bottom}px`) - if (directionMultiplier > 0) { - shiftTop() - setTimeout(shiftBottom, pageTransitionTime) - } else { - shiftBottom() - setTimeout(shiftTop, pageTransitionTime) - } + // if (directionMultiplier > 0) { + // shiftTop() + // setTimeout(shiftBottom, pageTransitionTime) + // } else { + // shiftBottom() + // setTimeout(shiftTop, pageTransitionTime) + // } - setTimeout(() => (indicatorBar.style.opacity = '100%'), pageTransitionTime + 300) - } + // setTimeout(() => (indicatorBar.style.opacity = '100%'), pageTransitionTime + 300) + // } - onMount(() => setTimeout(() => navigate(data.url.pathname))) // More stupid fucking non-blocking event loop shit - beforeNavigate(({ to }) => { - if (to) navigate(to.url.pathname) - }) + // onMount(() => setTimeout(() => navigate(data.url.pathname))) // More stupid fucking non-blocking event loop shit + // beforeNavigate(({ to }) => { + // if (to) navigate(to.url.pathname) + // }) {#if $pageWidth >= 768}
-
+
- {#each data.tabs.filter((tab) => tab.type === 'nav') as nav, index} - + {#each data.navTabs as nav} + {/each} -
+
-
- {#each data.tabs.filter((tab) => tab.type === 'playlist') as playlist} -
- - {playlist.name} -
+
+ {#each data.playlistTabs as playlist} + {/each}
@@ -138,19 +113,4 @@ /> -->
-{/if} - - +{/if} \ No newline at end of file diff --git a/src/routes/(app)/+layout.ts b/src/routes/(app)/+layout.ts index ec78f46..3d5f127 100644 --- a/src/routes/(app)/+layout.ts +++ b/src/routes/(app)/+layout.ts @@ -1,91 +1,83 @@ import type { LayoutLoad } from './$types' - -export interface Tab { - type: 'nav' | 'playlist' - pathname: string - name: string - icon: string - button?: HTMLButtonElement -} +import type { NavTab } from '$lib/components/navbar/navTab.svelte' +import type { PlaylistTab } from '$lib/components/navbar/playlistTab.svelte' export const load: LayoutLoad = () => { - const navTabs: Tab[] = [ + const navTabs: NavTab[] = [ { - type: 'nav', pathname: '/', name: 'Home', icon: 'fa-solid fa-house', }, { - type: 'nav', pathname: '/user', name: 'User', icon: 'fa-solid fa-user', // This would be a cool spot for a user-uploaded pfp }, { - type: 'nav', pathname: '/search', name: 'Search', icon: 'fa-solid fa-search', }, { - type: 'nav', pathname: '/library', name: 'Libray', icon: 'fa-solid fa-bars-staggered', }, ] - const playlistTabs: Tab[] = [ + const playlistTabs: PlaylistTab[] = [ { - type: 'playlist', - pathname: '/library?playlist=AD:TRANCE 10', + id: 'AD:TRANCE 10', name: 'AD:TRANCE 10', - icon: 'https://www.diverse.direct/wp/wp-content/uploads/470_artwork.jpg', + thumbnail: 'https://www.diverse.direct/wp/wp-content/uploads/470_artwork.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=Fionaredica', + id: 'Fionaredica', name: 'Fionaredica', - icon: 'https://f4.bcbits.com/img/a2436961975_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a2436961975_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=Machinate', + id: 'Machinate', name: 'Machinate', - icon: 'https://f4.bcbits.com/img/a3587136348_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a3587136348_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=MAGGOD', + id: 'MAGGOD', name: 'MAGGOD', - icon: 'https://f4.bcbits.com/img/a3641603617_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a3641603617_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=The Requiem', + id: 'The Requiem', name: 'The Requiem', - icon: 'https://f4.bcbits.com/img/a2458067285_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a2458067285_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=IRREPARABLE HARDCORE IS BACK 2 -Horai Gekka-', + id: 'IRREPARABLE HARDCORE IS BACK 2 -Horai Gekka-', name: 'IRREPARABLE HARDCORE IS BACK 2 -Horai Gekka-', - icon: 'https://f4.bcbits.com/img/a1483629734_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a1483629734_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=妄殺オタクティクス', + id: '妄殺オタクティクス', name: '妄殺オタクティクス', - icon: 'https://f4.bcbits.com/img/a1653481367_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a1653481367_10.jpg', }, { - type: 'playlist', - pathname: '/library?playlist=Collapse', + id: 'Collapse', name: 'Collapse', - icon: 'https://f4.bcbits.com/img/a0524413952_10.jpg', + thumbnail: 'https://f4.bcbits.com/img/a0524413952_10.jpg', + }, + { + id: 'Fleurix', + name: 'Fleurix', + thumbnail: 'https://f4.bcbits.com/img/a1856993876_10.jpg', + }, + { + id: '天​才​失​格 -No Longer Prodigy-', + name: '天​才​失​格 -No Longer Prodigy-', + thumbnail: 'https://f4.bcbits.com/img/a2186643420_10.jpg', }, ] - return { tabs: navTabs.concat(playlistTabs) } + return { navTabs, playlistTabs } }