diff --git a/src/app.css b/src/app.css
index e383a5e..db7b98e 100644
--- a/src/app.css
+++ b/src/app.css
@@ -38,7 +38,7 @@
--youtube-red: #ff0000;
}
-@media screen and (max-width: 640px) {
+@media screen and (max-width: 768px) {
:root {
font-size: 0.7rem;
}
diff --git a/src/lib/components/media/mediaCard.svelte b/src/lib/components/media/mediaCard.svelte
index a5a7b29..c341646 100644
--- a/src/lib/components/media/mediaCard.svelte
+++ b/src/lib/components/media/mediaCard.svelte
@@ -3,7 +3,7 @@
import Services from '$lib/services.json'
import IconButton from '$lib/components/utility/iconButton.svelte'
- import { backgroundImage } from '$lib/utils/stores.js'
+ import { backgroundImage, currentlyPlaying } from '$lib/utils/stores.js'
const iconClasses = {
song: 'fa-solid fa-music',
@@ -19,7 +19,7 @@
const x = (2 * (event.x - cardRect.left)) / cardRect.width - 1 // These are simplified calculations to find the x-y coords relative to the center of the card
const y = (2 * (cardRect.top - event.y)) / cardRect.height + 1
- let angle = Math.atan(x / y) // You'd think it should be y / x but it's actually the inverse
+ const angle = Math.atan(x / y) // You'd think it should be y / x but it's actually the inverse
const distanceFromCorner = Math.sqrt((x - 1) ** 2 + (y - 1) ** 2) // This is a cool little trick, the -1 on the x an y coordinate is effective the same as saying "make the origin of the glare [1, 1]"
cardGlare.style.backgroundImage = `linear-gradient(${angle}rad, transparent ${distanceFromCorner * 50 + 50}%, rgba(255, 255, 255, 0.1) ${distanceFromCorner * 50 + 60}%, transparent 100%)`
@@ -40,7 +40,12 @@
{/if}
- ($backgroundImage = mediaData.image)}>
+ {
+ $currentlyPlaying = mediaData
+ $backgroundImage = mediaData.image
+ }}
+ >
diff --git a/src/lib/components/media/miniPlayer.svelte b/src/lib/components/media/miniPlayer.svelte
new file mode 100644
index 0000000..49ece70
--- /dev/null
+++ b/src/lib/components/media/miniPlayer.svelte
@@ -0,0 +1,102 @@
+
+
+{#if song}
+
+ {#if displayMode === 'vertical'}
+
Vertical Mode
+ {:else}
+
+
+
+
+
{song.name}
+
{Array.from(song.artists, (artist) => artist.name).join(', ')}
+
+ (songLiked = !songLiked)}>
+ {#if songLiked}
+
+ {:else}
+
+ {/if}
+
+
+
+
+
+
+
+
+
+ ($currentlyPlaying = null)}>
+
+
+
+
+
+
+
+
+ {
+ volume = event.detail.value
+ setVolume(volume)
+ }}
+ />
+ {
+ if (volume > 0) {
+ volume = 0
+ } else {
+ volume = getVolume()
+ }
+ volumeSlider.setValue(volume)
+ }}
+ >
+
+
+
+
+
+
+
+
+ {/if}
+
+{/if}
+
+
diff --git a/src/lib/components/media/scrollableCardMenu.svelte b/src/lib/components/media/scrollableCardMenu.svelte
index 7bdde29..fc7ef94 100644
--- a/src/lib/components/media/scrollableCardMenu.svelte
+++ b/src/lib/components/media/scrollableCardMenu.svelte
@@ -6,7 +6,12 @@
import IconButton from '$lib/components/utility/iconButton.svelte'
let scrollable,
+ scrollableWidth,
+ isScrollable = false,
scrollpos = 0
+
+ $: isScrollable = scrollable?.scrollWidth > scrollableWidth
+ $: scrollpos = scrollable?.scrollLeft / (scrollable?.scrollWidth - scrollableWidth)
@@ -15,16 +20,17 @@
{header}
{/if}
- (scrollable.scrollLeft -= scrollable.clientWidth)}>
+ (scrollable.scrollLeft -= scrollable.clientWidth)}>
- 0.99} on:click={() => (scrollable.scrollLeft += scrollable.clientWidth)}>
+ 0.99 || !isScrollable} on:click={() => (scrollable.scrollLeft += scrollable.clientWidth)}>
(scrollpos = scrollable.scrollLeft / (scrollable.scrollWidth - scrollable.clientWidth))}
class="no-scrollbar flex gap-6 overflow-y-hidden overflow-x-scroll scroll-smooth py-4"
>
diff --git a/src/lib/components/utility/footer.svelte b/src/lib/components/utility/footer.svelte
new file mode 100644
index 0000000..0c7830e
--- /dev/null
+++ b/src/lib/components/utility/footer.svelte
@@ -0,0 +1,12 @@
+
+
+
diff --git a/src/lib/components/utility/navbar.svelte b/src/lib/components/utility/navbar.svelte
index 532e6e7..9f3fe3d 100644
--- a/src/lib/components/utility/navbar.svelte
+++ b/src/lib/components/utility/navbar.svelte
@@ -2,46 +2,35 @@
import IconButton from './iconButton.svelte'
import { goto } from '$app/navigation'
import { page } from '$app/stores'
-
- let windowY = 0
-
-
0}>
+
-
-
+ goto('/settings')}>
+
{#if $page.url.pathname !== '/'}
- goto('/')}>
-
-
history.back()}>
{/if}
-
diff --git a/src/routes/mediaDataSchema.json b/src/lib/mediaDataSchema.json
similarity index 100%
rename from src/routes/mediaDataSchema.json
rename to src/lib/mediaDataSchema.json
diff --git a/src/lib/utils/stores.js b/src/lib/utils/stores.js
index f000ee2..881d959 100644
--- a/src/lib/utils/stores.js
+++ b/src/lib/utils/stores.js
@@ -1,5 +1,9 @@
import { writable } from 'svelte/store'
+export const pageWidth = writable(null)
+
export const newestAlert = writable([null, null])
+export const currentlyPlaying = writable(null)
+
export const backgroundImage = writable(null)
diff --git a/src/lib/utils/utils.js b/src/lib/utils/utils.js
index 36bffed..e7f5c99 100644
--- a/src/lib/utils/utils.js
+++ b/src/lib/utils/utils.js
@@ -1,22 +1,16 @@
import Joi from 'joi'
-export const ticksToTime = (ticks) => {
- const totalSeconds = ~~(ticks / 10000000)
- const totalMinutes = ~~(totalSeconds / 60)
- const hours = ~~(totalMinutes / 60)
+export const getVolume = () => {
+ const currentVolume = localStorage.getItem('volume')
+ if (currentVolume) return currentVolume
- const remainderMinutes = totalMinutes - hours * 60
- const remainderSeconds = totalSeconds - totalMinutes * 60
+ const defaultVolume = 100
+ localStorage.setItem('volume', defaultVolume)
+ return defaultVolume
+}
- const format = (value) => {
- return value < 10 ? `0${value}` : value
- }
-
- if (hours > 0) {
- return `${hours}:${format(remainderMinutes)}:${format(remainderSeconds)}`
- } else {
- return `${remainderMinutes}:${format(remainderSeconds)}`
- }
+export const setVolume = (volume) => {
+ if (Number.isFinite(volume)) localStorage.setItem('volume', Math.round(volume))
}
export class JellyfinUtils {
diff --git a/src/routes/(app)/+layout.js b/src/routes/(app)/+layout.js
new file mode 100644
index 0000000..547f579
--- /dev/null
+++ b/src/routes/(app)/+layout.js
@@ -0,0 +1,6 @@
+/** @type {import('./$types').LayoutLoad} */
+export const load = ({ url }) => {
+ return {
+ url: url.pathname,
+ }
+}
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
new file mode 100644
index 0000000..b654257
--- /dev/null
+++ b/src/routes/(app)/+layout.svelte
@@ -0,0 +1,111 @@
+
+
+
+ {#if $pageWidth > 768}
+
+
+ {#each Object.entries(contentTabs) as [page, tabData]}
+ {#if data.url === page}
+ {tabData.header}
+ {:else}
+ {tabData.header}
+ {/if}
+ {/each}
+ {#if data.url in contentTabs}
+
+ {/if}
+
+
+ {:else}
+
+ {/if}
+
+ {#key previousPage}
+
+
+
+ {/key}
+
+ 768 ? 'horizontal' : 'vertical'} />
+
+
+ {#if $pageWidth < 768}
+
+
+
+ {#each Object.entries(contentTabs) as [page, tabData]}
+ {#if data.url === page}
+
+ {:else}
+
+ {/if}
+ {/each}
+ {#if data.url in contentTabs}
+
+ {/if}
+
+
+
+ {/if}
+
diff --git a/src/routes/+page.server.js b/src/routes/(app)/+page.server.js
similarity index 100%
rename from src/routes/+page.server.js
rename to src/routes/(app)/+page.server.js
diff --git a/src/routes/+page.svelte b/src/routes/(app)/+page.svelte
similarity index 100%
rename from src/routes/+page.svelte
rename to src/routes/(app)/+page.svelte
diff --git a/src/routes/album/[id]/+page.server.js b/src/routes/(app)/album/[id]/+page.server.js
similarity index 100%
rename from src/routes/album/[id]/+page.server.js
rename to src/routes/(app)/album/[id]/+page.server.js
diff --git a/src/routes/album/[id]/+page.svelte b/src/routes/(app)/album/[id]/+page.svelte
similarity index 100%
rename from src/routes/album/[id]/+page.svelte
rename to src/routes/(app)/album/[id]/+page.svelte
diff --git a/src/routes/artist/+page.server.js b/src/routes/(app)/artist/+page.server.js
similarity index 100%
rename from src/routes/artist/+page.server.js
rename to src/routes/(app)/artist/+page.server.js
diff --git a/src/routes/artist/+page.svelte b/src/routes/(app)/artist/+page.svelte
similarity index 100%
rename from src/routes/artist/+page.svelte
rename to src/routes/(app)/artist/+page.svelte
diff --git a/src/routes/details/+page.svelte b/src/routes/(app)/details/+page.svelte
similarity index 100%
rename from src/routes/details/+page.svelte
rename to src/routes/(app)/details/+page.svelte
diff --git a/src/routes/library/+page.svelte b/src/routes/(app)/library/+page.svelte
similarity index 100%
rename from src/routes/library/+page.svelte
rename to src/routes/(app)/library/+page.svelte
diff --git a/src/routes/playlist/+page.svelte b/src/routes/(app)/playlist/+page.svelte
similarity index 100%
rename from src/routes/playlist/+page.svelte
rename to src/routes/(app)/playlist/+page.svelte
diff --git a/src/routes/settings/+layout.svelte b/src/routes/(settings)/settings/+layout.svelte
similarity index 94%
rename from src/routes/settings/+layout.svelte
rename to src/routes/(settings)/settings/+layout.svelte
index 06d90cb..237a2dd 100644
--- a/src/routes/settings/+layout.svelte
+++ b/src/routes/(settings)/settings/+layout.svelte
@@ -17,7 +17,7 @@
}
-
+
diff --git a/src/routes/settings/+page.svelte b/src/routes/(settings)/settings/+page.svelte
similarity index 100%
rename from src/routes/settings/+page.svelte
rename to src/routes/(settings)/settings/+page.svelte
diff --git a/src/routes/settings/connections/+page.server.js b/src/routes/(settings)/settings/connections/+page.server.js
similarity index 100%
rename from src/routes/settings/connections/+page.server.js
rename to src/routes/(settings)/settings/connections/+page.server.js
diff --git a/src/routes/settings/connections/+page.svelte b/src/routes/(settings)/settings/connections/+page.svelte
similarity index 100%
rename from src/routes/settings/connections/+page.svelte
rename to src/routes/(settings)/settings/connections/+page.svelte
diff --git a/src/routes/settings/connections/jellyfinAuthBox.svelte b/src/routes/(settings)/settings/connections/jellyfinAuthBox.svelte
similarity index 100%
rename from src/routes/settings/connections/jellyfinAuthBox.svelte
rename to src/routes/(settings)/settings/connections/jellyfinAuthBox.svelte
diff --git a/src/routes/settings/connections/userDataSchemaRef.json b/src/routes/(settings)/settings/connections/userDataSchemaRef.json
similarity index 100%
rename from src/routes/settings/connections/userDataSchemaRef.json
rename to src/routes/(settings)/settings/connections/userDataSchemaRef.json
diff --git a/src/routes/+layout.server.js b/src/routes/+layout.server.js
deleted file mode 100644
index f8041e5..0000000
--- a/src/routes/+layout.server.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export const trailingSlash = 'never'
-
-/** @type {import('./$types').PageServerLoad} */
-export const load = ({ url }) => {
- return {
- url: url.pathname,
- }
-}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index ef66c1b..4abe79b 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -2,13 +2,10 @@
import '../app.css'
import '@fortawesome/fontawesome-free/css/all.min.css'
import AlertBox from '$lib/components/utility/alertBox.svelte'
- import SubLayouts from './subLayouts.svelte'
- import { newestAlert, backgroundImage } from '$lib/utils/stores.js'
+ import { newestAlert, backgroundImage, pageWidth } from '$lib/utils/stores.js'
import { fade } from 'svelte/transition'
import { onMount } from 'svelte'
- export let data
-
let alertBox
$: addAlert($newestAlert)
@@ -22,6 +19,7 @@
onMount(() => (loaded = true))
+
@@ -33,9 +31,7 @@
{/key}
{/if}
-
-
-
+
diff --git a/src/routes/subLayouts.svelte b/src/routes/subLayouts.svelte
deleted file mode 100644
index 28f356e..0000000
--- a/src/routes/subLayouts.svelte
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-{#if Object.values(contentTabs).includes(currentPage)}
-
-
-
- {#each Object.entries(contentTabs) as [header, page]}
- {#if currentPage === page}
- {header}
- {:else}
- {header}
- {/if}
- {/each}
-
-
-
-
- {#key previousPage}
-
-
-
- {/key}
-
-{:else}
-
-{/if}
diff --git a/src/routes/youtube-music/+page.server.js b/src/routes/youtube-music/+page.server.js
deleted file mode 100644
index de2bb88..0000000
--- a/src/routes/youtube-music/+page.server.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const prerender = false
-export const ssr = false
-
-/** @type {import('./$types').PageLoad} */
-export async function load() {}
diff --git a/src/routes/youtube-music/+page.svelte b/src/routes/youtube-music/+page.svelte
deleted file mode 100644
index 7107e07..0000000
--- a/src/routes/youtube-music/+page.svelte
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-