This is the code that runs https://bandolier.learnjsthehardway.com/ for you to review. It uses the https://git.learnjsthehardway.com/learn-javascript-the-hard-way/bandolier-template to create the documentation for the project.
https://bandolier.learnjsthehardway.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
2.9 KiB
121 lines
2.9 KiB
2 years ago
|
<script>
|
||
|
import Layout from "$/client/Layout.svelte";
|
||
|
import { onMount } from "svelte";
|
||
|
import api from "$/client/api.js";
|
||
|
import {link} from 'svelte-spa-router';
|
||
|
import { defer, page_change } from "$/client/helpers.js";
|
||
|
import Icon from "$/client/components/Icon.svelte";
|
||
|
import WTVideo from "$/client/components/WTVideo.svelte";
|
||
|
import Video from "$/client/components/Video.svelte";
|
||
|
import IconImage from "$/client/components/IconImage.svelte";
|
||
|
import SnapImage from "$/client/components/SnapImage.svelte";
|
||
|
|
||
|
export let params = {};
|
||
|
let media = {};
|
||
|
let media_defer = defer();
|
||
|
|
||
|
const load_related = async () => {
|
||
|
const [ status, data ] = await api.get("/api/media");
|
||
|
return status == 200 ? data : [];
|
||
|
}
|
||
|
|
||
|
const load_media = async () => {
|
||
|
const [status, data] = await api.get("/api/media", {
|
||
|
media_id: params.id
|
||
|
});
|
||
|
|
||
|
if(status === 200) {
|
||
|
media = data[0];
|
||
|
media_defer.resolve();
|
||
|
} else {
|
||
|
console.error("Invalid response", status, data);
|
||
|
media_defer.reject();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$: if(page_change(media, params)) {
|
||
|
media_defer = defer();
|
||
|
load_media();
|
||
|
}
|
||
|
|
||
|
onMount(load_media);
|
||
|
</script>
|
||
|
|
||
|
<style>
|
||
|
content {
|
||
|
padding-top: var(--fixed-header-height);
|
||
|
flex-direction: row-reverse;
|
||
|
}
|
||
|
|
||
|
content > left {
|
||
|
overflow-y: auto;
|
||
|
min-height: calc(100vh - var(--fixed-header-height));
|
||
|
max-height: calc(100vh - var(--fixed-header-height));
|
||
|
}
|
||
|
|
||
|
content > right {
|
||
|
border: 1px solid green;
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
video-display {
|
||
|
display: flex;
|
||
|
background-color: var(--value2);
|
||
|
width: 100%;
|
||
|
}
|
||
|
</style>
|
||
|
|
||
|
<Layout footer={ false } fixed={ true } authenticated={ true } fullwidth={ true }>
|
||
|
<content>
|
||
|
<left>
|
||
|
{#await load_related()}
|
||
|
|
||
|
{:then related}
|
||
|
{#each related as media}
|
||
|
<card>
|
||
|
<top>
|
||
|
<a href="/video/{ media.id }/" use:link>
|
||
|
{#if media.poster}
|
||
|
<SnapImage width={ media.width / 3 } height={ media.height / 3 } src={ media.poster } />
|
||
|
{:else}
|
||
|
<IconImage name="video" />
|
||
|
{/if}
|
||
|
</a>
|
||
|
</top>
|
||
|
<bottom>{ media.id}</bottom>
|
||
|
</card>
|
||
|
{/each}
|
||
|
{/await}
|
||
|
</left>
|
||
|
|
||
|
|
||
|
<right>
|
||
|
{#await media_defer}
|
||
|
|
||
|
{:then}
|
||
|
<video-display style="--aspect-ratio: 16/9;">
|
||
|
{#if media.torrent_url}
|
||
|
<WTVideo media={ media } />
|
||
|
{:else}
|
||
|
<Video src={ media.src } poster={ media.poster } />
|
||
|
{/if}
|
||
|
</video-display>
|
||
|
|
||
|
<info>
|
||
|
<tile>
|
||
|
<left>
|
||
|
<Icon name="user" size="48" />
|
||
|
</left>
|
||
|
<middle>
|
||
|
ID: { media.id } { media.title || "No title." } { media.duration }
|
||
|
</middle>
|
||
|
<right>
|
||
|
{ media.views } <Icon name="eye" />
|
||
|
</right>
|
||
|
</tile>
|
||
|
</info>
|
||
|
{/await}
|
||
|
</right>
|
||
|
</content>
|
||
|
</Layout>
|