diff options
| author | Fuwn <[email protected]> | 2023-12-30 17:18:22 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-12-30 17:18:22 -0800 |
| commit | 3de6d077b690bac153ba91d6c1483e58b1998e4b (patch) | |
| tree | 2e5d266ef5e3ed42a5dc9e8e8bddacfd1c5c558c /src/lib/Tools | |
| parent | fix(anilist): final push page (diff) | |
| download | due.moe-3de6d077b690bac153ba91d6c1483e58b1998e4b.tar.xz due.moe-3de6d077b690bac153ba91d6c1483e58b1998e4b.zip | |
feat(wrapped): move preview next to options
Diffstat (limited to 'src/lib/Tools')
| -rw-r--r-- | src/lib/Tools/Wrapped.svelte | 622 |
1 files changed, 318 insertions, 304 deletions
diff --git a/src/lib/Tools/Wrapped.svelte b/src/lib/Tools/Wrapped.svelte index 35f3e0e3..a9af64c4 100644 --- a/src/lib/Tools/Wrapped.svelte +++ b/src/lib/Tools/Wrapped.svelte @@ -487,341 +487,344 @@ {#await wrapped(user, currentUserIdentity)} {@html nbsp('Loading user data ...')} {:then wrapped} - <div - id="wrapped" - class:light-theme={lightMode} - style={`width: ${width}px;`} - class:transparent={transparency} - > - {#if !disableActivityHistory && activityHistoryPosition === 'TOP'} - <div class="categories-grid" style="padding-bottom: 0;"> - <div class="category-grid bottom-category pure-category category"> - <div id="activity-history"> - <ActivityHistoryGrid {user} activityData={activities} /> + <div id="list-container"> + <div + id="wrapped" + class:light-theme={lightMode} + style={`width: ${width}px; flex-shrink: 0;`} + class:transparent={transparency} + > + {#if !disableActivityHistory && activityHistoryPosition === 'TOP'} + <div class="categories-grid" style="padding-bottom: 0;"> + <div class="category-grid bottom-category pure-category category"> + <div id="activity-history"> + <ActivityHistoryGrid {user} activityData={activities} /> + </div> </div> </div> - </div> - {/if} - <div class="categories-grid" style="padding-bottom: 0;"> - <div class="grid-item image-grid avatar-grid category top-category"> - <a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank"> - <img src={proxy(wrapped.avatar.large)} alt="User Avatar" on:load={updateWidth} /> - </a> - <div> + {/if} + <div class="categories-grid" style="padding-bottom: 0;"> + <div class="grid-item image-grid avatar-grid category top-category"> + <a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank"> + <img src={proxy(wrapped.avatar.large)} alt="User Avatar" on:load={updateWidth} /> + </a> <div> - <a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank"> - <b> - {currentUserIdentity.name} - </b> - </a> + <div> + <a href={`https://anilist.co/user/${currentUserIdentity.name}`} target="_blank"> + <b> + {currentUserIdentity.name} + </b> + </a> + </div> + <div> + Status Posts: {wrapped.activities.statusCount} + </div> + <div> + Messages: {wrapped.activities.messageCount} + </div> + <div> + Days Active: {activities.length}/{useFullActivityHistory ? 365 : 189} + </div> </div> - <div> - Status Posts: {wrapped.activities.statusCount} + </div> + <div class="category-grid pure-category category top-category"> + <div class="grid-item"> + <b>Anime</b> </div> - <div> - Messages: {wrapped.activities.messageCount} + <div class="grid-item"> + Time Watched: {((minutesWatched || 0) / 60 / 24).toFixed(2)} days </div> - <div> - Days Active: {activities.length}/{useFullActivityHistory ? 365 : 189} + <div class="grid-item"> + Completed: {animeList?.length} </div> + <div class="grid-item">Episodes: {episodes}</div> </div> - </div> - <div class="category-grid pure-category category top-category"> - <div class="grid-item"> - <b>Anime</b> - </div> - <div class="grid-item"> - Time Watched: {((minutesWatched || 0) / 60 / 24).toFixed(2)} days - </div> - <div class="grid-item"> - Completed: {animeList?.length} - </div> - <div class="grid-item">Episodes: {episodes}</div> - </div> - <div class="category-grid pure-category category top-category"> - <div class="grid-item"> - <b>Manga</b> - </div> - <div class="grid-item"> - Time Read: {estimatedDayReading(chapters).toFixed(2)} days - </div> - <div class="grid-item"> - Completed: {mangaList?.length} - </div> - <div class="grid-item"> - Chapters: {chapters} + <div class="category-grid pure-category category top-category"> + <div class="grid-item"> + <b>Manga</b> + </div> + <div class="grid-item"> + Time Read: {estimatedDayReading(chapters).toFixed(2)} days + </div> + <div class="grid-item"> + Completed: {mangaList?.length} + </div> + <div class="grid-item"> + Chapters: {chapters} + </div> </div> </div> - </div> - {#if !disableActivityHistory && activityHistoryPosition === 'BELOW_TOP'} - <div class="categories-grid" style="padding-bottom: 0;"> - <div class="category-grid bottom-category pure-category category"> - <div id="activity-history"> - <ActivityHistoryGrid {user} activityData={activities} /> + {#if !disableActivityHistory && activityHistoryPosition === 'BELOW_TOP'} + <div class="categories-grid" style="padding-bottom: 0;"> + <div class="category-grid bottom-category pure-category category"> + <div id="activity-history"> + <ActivityHistoryGrid {user} activityData={activities} /> + </div> </div> </div> - </div> - {/if} - {#if animeList !== undefined || mangaList !== undefined} - <div class="categories-grid"> - {#if animeList !== undefined && animeList.length !== 0} - <div class="category-grid pure-category category middle-category"> - <div class="grid-item image-grid"> - <a href={`https://anilist.co/anime/${animeList[0].id}`} target="_blank"> - <img - src={proxy(animeList[0].coverImage.extraLarge)} - alt="Highest Rated Anime Cover" - class="cover-image" - on:load={updateWidth} - /> - </a> - <div> - <b>{animeMostTitle} Anime</b> - <ol> - {#each animeList?.slice(0, highestRatedCount) as anime} - <li> - <a href={`https://anilist.co/anime/${anime.id}`} target="_blank"> - <MediaTitleDisplay title={anime.title} /> - </a> - {highestRatedMediaPercentage ? `: ${anime.mediaListEntry?.score}%` : ''} - </li> - {/each} - </ol> + {/if} + {#if animeList !== undefined || mangaList !== undefined} + <div class="categories-grid"> + {#if animeList !== undefined && animeList.length !== 0} + <div class="category-grid pure-category category middle-category"> + <div class="grid-item image-grid"> + <a href={`https://anilist.co/anime/${animeList[0].id}`} target="_blank"> + <img + src={proxy(animeList[0].coverImage.extraLarge)} + alt="Highest Rated Anime Cover" + class="cover-image" + on:load={updateWidth} + /> + </a> + <div> + <b>{animeMostTitle} Anime</b> + <ol> + {#each animeList?.slice(0, highestRatedCount) as anime} + <li> + <a href={`https://anilist.co/anime/${anime.id}`} target="_blank"> + <MediaTitleDisplay title={anime.title} /> + </a> + {highestRatedMediaPercentage ? `: ${anime.mediaListEntry?.score}%` : ''} + </li> + {/each} + </ol> + </div> </div> </div> - </div> - {/if} - {#if mangaList !== undefined && mangaList.length !== 0} - <div class="category-grid pure-category category middle-category"> - <div class="grid-item image-grid"> - <a href={`https://anilist.co/manga/${mangaList[0].id}`} target="_blank"> - <img - src={proxy(mangaList[0].coverImage.extraLarge)} - alt="Highest Rated Manga Cover" - class="cover-image" - on:load={updateWidth} - /> - </a> - <div> - <b>{mangaMostTitle} Manga</b> - <ol> - {#each mangaList?.slice(0, highestRatedCount) as manga} - <li> - <a href={`https://anilist.co/manga/${manga.id}`} target="_blank"> - <MediaTitleDisplay title={manga.title} /> - </a> - {highestRatedMediaPercentage ? `: ${manga.mediaListEntry?.score}%` : ''} - </li> - {/each} - </ol> + {/if} + {#if mangaList !== undefined && mangaList.length !== 0} + <div class="category-grid pure-category category middle-category"> + <div class="grid-item image-grid"> + <a href={`https://anilist.co/manga/${mangaList[0].id}`} target="_blank"> + <img + src={proxy(mangaList[0].coverImage.extraLarge)} + alt="Highest Rated Manga Cover" + class="cover-image" + on:load={updateWidth} + /> + </a> + <div> + <b>{mangaMostTitle} Manga</b> + <ol> + {#each mangaList?.slice(0, highestRatedCount) as manga} + <li> + <a href={`https://anilist.co/manga/${manga.id}`} target="_blank"> + <MediaTitleDisplay title={manga.title} /> + </a> + {highestRatedMediaPercentage ? `: ${manga.mediaListEntry?.score}%` : ''} + </li> + {/each} + </ol> + </div> </div> </div> - </div> - {/if} - </div> - {/if} - {#if topMedia && topGenresTags && ((topMedia.topGenreMedia && topMedia.genres.length > 0) || (topMedia.topTagMedia && topMedia.tags.length > 0))} - <div class="categories-grid" style="padding-top: 0;"> - {#if topMedia.topGenreMedia && topMedia.genres.length > 0} - <div class="category-grid pure-category category"> - <div class="grid-item image-grid"> - <a - href={`https://anilist.co/${topMedia.topGenreMedia.type.toLowerCase()}/${ - topMedia.topGenreMedia.id - }`} - target="_blank" - > - <img - src={proxy(topMedia.topGenreMedia.coverImage.extraLarge)} - alt="Highest Rated Genre Cover" - class="cover-image" - on:load={updateWidth} - /> - </a> - <div> - <b>{genreTagTitle} Genres</b> - <ol> - {#each topMedia.genres as genre} - <li> - <a - href={`https://anilist.co/search/anime?genres=${genre.genre}`} - target="_blank" - > - {genre.genre}{highestRatedGenreTagPercentage - ? `: ${genre.averageScore}%` - : ''} - </a> - </li> - {/each} - </ol> + {/if} + </div> + {/if} + {#if topMedia && topGenresTags && ((topMedia.topGenreMedia && topMedia.genres.length > 0) || (topMedia.topTagMedia && topMedia.tags.length > 0))} + <div class="categories-grid" style="padding-top: 0;"> + {#if topMedia.topGenreMedia && topMedia.genres.length > 0} + <div class="category-grid pure-category category"> + <div class="grid-item image-grid"> + <a + href={`https://anilist.co/${topMedia.topGenreMedia.type.toLowerCase()}/${ + topMedia.topGenreMedia.id + }`} + target="_blank" + > + <img + src={proxy(topMedia.topGenreMedia.coverImage.extraLarge)} + alt="Highest Rated Genre Cover" + class="cover-image" + on:load={updateWidth} + /> + </a> + <div> + <b>{genreTagTitle} Genres</b> + <ol> + {#each topMedia.genres as genre} + <li> + <a + href={`https://anilist.co/search/anime?genres=${genre.genre}`} + target="_blank" + > + {genre.genre}{highestRatedGenreTagPercentage + ? `: ${genre.averageScore}%` + : ''} + </a> + </li> + {/each} + </ol> + </div> </div> </div> - </div> - {/if} - {#if topMedia.topTagMedia && topMedia.tags.length > 0} - <div class="category-grid pure-category category"> - <div class="grid-item image-grid"> - <a - href={`https://anilist.co/${topMedia.topTagMedia.type.toLowerCase()}/${ - topMedia.topTagMedia.id - }`} - target="_blank" - > - <img - src={proxy(topMedia.topTagMedia.coverImage.extraLarge)} - alt="Highest Rated Tag Cover" - class="cover-image" - on:load={updateWidth} - /> - </a> - <div> - <b>{genreTagTitle} Tags</b> - <ol> - {#each topMedia.tags as tag} - <li> - <a - href={`https://anilist.co/search/anime?genres=${tag.tag}`} - target="_blank" - > - {tag.tag}{highestRatedGenreTagPercentage - ? `: ${tag.averageScore}%` - : ''} - </a> - </li> - {/each} - </ol> + {/if} + {#if topMedia.topTagMedia && topMedia.tags.length > 0} + <div class="category-grid pure-category category"> + <div class="grid-item image-grid"> + <a + href={`https://anilist.co/${topMedia.topTagMedia.type.toLowerCase()}/${ + topMedia.topTagMedia.id + }`} + target="_blank" + > + <img + src={proxy(topMedia.topTagMedia.coverImage.extraLarge)} + alt="Highest Rated Tag Cover" + class="cover-image" + on:load={updateWidth} + /> + </a> + <div> + <b>{genreTagTitle} Tags</b> + <ol> + {#each topMedia.tags as tag} + <li> + <a + href={`https://anilist.co/search/anime?genres=${tag.tag}`} + target="_blank" + > + {tag.tag}{highestRatedGenreTagPercentage + ? `: ${tag.averageScore}%` + : ''} + </a> + </li> + {/each} + </ol> + </div> </div> </div> - </div> - {/if} - </div> - {/if} - {#if !disableActivityHistory && activityHistoryPosition === 'ORIGINAL'} - <div class="categories-grid" style="padding-top: 0;"> - <div class="category-grid bottom-category pure-category category"> - <div id="activity-history"> - <ActivityHistoryGrid {user} activityData={activities} /> + {/if} + </div> + {/if} + {#if !disableActivityHistory && activityHistoryPosition === 'ORIGINAL'} + <div class="categories-grid" style="padding-top: 0;"> + <div class="category-grid bottom-category pure-category category"> + <div id="activity-history"> + <ActivityHistoryGrid {user} activityData={activities} /> + </div> </div> </div> - </div> - {/if} - {#if watermark} - <div class="categories-grid" style="padding-top: 0;"> - <div class="category-grid pure-category" id="watermark"> - <a href="https://due.moe/wrapped" target="_blank">due.moe/wrapped</a> + {/if} + {#if watermark} + <div class="categories-grid" style="padding-top: 0;"> + <div class="category-grid pure-category" id="watermark"> + <a href="https://due.moe/wrapped" target="_blank">due.moe/wrapped</a> + </div> </div> - </div> - {/if} - </div> - - <p /> - - <p> - <a href={'#'} on:click={screenshot} data-umami-event="Generate Wrapped">Generate image</a> - </p> + {/if} + </div> + <div class="list"> + <p> + <a href={'#'} on:click={screenshot} data-umami-event="Generate Wrapped" + >Generate image</a + > + </p> - <details open> - <summary>Options</summary> - <div id="options"> <details open> - <summary>Display</summary> - - <input type="checkbox" bind:checked={watermark} /> Show watermark<br /> - <input type="checkbox" bind:checked={transparency} /> Enable background transparency<br - /> - <input type="checkbox" bind:checked={lightMode} /> - Enable light mode<br /> - <input type="checkbox" bind:checked={topGenresTags} /> - Show top genres and tags<br /> - <input type="checkbox" bind:checked={disableActivityHistory} /> Hide activity history<br - /> - <input type="checkbox" bind:checked={highestRatedMediaPercentage} /> Show highest rated - media percentages<br /> - <input type="checkbox" bind:checked={highestRatedGenreTagPercentage} /> Show highest - rated genre and tag percentages<br /> - <select bind:value={activityHistoryPosition}> - <option value="ORIGINAL">Original</option> - <option value="TOP">Top</option> - <option value="BELOW_TOP">Below Top</option> - </select> - Activity history position<br /> - <select bind:value={highestRatedCount}> - {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} - <option value={count}>{count}</option> - {/each} - </select> - Highest rated media count<br /> - <select bind:value={genreTagCount}> - {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} - <option value={count}>{count}</option> - {/each} - </select> - Highest genre and tag count<br /> - <button on:click={updateWidth}>Find best fit</button> - <button on:click={() => (width -= 25)}>-25px</button> - <button on:click={() => (width += 25)}>+25px</button> - Width adjustment<br /> + <summary>Options</summary> + <div id="options"> + <details open> + <summary>Display</summary> + + <input type="checkbox" bind:checked={watermark} /> Show watermark<br /> + <input type="checkbox" bind:checked={transparency} /> Enable background transparency<br + /> + <input type="checkbox" bind:checked={lightMode} /> + Enable light mode<br /> + <input type="checkbox" bind:checked={topGenresTags} /> + Show top genres and tags<br /> + <input type="checkbox" bind:checked={disableActivityHistory} /> Hide activity + history<br /> + <input type="checkbox" bind:checked={highestRatedMediaPercentage} /> Show highest + rated media percentages<br /> + <input type="checkbox" bind:checked={highestRatedGenreTagPercentage} /> Show highest + rated genre and tag percentages<br /> + <select bind:value={activityHistoryPosition}> + <option value="ORIGINAL">Original</option> + <option value="TOP">Top</option> + <option value="BELOW_TOP">Below Top</option> + </select> + Activity history position<br /> + <select bind:value={highestRatedCount}> + {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} + <option value={count}>{count}</option> + {/each} + </select> + Highest rated media count<br /> + <select bind:value={genreTagCount}> + {#each [3, 4, 5, 6, 7, 8, 9, 10] as count} + <option value={count}>{count}</option> + {/each} + </select> + Highest genre and tag count<br /> + <button on:click={updateWidth}>Find best fit</button> + <button on:click={() => (width -= 25)}>-25px</button> + <button on:click={() => (width += 25)}>+25px</button> + Width adjustment<br /> + </details> + + <p /> + + <details open> + <summary>Calculation</summary> + + <input type="checkbox" bind:checked={useFullActivityHistory} /> + Enable full-year activity<br /> + <SettingHint> + If you have many activities, you may rate-limited and you may need multiple + attempts to fully populate your local activity history database.<br />If you get + rate-limited, wait one minute, then try again. + <a href={'#'} on:click={pruneFullYear}>Refresh data</a> + </SettingHint><br /> + <p /> + <select bind:value={mediaSort}> + <option value={SortOptions.SCORE}>Score</option> + <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> + </select> + Anime and manga sort<br /> + <select bind:value={genreTagsSort}> + <option value={SortOptions.SCORE}>Score</option> + <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> + <option value={SortOptions.COUNT}>Count</option> + </select> + Genre and tag sort<br /> + <input type="checkbox" bind:checked={includeMusic} /> Include music<br /> + <input type="checkbox" bind:checked={includeRepeats} /> Include rewatches & rereads<br + /> + <input type="checkbox" bind:checked={includeSpecials} /> Include specials<br /> + <input type="checkbox" bind:checked={includeOVAs} /> Include OVAs<br /> + <input type="checkbox" bind:checked={includeMovies} /> Include movies<br /> + <input + type="text" + bind:value={excludedKeywordsInput} + on:keypress={(e) => { + e.key === 'Enter' && submitExcludedKeywords(); + }} + /> + Excluded keywords + <a href={`#`} on:click={submitExcludedKeywords} title="Or click your Enter key" + >Submit</a + > + <br /> + <SettingHint>Comma separated list (e.g., "My Hero, Kaguya")</SettingHint> + </details> + </div> </details> <p /> - <details open> - <summary>Calculation</summary> - - <input type="checkbox" bind:checked={useFullActivityHistory} /> - Enable full-year activity<br /> - <SettingHint> - If you have many activities, you may rate-limited and you may need multiple attempts - to fully populate your local activity history database.<br />If you get rate-limited, - wait one minute, then try again. - <a href={'#'} on:click={pruneFullYear}>Refresh data</a> - </SettingHint><br /> - <p /> - <select bind:value={mediaSort}> - <option value={SortOptions.SCORE}>Score</option> - <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> - </select> - Anime and manga sort<br /> - <select bind:value={genreTagsSort}> - <option value={SortOptions.SCORE}>Score</option> - <option value={SortOptions.MINUTES_WATCHED}>Minutes Watched/Read</option> - <option value={SortOptions.COUNT}>Count</option> - </select> - Genre and tag sort<br /> - <input type="checkbox" bind:checked={includeMusic} /> Include music<br /> - <input type="checkbox" bind:checked={includeRepeats} /> Include rewatches & rereads<br - /> - <input type="checkbox" bind:checked={includeSpecials} /> Include specials<br /> - <input type="checkbox" bind:checked={includeOVAs} /> Include OVAs<br /> - <input type="checkbox" bind:checked={includeMovies} /> Include movies<br /> - <input - type="text" - bind:value={excludedKeywordsInput} - on:keypress={(e) => { - e.key === 'Enter' && submitExcludedKeywords(); - }} - /> - Excluded keywords - <a href={`#`} on:click={submitExcludedKeywords} title="Or click your Enter key" - >Submit</a - > - <br /> - <SettingHint>Comma separated list (e.g., "My Hero, Kaguya")</SettingHint> - </details> - </div> - </details> - - <p /> + <div id="wrapped-final" /> - <div id="wrapped-final" /> - - {#if generated} - <p /> + {#if generated} + <p /> - <blockquote> - Click on the image to download, or right click and select "Save Image As...". - </blockquote> - {/if} + <blockquote> + Click on the image to download, or right click and select "Save Image As...". + </blockquote> + {/if} + </div> + </div> {:catch} <Error /> {/await} @@ -920,4 +923,15 @@ height: auto; width: 50%; } + + #list-container { + display: flex; + gap: 1rem; + flex-wrap: wrap; + } + + .list { + flex-grow: 1; + flex-basis: 1%; + } </style> |