viewAnime work

This commit is contained in:
ThaUnknown 2022-03-11 18:31:55 +01:00
parent 81b26292a7
commit 49cc6bb956
5 changed files with 270 additions and 10 deletions

View file

@ -1,16 +1,19 @@
<script>
import Sidebar from './lib/Sidebar.svelte'
import Router from './lib/Router.svelte'
import ViewAnime from './lib/ViewAnime.svelte'
let page = 'home'
</script>
<div class="page-wrapper with-sidebar" data-sidebar-type="full-height overlayed-sm-and-down" data-sidebar-hidden="hidden">
<div class="sticky-alerts" />
<!-- svelte-ignore missing-declaration -->
<div class="sidebar-overlay" on:click={halfmoon.toggleSidebar.bind(halfmoon)} />
<Sidebar bind:page />
<Router bind:page />
</div>
<ViewAnime>
<div class="page-wrapper with-sidebar" data-sidebar-type="full-height overlayed-sm-and-down" data-sidebar-hidden="hidden">
<div class="sticky-alerts" />
<!-- svelte-ignore missing-declaration -->
<div class="sidebar-overlay" on:click={halfmoon.toggleSidebar.bind(halfmoon)} />
<Sidebar bind:page />
<Router bind:page />
</div>
</ViewAnime>
<style>
:root {

View file

@ -1,6 +1,12 @@
<script>
import { countdown } from '../modules/util.js'
import { getContext } from 'svelte'
export let cards = new Promise(() => {})
const view = getContext('view')
function viewMedia(media) {
$view = media
}
</script>
{#await cards}
@ -30,7 +36,7 @@
</div>
</div>
{:else}
<div class="card m-0 p-0" on:click={card.onclick} style:--color={card.media.coverImage.color || '#1890ff'}>
<div class="card m-0 p-0" on:click={card.onclick || (() => viewMedia(card.media))} style:--color={card.media.coverImage.color || '#1890ff'}>
<div class="row h-full">
<div class="col-4">
<img loading="lazy" src={card.media.coverImage.extraLarge || ''} alt="cover" class="cover-img w-full h-full" />

View file

@ -11,4 +11,3 @@
<div class={'pointer border-bottom ' + ($selectedTab === tab ? 'bg-dark-light' : '')} on:click={() => selectTab(tab)}>
<slot />
</div>

View file

@ -0,0 +1,252 @@
<script>
import { setContext } from 'svelte'
import { writable } from 'svelte/store'
let view = writable(null)
setContext('view', view)
$: console.log($view)
function close() {
$view = null
}
const detailsMap = [
{ property: 'episode', label: 'Airing', icon: 'schedule', custom: 'property' },
{ property: 'genres', label: 'Genres', icon: 'theater_comedy' },
{ property: 'season', label: 'Season', icon: 'spa', custom: 'property' },
{ property: 'episodes', label: 'Episodes', icon: 'theaters', custom: 'property' },
{ property: 'duration', label: 'Duration', icon: 'timer' },
{ property: 'format', label: 'Format', icon: 'monitor' },
{ property: 'status', label: 'Status', icon: 'live_tv' },
{ property: 'nodes', label: 'Studio', icon: 'business' },
{ property: 'source', label: 'Source', icon: 'source' },
{ property: 'averageScore', label: 'Rating', icon: 'trending_up', custom: 'property' },
{ property: 'english', label: 'English', icon: 'title' },
{ property: 'romaji', label: 'Romaji', icon: 'translate' },
{ property: 'native', label: 'Native', icon: '語', custom: 'icon' }
]
function getCustomProperty(detail, media) {
if (detail.property === 'episodes' && media.progress) {
return `Watched <b>${media.progress}</b> of <b>${media.episodes}</b>`
} else if (detail.property === 'averageScore') {
return media.averageScore + '%'
} else if (detail.property === 'season') {
return [media.season?.toLowerCase(), media.seasonYear].filter(f => f).join(' ')
} else if (detail.property === 'episode') {
return `Ep ${media.nextAiringEpisode.episode}: ${countdown(media.nextAiringEpisode.timeUntilAiring)}`
} else {
return media[detail.property]
}
}
</script>
<div class="modal modal-full" class:show={$view} id="viewAnime" tabindex="-1" role="dialog">
{#if $view}
<div class="h-full modal-content bg-very-dark p-0 overflow-y-auto">
<button class="close pointer z-30 bg-dark shadow-lg border" type="button" on:click={close}>
<span>×</span>
</button>
<div class="h-md-half w-full position-relative z-20">
<div class="h-full w-full position-absolute bg-dark-light banner" style:--bannerurl={`url('${$view.bannerImage||''}')`}/>
<div class="d-flex h-full top w-full">
<div class="container-xl w-full">
<div class="row d-flex justify-content-end flex-row h-full px-20 pt-20 px-xl-0">
<div class="col-md-3 col-4 d-flex h-full justify-content-end flex-column pb-15 align-items-center">
<img class="contain-img rounded mw-full mh-full shadow" alt="cover" src={$view.coverImage?.extraLarge || $view.coverImage?.medium} />
</div>
<div class="col-md-9 col-8 row align-content-end pl-20">
<div class="col-md-8 col-12 d-flex justify-content-end flex-column">
<div class="px-md-20 d-flex flex-column font-size-12">
<span class="title font-weight-bold pb-sm-15 text-white">
{$view.title.userPreferred}
</span>
<div class="d-flex flex-row font-size-18 pb-sm-15">
<span class="material-icons mr-10 font-size-24"> trending_up </span>
<span>
Rating: {$view.averageScore + '%'}
<span class="font-weight-bold mr-20" />
</span>
<span class="material-icons mx-10 font-size-24"> monitor </span>
<span>
Format: {'TV' ? $view.format : $view.format?.toLowerCase()}
<span class="font-weight-bold mr-20 text-capitalize" />
</span>
{#if $view.episodes === 1 || (!$view.episodes && !$view.nextAiringEpisode?.episode)}
<span class="material-icons mx-10 font-size-24"> theaters </span>
<span>
Episodes: {$view.episodes}
<span class="font-weight-bold mr-20" />
</span>
{:else}
<span class="material-icons mx-10 font-size-24"> timer </span>
<span>
Length: {$view.duration + ' min'}
<span class="font-weight-bold mr-20" />
</span>
{/if}
</div>
<div class="pb-15 pt-5 overflow-x-auto text-nowrap font-weight-bold">
{#each $view.genres as genre}
<div class="badge badge-pill shadow">
{genre}
</div>
{/each}
</div>
</div>
</div>
<div class="col-md-4 d-flex justify-content-end flex-column">
<div class="d-flex flex-column flex-wrap">
<div class="btn-group mb-5" role="group">
<button class="btn btn-primary d-flex align-items-center font-weight-bold font-size-24 h-50" type="button">
<span class="material-icons mr-10 font-size-24 w-30"> play_arrow </span>
<span>Play</span>
</button>
<div class="btn-group dropdown with-arrow" role="group">
<button
class="btn btn-square btn-primary d-flex h-50 w-50 justify-content-center"
data-toggle="dropdown"
type="button"
aria-haspopup="true"
id="dropdown-play"
aria-expanded="false">
<span class="material-icons">expand_more</span>
<span class="sr-only">Open dropdown</span>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-play">
<div class="input-group w-250 form-control-lg p-0">
<div class="input-group-prepend">
<span class="input-group-text">Episode</span>
</div>
<input type="number" value="1" min="1" max="30" class="form-control text-right form-control-lg" />
</div>
</div>
</div>
</div>
<div class="btn-group mb-5 border-0" role="group">
<button class="btn d-flex align-items-center font-weight-bold font-size-16 border-0" type="button">
<span class="material-icons mr-10 font-size-18 w-30"> get_app </span>
Download
</button>
<div class="btn-group dropdown with-arrow" role="group">
<button
class="btn btn-square d-flex w-50 justify-content-center border-0"
data-toggle="dropdown"
type="button"
id="dropdown-download"
aria-haspopup="true"
aria-expanded="false">
<span class="material-icons">expand_more</span>
<span class="sr-only">Open dropdown</span>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-download">
<div class="input-group w-250 form-control-lg p-0">
<div class="input-group-prepend">
<span class="input-group-text">Episode</span>
</div>
<input type="number" value="1" min="1" max="30" class="form-control text-right form-control-lg" />
</div>
</div>
</div>
</div>
<button class="btn d-flex align-items-center mb-5 font-weight-bold font-size-16">
<span class="material-icons mr-10 font-size-18 w-30"> live_tv </span>
Trailer
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-xl bg-very-dark z-10">
<div class="row p-20 px-xl-0 flex-column-reverse flex-md-row">
<div class="col-md-9 px-20">
<h1 class="title font-weight-bold text-white">Sypnosis</h1>
<div class="font-size-16 pr-15">
{@html $view.description}
</div>
<!-- <h1 class="title font-weight-bold text-white pt-20">Episodes</h1>
<div class="d-flex flex-wrap justify-content-start"> -->
<!-- <div class="position-relative w-250 rounded mr-10 mb-10 overflow-hidden pointer">
<img loading="lazy"
src="https://img1.ak.crunchyroll.com/i/spire1-tmb/b199406edeebc19a7f4e4412d6e1dfcc1365964779_full.jpg"
class="w-full h-full">
<div class="position-absolute ep-title w-full p-5 text-truncate bottom-0">Episode 1 - To You, 2,000
Years in the Future -The Fall of Zhiganshina (1)</div>
</div> -->
<!-- </div> -->
</div>
<div class="col-md-3 px-sm-0 px-20">
<h1 class="title font-weight-bold text-white">Details</h1>
<div class="card m-0 px-20 py-10 d-flex flex-md-column flex-row overflow-x-auto text-capitalize" id="viewDetails">
{#each detailsMap as detail}
{@const property = $view[detail.property]}
{#if property}
<div class="d-flex flex-row px-10 py-5">
<div class={detail.custom === 'icon' ? 'd-flex align-items-center text-nowrap font-size-12 font-weight-bold' : 'material-icons mr-10 font-size-24'}>
{detail.icon}
</div>
<div class="d-flex flex-column justify-content-center text-nowrap">
<div class="font-weight-bold">
{#if detail.custom === 'property'}
{getCustomProperty(detail, $view)}
{:else if property.constructor === Array}
{property === 'nodes' ? property[0] && property[0].name : property.join(', ').replace(/_/g, ' ').toLowerCase()}
{:else}
{property.toString().replace(/_/g, ' ').toLowerCase()}
{/if}
</div>
<div />
</div>
</div>
{/if}
{/each}
</div>
</div>
</div>
</div>
</div>
{/if}
</div>
<slot />
<style>
.banner {
background: no-repeat center center;
background-size: cover;
background-image: linear-gradient(0deg, rgba(17,20,23,1) 0%, rgba(17,20,23,0.80) 25%, rgba(17,20,23,0.40) 50%, rgba(37,40,44,0) 100%), var(--bannerurl) !important
}
.top {
backdrop-filter: blur(10px);
}
/* #viewEpisodesWrapper.hidden {
opacity: 0;
height: 0
}
#viewEpisodesWrapper {
opacity: 1;
height: auto;
transition: opacity .2s cubic-bezier(.25, .8, .25, 1);
overflow: hidden;
} */
.card {
background-color: var(--dm-button-bg-color) !important;
background-image: var(--dm-button-bg-image) !important;
box-shadow: var(--dm-button-box-shadow) !important;
}
.title {
font-size: 4rem;
}
.badge {
background-color: var(--dm-button-bg-color) !important;
padding: 0.6rem 2rem;
font-size: 1.4rem;
border: none;
margin-right: 0.6rem;
}
</style>

View file

@ -104,7 +104,7 @@ export async function resolveFileMedia (opts) {
async function resolveTitle (title) {
if (!(title in relations)) {
// resolve name and shit
const method = { name: title, method: 'SearchName', perPage: 1, status: ['RELEASING', 'FINISHED'], sort: 'SEARCH_MATCH', startDate: 10000000 }
const method = { name: title, method: 'SearchName', perPage: 1, status: ['RELEASING'], sort: 'SEARCH_MATCH', startDate: 10000000 }
let res = await alRequest(method)
if (!res.data.Page.media[0]) {
const index = method.name.search(/S\d/)