fix: improve design

fixed sidebar hover animations
added card status dots
fixed card genre overflow
fixed card no genre
search is now sticky
viewanime now uses cards to display things
This commit is contained in:
ThaUnknown 2023-04-11 17:23:54 +02:00
parent 1aecac107b
commit f19dbdb400
7 changed files with 99 additions and 78 deletions

View file

@ -1,6 +1,6 @@
{
"name": "Miru",
"version": "3.9.2",
"version": "3.9.3",
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
"description": "Stream anime torrents, real-time with no waiting for downloads.",
"main": "src/index.js",

View file

@ -8,6 +8,15 @@
}
export let length = 5
export let tabable = false
const statusColorMap = {
CURRENT: 'rgb(61,180,242)',
PLANNING: 'rgb(247,154,99)',
COMPLETED: 'rgb(123,213,85)',
PAUSED: 'rgb(250,122,122)',
REPEAT: '#3baeea',
DROPPED: 'rgb(232,93,117)'
}
</script>
{#await cards}
@ -52,6 +61,9 @@
<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'>
{#if card.media.mediaListEntry?.status}
<div style:--statusColor={statusColorMap[card.media.mediaListEntry.status]} class='list-status-circle d-inline-flex overflow-hidden mr-5' title={card.media.mediaListEntry.status} />
{/if}
{#if card.failed}
<span class='badge badge-secondary'>Uncertain</span>
{/if}
@ -86,11 +98,13 @@
<div class='overflow-y-auto px-15 pb-5 bg-very-dark card-desc pre-wrap'>
{card.media.description?.replace(/<[^>]*>/g, '') || ''}
</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 mr-5 font-weight-bold'>{genre}</span>
{/each}
</div>
{#if card.media.genres.length}
<div class='px-15 pb-10 pt-5 genres'>
{#each card.media.genres.slice(0, 3) as genre}
<span class='badge badge-pill badge-color text-dark mt-5 mr-5 font-weight-bold'>{genre}</span>
{/each}
</div>
{/if}
</div>
</div>
</div>
@ -185,4 +199,10 @@
.day-row {
grid-column: 1 / -1;
}
.list-status-circle {
background: var(--statusColor);
height: 1.1rem;
width: 1.1rem;
border-radius: 50%;
}
</style>

View file

@ -359,32 +359,31 @@
</script>
<div class='d-flex h-full flex-column overflow-y-scroll root' on:scroll={infiniteScroll} bind:this={container}>
<div class='h-full py-10'>
<Search bind:media bind:search={$search} bind:current {loadCurrent} />
{#if media.length}
<Gallery {media} />
{:else}
<div class='container'>
{#if $progress < 30}
We're ${30 - $progress} short of our monthly goal! That's only {Math.ceil((30 - $progress) / 5)} people donating $5.00!
{:else}
We've reached the donation goal for this month! \o/
{/if}
<div class='progress-group py-5'>
<div class='progress'>
<div class='progress-bar progress-bar-animated' role='progressbar' style='width: {$progress / 30 * 100}%;' />
</div>
<span class='progress-group-label'>${$progress} / $30.00</span>
<Search bind:media bind:search={$search} bind:current {loadCurrent} />
<hr />
{#if media.length}
<Gallery {media} />
{:else}
<div class='container'>
{#if $progress < 30}
We're ${30 - $progress} short of our monthly goal! That's only {Math.ceil((30 - $progress) / 5)} people donating $5.00!
{:else}
We've reached the donation goal for this month! \o/
{/if}
<div class='progress-group py-5'>
<div class='progress'>
<div class='progress-bar progress-bar-animated' role='progressbar' style='width: {$progress / 30 * 100}%;' />
</div>
<button class='btn btn-primary' type='button' on:click={() => { window.IPC.emit('open', 'https://github.com/sponsors/ThaUnknown/') }}>Donate</button>
<span class='progress-group-label'>${$progress} / $30.00</span>
</div>
<div>
{#each Object.entries(sections) as [key, opts] (key)}
{#if !opts.hide}
<Section opts={{ ...opts, onclick: () => (current = key) }} />
{/if}
{/each}
</div>
{/if}
</div>
<button class='btn btn-primary' type='button' on:click={() => { window.IPC.emit('open', 'https://github.com/sponsors/ThaUnknown/') }}>Donate</button>
</div>
<div>
{#each Object.entries(sections) as [key, opts] (key)}
{#if !opts.hide}
<Section opts={{ ...opts, onclick: () => (current = key) }} />
{/if}
{/each}
</div>
{/if}
</div>

View file

@ -47,7 +47,7 @@
}
</script>
<div class='container-fluid row p-20' on:input={input}>
<div class='container-fluid row p-20 position-sticky top-0 search-container z-40' on:input={input}>
<div class='col-lg col-4 p-10 d-flex flex-column justify-content-end'>
<div class='pb-10 font-size-24 font-weight-semi-bold d-flex'>
<div class='material-icons mr-10 font-size-30'>title</div>
@ -217,4 +217,7 @@
.font-size-30 {
font-size: 3rem !important;
}
.search-container {
background: var(--dm-base-body-bg-color);;
}
</style>

View file

@ -215,6 +215,8 @@
[data-toggle='tooltip']:not([data-target-breakpoint])::before,
[data-toggle='tooltip']:not([data-target-breakpoint])::before {
visibility: visible !important;
pointer-events: none;
background: #fff;
color: #000;
transition: opacity 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), top 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
@ -224,8 +226,7 @@
box-shadow: var(--dm-shadow) !important;
}
[data-toggle='tooltip']:not([data-target-breakpoint]):hover::before,
[data-toggle='tooltip']:not([data-target-breakpoint]):focus::before {
[data-toggle='tooltip']:not([data-target-breakpoint]):hover::before {
opacity: 1;
top: 50%;
}

View file

@ -7,13 +7,13 @@
export let title = 'Relations'
</script>
{#if list?.length}
<span class='d-flex align-items-end pointer text-decoration-none mt-20 pt-20' on:click={toggleList}>
<span class='d-flex align-items-end pointer text-decoration-none pt-20' on:click={toggleList}>
<h1 class='font-weight-bold text-white'>{title}</h1>
{#if list.length > 4}
<h6 class='ml-auto font-size-12 more text-muted'>{showMore ? 'Show Less' : 'Show More'}</h6>
{/if}
</span>
<div class='d-flex text-capitalize flex-wrap pt-20 justify-center'>
<div class='d-flex text-capitalize flex-wrap card m-0'>
{#each list.slice(0, showMore ? 100 : 4) as item}
<slot {item} />
{/each}

View file

@ -36,8 +36,8 @@
<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={media.coverImage?.extraLarge || media.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='col-md-9 col-8 row align-content-end'>
<div class='col-md-8 col-12 d-flex justify-content-end flex-column pl-20'>
<div class='px-md-20 d-flex flex-column font-size-12'>
<span class='title font-weight-bold pb-sm-15 text-white select-all'>
{media.title.userPreferred}
@ -84,59 +84,54 @@
</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'>
<div class='col-md-9 pr-50'>
<h1 class='title font-weight-bold text-white'>Synopsis</h1>
<div class='font-size-16 pr-15 pre-wrap select-all'>
<div class='font-size-16 pre-wrap select-all card m-0'>
{media.description?.replace(/<[^>]*>/g, '') || ''}
</div>
<ToggleList list={media.relations?.edges?.filter(({ node }) => node.type === 'ANIME')} let:item title='Relations'>
<div class='w-150 mx-15 mb-10 rel pointer'
<div class='w-150 mx-15 my-10 rel pointer'
on:click={async () => { $view = null; $view = (await alRequest({ method: 'SearchIDSingle', id: item.node.id })).data.Media }}
on:keydown={wrapEnter(async () => { $view = null; $view = (await alRequest({ method: 'SearchIDSingle', id: item.node.id })).data.Media })}
tabindex='0' role='button'
>
<img loading='lazy' src={item.node.coverImage.medium || ''} alt='cover' class='cover-img w-full h-200 rel-img' />
tabindex='0' role='button'>
<img loading='lazy' src={item.node.coverImage.medium || ''} alt='cover' class='cover-img w-full h-200 rel-img rounded' />
<div class='pt-5'>{item.relationType.replace(/_/g, ' ').toLowerCase()}</div>
<h5 class='font-weight-bold text-white'>{item.node.title.userPreferred}</h5>
<h5 class='font-weight-bold text-white mb-5'>{item.node.title.userPreferred}</h5>
</div>
</ToggleList>
{#if maxPlayEp}
<table class='table table-hover w-500 table-auto'>
<thead>
<tr>
<th class='px-0'><h2 class='title font-weight-bold text-white pt-20 mb-5'>Episodes</h2></th>
<th />
</tr>
</thead>
<tbody>
{#each Array(maxPlayEp) as _, i}
{@const ep = maxPlayEp - i}
<tr class="font-size-20 py-10 pointer {ep <= media.mediaListEntry?.progress ? 'text-muted' : 'text-white'}"
on:click={() => {
playAnime(media, ep)
close()
}}
on:keydown={wrapEnter(() => {
playAnime(media, ep)
close()
})}
tabindex='0' role='button'
>
<td class='w-full font-weight-semi-bold'>Episode {ep}</td>
<td class='material-icons text-right h-full d-table-cell'>play_arrow</td>
</tr>
{/each}
</tbody>
</table>
<h1 class='title font-weight-bold text-white pt-20'>Episodes</h1>
<div class='card m-0 d-inline-block'>
<table class='table table-hover w-500 table-auto '>
<tbody>
{#each Array(maxPlayEp) as _, i}
{@const ep = maxPlayEp - i}
<tr class="font-size-20 py-10 pointer {ep <= media.mediaListEntry?.progress ? 'text-muted' : 'text-white'}"
on:click={() => {
playAnime(media, ep)
close()
}}
on:keydown={wrapEnter(() => {
playAnime(media, ep)
close()
})}
tabindex='0' role='button'
>
<td class='w-full font-weight-semi-bold'>Episode {ep}</td>
<td class='material-icons text-right h-full d-table-cell'>play_arrow</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
<ToggleList list={media.recommendations.edges.filter(edge => edge.node.mediaRecommendation)} let:item title='Recommendations'>
<div class='w-150 mx-15 mb-10 rel pointer'
<div class='w-150 mx-15 my-10 rel pointer'
on:click={async () => { $view = null; $view = (await alRequest({ method: 'SearchIDSingle', id: item.node.mediaRecommendation.id })).data.Media }}
on:keydown={wrapEnter(async () => { $view = null; $view = (await alRequest({ method: 'SearchIDSingle', id: item.node.mediaRecommendation.id })).data.Media })}
tabindex='0' role='button'
>
<img loading='lazy' src={item.node.mediaRecommendation.coverImage.medium || ''} alt='cover' class='cover-img w-full h-200 rel-img' />
<h5 class='font-weight-bold text-white'>{item.node.mediaRecommendation.title.userPreferred}</h5>
tabindex='0' role='button'>
<img loading='lazy' src={item.node.mediaRecommendation.coverImage.medium || ''} alt='cover' class='cover-img w-full h-200 rel-img rounded' />
<h5 class='font-weight-bold text-white mb-5'>{item.node.mediaRecommendation.title.userPreferred}</h5>
</div>
</ToggleList>
</div>
@ -170,6 +165,9 @@
.title {
font-size: 4rem;
}
.pr-50 {
padding-right: 5rem;
}
.close {
top: 1rem !important;
left: unset !important;