aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-01-16 02:21:25 -0800
committerFuwn <[email protected]>2024-01-16 02:21:25 -0800
commit2f7c8ce0bbc7ecc13f6670e4575678a2ff0d7432 (patch)
treeb149b36fa8567694ae4cc706f8302cfa0d00c912 /src
parentfix(sequelspy): move hover cover to title (diff)
downloaddue.moe-2f7c8ce0bbc7ecc13f6670e4575678a2ff0d7432.tar.xz
due.moe-2f7c8ce0bbc7ecc13f6670e4575678a2ff0d7432.zip
feat(anime): thumbnail mode
Diffstat (limited to 'src')
-rw-r--r--src/lib/List/Anime/CleanAnimeList.svelte235
-rw-r--r--src/lib/List/mediaTitle.ts14
-rw-r--r--src/lib/Media/Anime/Airing/time.ts9
-rw-r--r--src/lib/Settings/Categories/Display.svelte1
-rw-r--r--src/stores/settings.ts2
5 files changed, 183 insertions, 78 deletions
diff --git a/src/lib/List/Anime/CleanAnimeList.svelte b/src/lib/List/Anime/CleanAnimeList.svelte
index 32f4b6f4..6daba5f3 100644
--- a/src/lib/List/Anime/CleanAnimeList.svelte
+++ b/src/lib/List/Anime/CleanAnimeList.svelte
@@ -19,6 +19,8 @@
onMouseMove,
type HoverCoverResponse
} from '$lib/Media/Cover/hoverCover';
+ import { mediaTitle } from '../mediaTitle';
+ import tooltip from '$lib/Tooltip/tooltip';
export let media: Media[];
export let title: string;
@@ -64,95 +66,178 @@
</ul>
{/if}
-<ul>
- {#each media as anime}
- {@const progress = (anime.mediaListEntry || { progress: 0 }).progress}
+{#if $settings.displayThumbnailMode}
+ <div id="covers">
+ {#each media as anime}
+ {@const progress = (anime.mediaListEntry || { progress: 0 }).progress}
- {#if title.includes('Upcoming Episodes') || title.includes('Not Yet Released') || progress !== (anime.nextAiringEpisode?.episode || 9999) - 1}
- <li class="entry">
- <span class="content">
+ {#if title.includes('Upcoming Episodes') || title.includes('Not Yet Released') || progress !== (anime.nextAiringEpisode?.episode || 9999) - 1}
+ <div class="cover-card">
<a
href={outboundLink(anime, 'anime', $settings.displayOutboundLinksTo)}
target="_blank"
- on:mouseenter={() => {
- const response = onMouseEnter(anime);
-
- hoverCoverState.hovering = response.hovering;
- hoverCoverState.item = response.item;
- hoverCoverState.media = response.media;
- }}
- on:mouseleave={() => {
- const response = onMouseLeave();
-
- hoverCoverState.hovering = response.hovering;
- hoverCoverState.item = response.item;
- hoverCoverState.media = response.media;
- }}
- on:mousemove={(e) => {
- const response = onMouseMove(e, 300);
-
- hoverCoverState.style = response.style;
- }}
+ title={mediaTitle(anime)}
+ use:tooltip
>
- <span
- style={lastUpdatedMedia === anime.id && anime.episodes !== progress
- ? 'color: lightcoral'
- : ''}
- >
- <MediaTitle title={anime.title} />
- </span>
+ <img class="cover" src={anime.coverImage.extraLarge} alt="Cover" />
</a>
- {#if $settings.displaySocialButton}
- [<a href={`https://anilist.co/anime/${anime.id}/social`} target="_blank">S</a>]
- {/if}
- {#if title !== 'Upcoming Episodes' || title.includes('Not Yet Released') || !$settings.displayCountdownRightAligned}
- <span style="opacity: 50%;">|</span>
- {/if}
- {#if title !== 'Upcoming Episodes' || title.includes('Not Yet Released')}
- <!-- {anime.mediaListEntry?.progress || 0}{@html totalEpisodes(anime)} -->
- {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)}
- <button
- class="button-square button-action"
- style={pendingUpdate === anime.id ? 'pointer-events: none; opacity: 50%;' : ''}
- on:click={() => {
- if (pendingUpdate !== anime.id) {
- lastUpdatedMedia = anime.id;
- pendingUpdate = anime.id;
-
- incrementMediaProgress(anime.id, anime.mediaListEntry?.progress, user, () => {
- const mediaListEntry = media.find((m) => m.id === anime.id)?.mediaListEntry;
-
- if (mediaListEntry) mediaListEntry.progress = progress + 1;
-
- previousAnimeList = media;
- animeLists = cleanCache(user, identity);
- pendingUpdate = null;
- });
- }
- }}>+</button
+
+ <div class="cover-title">
+ {#if title !== 'Upcoming Episodes' || title.includes('Not Yet Released')}
+ {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)}
+ <button
+ class="button-square button-action"
+ style={pendingUpdate === anime.id ? 'pointer-events: none; opacity: 50%;' : ''}
+ on:click={() => {
+ if (pendingUpdate !== anime.id) {
+ lastUpdatedMedia = anime.id;
+ pendingUpdate = anime.id;
+
+ incrementMediaProgress(anime.id, anime.mediaListEntry?.progress, user, () => {
+ const mediaListEntry = media.find((m) => m.id === anime.id)?.mediaListEntry;
+
+ if (mediaListEntry) mediaListEntry.progress = progress + 1;
+
+ previousAnimeList = media;
+ animeLists = cleanCache(user, identity);
+ pendingUpdate = null;
+ });
+ }
+ }}>+</button
+ >
+ {#if !completed}
+ [{anime.nextAiringEpisode?.episode === -1
+ ? '?'
+ : (anime.nextAiringEpisode?.episode || 1) - 1}]
+ <br />
+ {@html airingTime(anime, subsPlease)}
+ {/if}
+ {:else}
+ {@html airingTime(anime, subsPlease, true)}
+ {/if}
+ </div>
+ </div>
+ {/if}
+ {/each}
+ </div>
+{:else}
+ <ul>
+ {#each media as anime}
+ {@const progress = (anime.mediaListEntry || { progress: 0 }).progress}
+
+ {#if title.includes('Upcoming Episodes') || title.includes('Not Yet Released') || progress !== (anime.nextAiringEpisode?.episode || 9999) - 1}
+ <li class="entry">
+ <span class="content">
+ <a
+ href={outboundLink(anime, 'anime', $settings.displayOutboundLinksTo)}
+ target="_blank"
+ on:mouseenter={() => {
+ const response = onMouseEnter(anime);
+
+ hoverCoverState.hovering = response.hovering;
+ hoverCoverState.item = response.item;
+ hoverCoverState.media = response.media;
+ }}
+ on:mouseleave={() => {
+ const response = onMouseLeave();
+
+ hoverCoverState.hovering = response.hovering;
+ hoverCoverState.item = response.item;
+ hoverCoverState.media = response.media;
+ }}
+ on:mousemove={(e) => {
+ const response = onMouseMove(e, 300);
+
+ hoverCoverState.style = response.style;
+ }}
>
- {#if !completed}
- [{anime.nextAiringEpisode?.episode === -1
- ? '?'
- : (anime.nextAiringEpisode?.episode || 1) - 1}]
+ <span
+ style={lastUpdatedMedia === anime.id && anime.episodes !== progress
+ ? 'color: lightcoral'
+ : ''}
+ >
+ <MediaTitle title={anime.title} />
+ </span>
+ </a>
+ {#if $settings.displaySocialButton}
+ [<a href={`https://anilist.co/anime/${anime.id}/social`} target="_blank">S</a>]
+ {/if}
+ {#if title !== 'Upcoming Episodes' || title.includes('Not Yet Released') || !$settings.displayCountdownRightAligned}
+ <span style="opacity: 50%;">|</span>
+ {/if}
+ {#if title !== 'Upcoming Episodes' || title.includes('Not Yet Released')}
+ <!-- {anime.mediaListEntry?.progress || 0}{@html totalEpisodes(anime)} -->
+ {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)}
+ <button
+ class="button-square button-action"
+ style={pendingUpdate === anime.id ? 'pointer-events: none; opacity: 50%;' : ''}
+ on:click={() => {
+ if (pendingUpdate !== anime.id) {
+ lastUpdatedMedia = anime.id;
+ pendingUpdate = anime.id;
+
+ incrementMediaProgress(anime.id, anime.mediaListEntry?.progress, user, () => {
+ const mediaListEntry = media.find((m) => m.id === anime.id)?.mediaListEntry;
+
+ if (mediaListEntry) mediaListEntry.progress = progress + 1;
+
+ previousAnimeList = media;
+ animeLists = cleanCache(user, identity);
+ pendingUpdate = null;
+ });
+ }
+ }}>+</button
+ >
+ {#if !completed}
+ [{anime.nextAiringEpisode?.episode === -1
+ ? '?'
+ : (anime.nextAiringEpisode?.episode || 1) - 1}]
+ <span class:countdown={$settings.displayCountdownRightAligned}>
+ {@html airingTime(anime, subsPlease)}
+ </span>
+ {/if}
+ {:else}
<span class:countdown={$settings.displayCountdownRightAligned}>
- {@html airingTime(anime, subsPlease)}
+ {@html airingTime(anime, subsPlease, true)}
</span>
{/if}
- {:else}
- <span class:countdown={$settings.displayCountdownRightAligned}>
- {@html airingTime(anime, subsPlease, true)}
- </span>
- {/if}
- </span>
- </li>
- {/if}
- {/each}
-</ul>
+ </span>
+ </li>
+ {/if}
+ {/each}
+ </ul>
+{/if}
<HoverCover options={hoverCoverState} width={300} />
<style>
+ #covers {
+ display: grid;
+ justify-content: center;
+ gap: 0.5rem;
+ row-gap: 1rem;
+ margin-top: 0.5rem;
+ grid-template-columns: repeat(auto-fill, minmax(116.609px, 1fr));
+ }
+
+ .cover {
+ background-size: cover;
+ background-position: center;
+ border-radius: 8px;
+ }
+
+ .cover-title {
+ text-align: center;
+ margin: 0.25rem;
+ }
+
+ .cover-card {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+
.entry::after {
content: '';
display: table;
diff --git a/src/lib/List/mediaTitle.ts b/src/lib/List/mediaTitle.ts
new file mode 100644
index 00000000..83344a7b
--- /dev/null
+++ b/src/lib/List/mediaTitle.ts
@@ -0,0 +1,14 @@
+import type { Media } from '$lib/AniList/media';
+import settings from '$stores/settings';
+import { get } from 'svelte/store';
+
+export const mediaTitle = (media: Media) => {
+ switch (get(settings).displayTitleFormat) {
+ case 'native':
+ return media.title.native || media.title.romaji || media.title.english;
+ case 'romaji':
+ return media.title.romaji || media.title.english || media.title.native;
+ case 'english':
+ return media.title.english || media.title.romaji || media.title.native;
+ }
+};
diff --git a/src/lib/Media/Anime/Airing/time.ts b/src/lib/Media/Anime/Airing/time.ts
index bcad803f..0f24ccc4 100644
--- a/src/lib/Media/Anime/Airing/time.ts
+++ b/src/lib/Media/Anime/Airing/time.ts
@@ -4,6 +4,7 @@ import type { SubsPlease } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
import settings from '$stores/settings';
import { injectAiringTime } from './Subtitled/match';
import { totalEpisodes } from '../episodes';
+import { get } from 'svelte/store';
export const airingTime = (
originalAnime: Media,
@@ -70,13 +71,15 @@ export const airingTime = (
hours ? `${hours.toFixed(3)} hours` : ''
}" style="opacity: ${opacity}%;">${anime.nextAiringEpisode?.episode}${totalEpisodes(
anime
- )} in ${timeFrame} <span style="opacity: 50%">${few ? `(${time})` : ''}</span></span>`;
+ )} in ${timeFrame} <span style="opacity: 50%">${
+ few && get(settings).displayThumbnailMode ? '<br>' : ''
+ }${few ? `(${time})` : ''}</span></span>`;
else
return `<span title="${
hours ? `${hours.toFixed(3)} hours` : ''
}" style="opacity: ${opacity}%;">${anime.nextAiringEpisode?.episode} in ${
- few ? '<b>' : ''
- }${timeFrame}${few ? '</b>' : ''} ${few ? `(${time})` : ''}</span>`;
+ few && get(settings).displayThumbnailMode ? '<br>' : ''
+ }${few ? '<b>' : ''}${timeFrame}${few ? '</b>' : ''} ${few ? `(${time})` : ''}</span>`;
}
return '';
diff --git a/src/lib/Settings/Categories/Display.svelte b/src/lib/Settings/Categories/Display.svelte
index 78fd514f..55661787 100644
--- a/src/lib/Settings/Categories/Display.svelte
+++ b/src/lib/Settings/Categories/Display.svelte
@@ -96,6 +96,7 @@
setting="displayHoverCover"
text="Show media cover when hovering on supported media titles"
/>
+<SettingCheckboxToggle setting="displayThumbnailMode" text="Show anime lists with thumbnails" />
<SettingCheckboxToggle setting="displaySocialButton" text="Show social tab shortcut for media" />
<select bind:value={$settings.displayTitleFormat}>
<option value="english">English</option>
diff --git a/src/stores/settings.ts b/src/stores/settings.ts
index 17342ce4..8d03dfb0 100644
--- a/src/stores/settings.ts
+++ b/src/stores/settings.ts
@@ -32,6 +32,7 @@ export interface Settings {
displayHoverCover: boolean;
displayDisableAnimations: boolean;
displayDisableNotifications: boolean;
+ displayThumbnailMode: boolean;
}
const defaultSettings: Settings = {
@@ -60,6 +61,7 @@ const defaultSettings: Settings = {
displayHoverCover: false,
displayDisableAnimations: false,
displayDisableNotifications: false,
+ displayThumbnailMode: false,
// Calculation
calculateChaptersRoundedDown: true,