mirror of
https://github.com/NoCrypt/migu.git
synced 2026-03-11 17:45:32 +00:00
viewAnime work
This commit is contained in:
parent
81b26292a7
commit
49cc6bb956
5 changed files with 270 additions and 10 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -11,4 +11,3 @@
|
|||
<div class={'pointer border-bottom ' + ($selectedTab === tab ? 'bg-dark-light' : '')} on:click={() => selectTab(tab)}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
252
src/renderer/src/lib/ViewAnime.svelte
Normal file
252
src/renderer/src/lib/ViewAnime.svelte
Normal 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>
|
||||
|
|
@ -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/)
|
||||
|
|
|
|||
Loading…
Reference in a new issue