mirror of
https://github.com/NoCrypt/migu.git
synced 2026-03-11 17:45:32 +00:00
cards
This commit is contained in:
parent
e16f276a25
commit
70f804ea7f
8 changed files with 237 additions and 17 deletions
|
|
@ -11,11 +11,11 @@
|
|||
<link href='/lib/halfmoon.css' rel='stylesheet'>
|
||||
<link href="/lib/Material-Icons.css" rel="stylesheet">
|
||||
|
||||
<script src='/lib/halfmoon.js'></script>
|
||||
<script defer src='/lib/halfmoon.js'></script>
|
||||
<script defer type="module" src="/src/main.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="dark-mode with-custom-webkit-scrollbars with-custom-css-scrollbars" data-sidebar-shortcut-enabled="true">
|
||||
</body>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -37,19 +37,6 @@
|
|||
overscroll-behavior: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@keyframes load-in {
|
||||
from {
|
||||
bottom: -1.2rem;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 0;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* sidebar patches */
|
||||
.page-wrapper.with-sidebar[data-sidebar-hidden] {
|
||||
--sidebar-width: var(--sidebar-minimised);
|
||||
|
|
|
|||
129
src/renderer/src/lib/Cards.svelte
Normal file
129
src/renderer/src/lib/Cards.svelte
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
<script>
|
||||
import { countdown } from '../modules/util.js'
|
||||
export let cards = new Promise(() => {})
|
||||
</script>
|
||||
|
||||
{#await cards}
|
||||
{#each Array(5) as _}
|
||||
<div class="card m-0 p-0">
|
||||
<div class="row h-full">
|
||||
<div class="col-4 skeloader" />
|
||||
<div class="col-8 bg-very-dark px-15 py-10">
|
||||
<p class="skeloader w-300 h-25 rounded bg-dark" />
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark" />
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{:then cards}
|
||||
{#each cards as card}
|
||||
{#if !card.media}
|
||||
<div class="card m-0 p-0" on:click={card.onclick}>
|
||||
<div class="row h-full">
|
||||
<div class="col-4 skeloader" />
|
||||
<div class="col-8 bg-very-dark px-15 py-10">
|
||||
<h5 class="m-0 text-capitalize font-weight-bold pb-10">{[card.parseObject.anime_title, card.parseObject.episode_number].filter(s => s).join(' - ')}</h5>
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark" />
|
||||
<p class="skeloader w-150 h-10 rounded bg-dark" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="card m-0 p-0" on:click={card.onclick} 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" />
|
||||
</div>
|
||||
<div class="col-8 h-full card-grid">
|
||||
<div class="px-15 py-10 bg-very-dark">
|
||||
<h5 class="m-0 text-capitalize font-weight-bold">{[card.media.title.userPreferred, card.episodeNumber].filter(s => s).join(' - ')}</h5>
|
||||
{#if card.schedule && card.media.nextAiringEpisode}
|
||||
<span class="text-muted font-weight-bold">
|
||||
{'EP ' + card.media.nextAiringEpisode.episode + ' in ' + countdown(card.media.nextAiringEpisode.timeUntilAiring)}
|
||||
</span>
|
||||
{/if}
|
||||
<p class="text-muted m-0 text-capitalize details">
|
||||
{#if card.media.format === 'TV'}
|
||||
<span>TV Show</span>
|
||||
{:else if card.media.format}
|
||||
<span>{card.media.format?.toLowerCase().replace(/_/g, ' ')}</span>
|
||||
{/if}
|
||||
{#if card.media.episodes}
|
||||
<span>{card.media.episodes + ' Episodes'}</span>
|
||||
{:else if card.media.duration}
|
||||
<span>{card.media.duration + ' Minutes'}</span>
|
||||
{/if}
|
||||
{#if card.media.status}
|
||||
<span>{card.media.status?.toLowerCase().replace(/_/g, ' ')}</span>
|
||||
{/if}
|
||||
<span>
|
||||
{[card.media.season?.toLowerCase(), card.media.seasonYear].filter(s => s).join(' ')}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-y-auto px-15 pb-5 bg-very-dark card-desc">
|
||||
{@html card.media.description}
|
||||
</div>
|
||||
<div class="px-15 pb-10 pt-5 genres">
|
||||
{#each card.media.genres as genre}
|
||||
<span class="badge badge-pill badge-color text-dark mt-5 font-weight-bold">{genre}</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/await}
|
||||
|
||||
<style>
|
||||
.h-10 {
|
||||
height: 1rem !important;
|
||||
}
|
||||
|
||||
.card-desc :global(p) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.details span + span::before {
|
||||
content: ' • ';
|
||||
}
|
||||
.card {
|
||||
will-change: transform, bottom;
|
||||
animation: 0.3s ease 0s 1 load-in;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
transition: transform 0.2s ease;
|
||||
height: 27rem !important;
|
||||
box-shadow: rgba(0, 4, 12, 0.3) 0px 7px 15px, rgba(0, 4, 12, 0.05) 0px 4px 4px;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
@keyframes load {
|
||||
from {
|
||||
left: -100%;
|
||||
}
|
||||
|
||||
to {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
.skeloader {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeloader::before {
|
||||
will-change: left;
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 15rem;
|
||||
background: linear-gradient(to right, transparent 0%, #25282c 50%, transparent 100%);
|
||||
animation: load 1s infinite cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,15 +1,64 @@
|
|||
<script>
|
||||
import Search from './Search.svelte'
|
||||
import Section from './Section.svelte'
|
||||
const sections = [
|
||||
{
|
||||
title: 'Continue Watching',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
},
|
||||
{
|
||||
title: 'New Releases',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
},
|
||||
{
|
||||
title: 'Your List',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
},
|
||||
{
|
||||
title: 'Trending Now',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
},
|
||||
{
|
||||
title: 'Romance',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
click: () => {},
|
||||
cards: new Promise(() => {})
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<div class="d-flex h-full flex-column overflow-y-scroll root">
|
||||
<div class="h-full py-10">
|
||||
<Search />
|
||||
<div>
|
||||
{#each sections as opts, i (i)}
|
||||
<Section {opts} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
animation: .3s ease 0s 1 load-in;
|
||||
animation: 0.3s ease 0s 1 load-in;
|
||||
}
|
||||
@keyframes load-in {
|
||||
from {
|
||||
bottom: -1.2rem;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 0;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<script>
|
||||
import Cards from '../../Cards.svelte'
|
||||
export let opts = {
|
||||
click: () => {},
|
||||
title: '',
|
||||
cards: undefined
|
||||
}
|
||||
</script>
|
||||
|
||||
<span class="d-flex px-20 align-items-end pointer text-decoration-none text-muted" on:click={opts.click}>
|
||||
<div class="pl-10 font-size-24 font-weight-semi-bold">{opts.title}</div>
|
||||
<div class="pr-10 ml-auto font-size-12">View More</div>
|
||||
</span>
|
||||
<div class="gallery pt-10 pb-20 w-full overflow-x-hidden position-relative">
|
||||
<Cards cards={opts.cards} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.text-muted:hover {
|
||||
color: var(--dm-link-text-color-hover) !important;
|
||||
}
|
||||
.gallery {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
grid-gap: 2rem;
|
||||
padding: 2rem 4rem;
|
||||
position: relative;
|
||||
padding: 0.7rem 4rem;
|
||||
grid-template-columns: repeat(5, 50rem);
|
||||
}
|
||||
|
||||
.gallery:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
width: 8rem;
|
||||
background: linear-gradient(270deg, rgba(37, 40, 44, 1) 0%, rgba(37, 40, 44, 0) 100%);
|
||||
/*this gradient looks like ass, need to find smth better*/
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
13
src/renderer/src/modules/util.js
Normal file
13
src/renderer/src/modules/util.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export function countdown (s) {
|
||||
const d = Math.floor(s / (3600 * 24))
|
||||
s -= d * 3600 * 24
|
||||
const h = Math.floor(s / 3600)
|
||||
s -= h * 3600
|
||||
const m = Math.floor(s / 60)
|
||||
s -= m * 60
|
||||
const tmp = []
|
||||
if (d) tmp.push(d + 'd')
|
||||
if (d || h) tmp.push(h + 'h')
|
||||
if (d || h || m) tmp.push(m + 'm')
|
||||
return tmp.join(' ')
|
||||
}
|
||||
Loading…
Reference in a new issue