Project refactoring
8
package-lock.json
generated
@@ -25,7 +25,7 @@
|
|||||||
"hls.js": "^1.4.14",
|
"hls.js": "^1.4.14",
|
||||||
"openapi-fetch": "^0.8.2",
|
"openapi-fetch": "^0.8.2",
|
||||||
"openapi-typescript": "^6.7.3",
|
"openapi-typescript": "^6.7.3",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.35",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"prettier-plugin-svelte": "^2.10.1",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
"radix-icons-svelte": "^1.2.1",
|
"radix-icons-svelte": "^1.2.1",
|
||||||
@@ -5084,9 +5084,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.32",
|
"version": "8.4.35",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
|
||||||
"integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
|
"integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|||||||
11
package.json
@@ -11,6 +11,7 @@
|
|||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"build:tizen": "vite build --outDir tizen/dist",
|
"build:tizen": "vite build --outDir tizen/dist",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
|
"preview:tizen": "vite build --outDir tizen/dist && vite preview --outDir tizen/dist",
|
||||||
"deploy": "PORT=9494 NODE_ENV=production node build/",
|
"deploy": "PORT=9494 NODE_ENV=production node build/",
|
||||||
"deploy:electron": "vite build && electron-builder -mw --x64 --config build.config.json; electron-builder -m --arm64 --config build.config.json",
|
"deploy:electron": "vite build && electron-builder -mw --x64 --config build.config.json; electron-builder -m --arm64 --config build.config.json",
|
||||||
"test": "playwright test",
|
"test": "playwright test",
|
||||||
@@ -21,10 +22,8 @@
|
|||||||
"format": "prettier --plugin-search-dir . --write ."
|
"format": "prettier --plugin-search-dir . --write ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.28.1",
|
|
||||||
"vitest": "^0.25.3",
|
|
||||||
"reflect-metadata": "^0.1.13",
|
|
||||||
"@jellyfin/sdk": "^0.8.2",
|
"@jellyfin/sdk": "^0.8.2",
|
||||||
|
"@playwright/test": "^1.28.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
||||||
"@tsconfig/svelte": "^5.0.2",
|
"@tsconfig/svelte": "^5.0.2",
|
||||||
"@types/axios": "^0.14.0",
|
"@types/axios": "^0.14.0",
|
||||||
@@ -40,10 +39,11 @@
|
|||||||
"hls.js": "^1.4.14",
|
"hls.js": "^1.4.14",
|
||||||
"openapi-fetch": "^0.8.2",
|
"openapi-fetch": "^0.8.2",
|
||||||
"openapi-typescript": "^6.7.3",
|
"openapi-typescript": "^6.7.3",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.35",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"prettier-plugin-svelte": "^2.10.1",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
"radix-icons-svelte": "^1.2.1",
|
"radix-icons-svelte": "^1.2.1",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
"svelte": "^3.59.1",
|
"svelte": "^3.59.1",
|
||||||
"svelte-check": "^3.6.2",
|
"svelte-check": "^3.6.2",
|
||||||
"svelte-i18n": "^4.0.0",
|
"svelte-i18n": "^4.0.0",
|
||||||
@@ -54,7 +54,8 @@
|
|||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "^4.5.1",
|
"vite": "^4.5.1",
|
||||||
"vite-plugin-singlefile": "^0.13.5"
|
"vite-plugin-singlefile": "^0.13.5",
|
||||||
|
"vitest": "^0.25.3"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|||||||
11
postcss.config.js
Normal file → Executable file
@@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {}
|
||||||
},
|
// 'flex-gap-polyfill': {}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { handleKeyboardNavigation, Selectable } from './lib/selectable';
|
import { handleKeyboardNavigation, Selectable } from './lib/selectable';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import Container from './Container.svelte';
|
import Container from './Container.svelte';
|
||||||
import NavbarItem from './lib/components-new/NavbarItem.svelte';
|
import NavbarItem from './lib/components/NavbarItem.svelte';
|
||||||
import { Bookmark, CardStack, Gear, Laptop, MagnifyingGlass } from 'radix-icons-svelte';
|
import { Bookmark, CardStack, Gear, Laptop, MagnifyingGlass } from 'radix-icons-svelte';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { Readable } from 'svelte/store';
|
import type { Readable } from 'svelte/store';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import IconButton from '../IconButton.svelte';
|
import IconButton from '../IconButton.svelte';
|
||||||
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
|
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Container from '../../../Container.svelte';
|
import type { Registerer } from '../../selectable';
|
||||||
|
|
||||||
export let gradientFromColor = 'from-stone-950';
|
export let gradientFromColor = 'from-stone-950';
|
||||||
export let heading = '';
|
export let heading = '';
|
||||||
@@ -44,19 +44,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<Container horizontal>
|
<div
|
||||||
<div
|
class={classNames(
|
||||||
class={classNames(
|
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
|
||||||
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
|
scrollClass
|
||||||
scrollClass
|
)}
|
||||||
)}
|
bind:this={carousel}
|
||||||
bind:this={carousel}
|
tabindex="-1"
|
||||||
tabindex="-1"
|
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
|
||||||
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
|
>
|
||||||
>
|
<slot />
|
||||||
<slot />
|
</div>
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
{#if scrollX > 50}
|
{#if scrollX > 50}
|
||||||
<div
|
<div
|
||||||
transition:fade={{ duration: 200 }}
|
transition:fade={{ duration: 200 }}
|
||||||
29
src/lib/components-old/Lang/I18n.svelte
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { addMessages, init, locale } from 'svelte-i18n';
|
||||||
|
|
||||||
|
import de from '../../lang/de.json';
|
||||||
|
import en from '../../lang/en.json';
|
||||||
|
import es from '../../lang/es.json';
|
||||||
|
import fr from '../../lang/fr.json';
|
||||||
|
import it from '../../lang/it.json';
|
||||||
|
import { settings } from '../../stores/settings.store';
|
||||||
|
|
||||||
|
addMessages('de', de);
|
||||||
|
addMessages('en', en);
|
||||||
|
addMessages('es', es);
|
||||||
|
addMessages('fr', fr);
|
||||||
|
addMessages('it', it);
|
||||||
|
|
||||||
|
settings.subscribe((value) => {
|
||||||
|
if (value.language) {
|
||||||
|
locale.set(value.language);
|
||||||
|
} else {
|
||||||
|
locale.set('en');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
init({
|
||||||
|
initialLocale: $settings.language,
|
||||||
|
fallbackLocale: 'en'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { TriangleRight } from 'radix-icons-svelte';
|
import { TriangleRight } from 'radix-icons-svelte';
|
||||||
|
import IconButton from './IconButton.svelte';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 309 B |
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 867 B |
|
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 684 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 697 B After Width: | Height: | Size: 697 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 382 B |
|
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 448 B |
@@ -1,23 +1,23 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
export let index = 0;
|
export let index = 0;
|
||||||
export let size: 'dynamic' | 'md' | 'lg' = 'md';
|
export let size: 'dynamic' | 'md' | 'lg' = 'md';
|
||||||
export let orientation: 'portrait' | 'landscape' = 'landscape';
|
export let orientation: 'portrait' | 'landscape' = 'landscape';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={classNames('rounded-xl overflow-hidden shadow-lg placeholder shrink-0', {
|
class={classNames('rounded-xl overflow-hidden shadow-lg placeholder shrink-0', {
|
||||||
'aspect-video': orientation === 'landscape',
|
'aspect-video': orientation === 'landscape',
|
||||||
'aspect-[2/3]': orientation === 'portrait',
|
'aspect-[2/3]': orientation === 'portrait',
|
||||||
'w-44': size === 'md' && orientation === 'portrait',
|
'w-44': size === 'md' && orientation === 'portrait',
|
||||||
'h-44': size === 'md' && orientation === 'landscape',
|
'h-44': size === 'md' && orientation === 'landscape',
|
||||||
'w-60': size === 'lg' && orientation === 'portrait',
|
'w-60': size === 'lg' && orientation === 'portrait',
|
||||||
'h-60': size === 'lg' && orientation === 'landscape',
|
'h-60': size === 'lg' && orientation === 'landscape',
|
||||||
'w-full': size === 'dynamic'
|
'w-full': size === 'dynamic'
|
||||||
})}
|
})}
|
||||||
style={'animation-delay: ' + ((index * 100) % 2000) + 'ms;'}
|
style={'animation-delay: ' + ((index * 100) % 2000) + 'ms;'}
|
||||||
transition:fade|global
|
transition:fade|global
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import IconButton from '../IconButton.svelte';
|
import IconButton from '../IconButton.svelte';
|
||||||
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
|
import { ChevronLeft, ChevronRight } from 'radix-icons-svelte';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { Registerer } from '../../selectable';
|
import Container from '../../../Container.svelte';
|
||||||
|
|
||||||
export let gradientFromColor = 'from-stone-950';
|
export let gradientFromColor = 'from-stone-950';
|
||||||
export let heading = '';
|
export let heading = '';
|
||||||
@@ -44,17 +44,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div
|
<Container horizontal>
|
||||||
class={classNames(
|
<div
|
||||||
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
|
class={classNames(
|
||||||
scrollClass
|
'flex overflow-x-scroll items-center overflow-y-visible gap-4 relative scrollbar-hide p-1',
|
||||||
)}
|
scrollClass
|
||||||
bind:this={carousel}
|
)}
|
||||||
tabindex="-1"
|
bind:this={carousel}
|
||||||
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
|
tabindex="-1"
|
||||||
>
|
on:scroll={() => (scrollX = carousel?.scrollLeft || scrollX)}
|
||||||
<slot />
|
>
|
||||||
</div>
|
<slot />
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
{#if scrollX > 50}
|
{#if scrollX > 50}
|
||||||
<div
|
<div
|
||||||
transition:fade={{ duration: 200 }}
|
transition:fade={{ duration: 200 }}
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useNavigate } from 'svelte-navigator';
|
import { useNavigate } from 'svelte-navigator';
|
||||||
import { type Readable } from 'svelte/store';
|
import { type Readable } from 'svelte/store';
|
||||||
import Container from '../../Container.svelte';
|
import Container from '../../Container.svelte';
|
||||||
|
|
||||||
export let to: string;
|
export let to: string;
|
||||||
let hasFocus: Readable<boolean>;
|
let hasFocus: Readable<boolean>;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
navigate(to);
|
navigate(to);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container tag="button" on:click={handleClick} bind:hasFocus>
|
<Container tag="button" on:click={handleClick} bind:hasFocus>
|
||||||
<div
|
<div
|
||||||
class={classNames('flex items-center my-2', {
|
class={classNames('flex items-center my-2', {
|
||||||
'text-amber-200': $hasFocus
|
'text-amber-200': $hasFocus
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<slot name="icon" />
|
<slot name="icon" />
|
||||||
<slot name="text" />
|
<slot name="text" />
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { TriangleRight } from 'radix-icons-svelte';
|
import { TriangleRight } from 'radix-icons-svelte';
|
||||||
import IconButton from './IconButton.svelte';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import Carousel from '../components/Carousel/Carousel.svelte';
|
import Carousel from '../components/Carousel/Carousel.svelte';
|
||||||
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
|
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
|
||||||
import Container from '../../Container.svelte';
|
import Container from '../../Container.svelte';
|
||||||
import type { Readable } from 'svelte/store';
|
|
||||||
|
|
||||||
settings.update((prev) => ({
|
settings.update((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -20,15 +19,11 @@
|
|||||||
jellyfinItemsStore.subscribe((items) => {
|
jellyfinItemsStore.subscribe((items) => {
|
||||||
console.warn('GOT ITEMS', items.data);
|
console.warn('GOT ITEMS', items.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
let focusIndex: Readable<number>;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Container focusOnMount>
|
<Container focusOnMount>
|
||||||
<div>LibraryPage</div>
|
<div>LibraryPage</div>
|
||||||
<Container horizontal bind:focusIndex>
|
<Carousel>
|
||||||
<Carousel>
|
<CarouselPlaceholderItems />
|
||||||
<CarouselPlaceholderItems {focusIndex} />
|
</Carousel>
|
||||||
</Carousel>
|
|
||||||
</Container>
|
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
import { settings } from '../stores/settings.store';
|
import { settings } from '../stores/settings.store';
|
||||||
import type { TitleType } from '../types';
|
import type { TitleType } from '../types';
|
||||||
import type { ComponentProps } from 'svelte';
|
import type { ComponentProps } from 'svelte';
|
||||||
import Poster from '../components-new/Poster.svelte';
|
import Poster from '../components/Poster.svelte';
|
||||||
import type { JellyfinItem } from '../apis/jellyfin/jellyfinApi';
|
import type { JellyfinItem } from '../apis/jellyfin/jellyfinApi';
|
||||||
import { jellyfinItemsStore } from '../stores/data.store';
|
import { jellyfinItemsStore } from '../stores/data.store';
|
||||||
import Carousel from '../components-new/Carousel/Carousel.svelte';
|
import Carousel from '../components/Carousel/Carousel.svelte';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
import CarouselPlaceholderItems from '../components-new/Carousel/CarouselPlaceholderItems.svelte';
|
import CarouselPlaceholderItems from '../components/Carousel/CarouselPlaceholderItems.svelte';
|
||||||
|
|
||||||
const jellyfinItemsPromise = new Promise<JellyfinItem[]>((resolve) => {
|
const jellyfinItemsPromise = new Promise<JellyfinItem[]>((resolve) => {
|
||||||
jellyfinItemsStore.subscribe((data) => {
|
jellyfinItemsStore.subscribe((data) => {
|
||||||
|
|||||||