diff options
Diffstat (limited to 'src/routes')
| -rw-r--r-- | src/routes/+error.svelte | 4 | ||||
| -rw-r--r-- | src/routes/+layout.svelte | 56 | ||||
| -rw-r--r-- | src/routes/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/api/authentication/log-out/+server.ts | 2 | ||||
| -rw-r--r-- | src/routes/api/oauth/refresh/+server.ts | 2 | ||||
| -rw-r--r-- | src/routes/completed/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/events/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/events/group/[group]/+page.svelte | 10 | ||||
| -rw-r--r-- | src/routes/events/groups/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/girls/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/girls/[language]/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/hololive/[[stream]]/+page.svelte | 10 | ||||
| -rw-r--r-- | src/routes/reader/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/schedule/+page.svelte | 4 | ||||
| -rw-r--r-- | src/routes/settings/+page.svelte | 9 | ||||
| -rw-r--r-- | src/routes/tools/+page.svelte | 8 | ||||
| -rw-r--r-- | src/routes/tools/[tool]/+page.svelte | 14 | ||||
| -rw-r--r-- | src/routes/updates/+page.svelte | 8 | ||||
| -rw-r--r-- | src/routes/user/[user]/+page.svelte | 54 | ||||
| -rw-r--r-- | src/routes/user/[user]/badges/+page.svelte | 240 |
20 files changed, 241 insertions, 204 deletions
diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index f822d521..26a7a69a 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -3,7 +3,7 @@ import { closest } from '$lib/Error/path'; import Popup from '$lib/Layout/Popup.svelte'; - $: suggestion = closest($page.url.pathname.replace('/', ''), [ + let suggestion = $derived(closest($page.url.pathname.replace('/', ''), [ 'birthdays', 'completed', 'schedule', @@ -13,7 +13,7 @@ 'updates', 'user', 'wrapped' - ]); + ])); </script> <Popup> diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 6d7fe757..3431bc86 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { run } from 'svelte/legacy'; + import type { SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease'; import { env } from '$env/dynamic/public'; import { userIdentity as getUserIdentity } from '$lib/Data/AniList/identity'; @@ -33,9 +35,9 @@ injectSpeedInsights(); - export let data; + let { data, children } = $props(); - let isHeaderVisible = true; + let isHeaderVisible = $state(true); let previousScrollPosition = 0; let notificationInterval: NodeJS.Timeout | undefined = undefined; @@ -43,7 +45,9 @@ addMessages('ja', japanese as unknown as LocaleDictionary); init({ fallbackLocale: 'en', initialLocale: $settings.displayLanguage }); - $: i18nLocale.set($settings.displayLanguage); + run(() => { + i18nLocale.set($settings.displayLanguage); + }); const navigationOrder = ['/', '/completed', '/schedule', '/updates', '/tools', '/settings']; const previousPage: Readable<string | null> = readable(null, (set) => { @@ -54,13 +58,15 @@ return () => unsubscribe(); }); - $: way = data.url.includes('/user') - ? 200 - : $previousPage && $previousPage.includes('/user') - ? -200 - : navigationOrder.indexOf(data.url) > navigationOrder.indexOf($previousPage ?? '/') - ? 200 - : -200; + let way = $derived( + data.url.includes('/user') + ? 200 + : $previousPage && $previousPage.includes('/user') + ? -200 + : navigationOrder.indexOf(data.url) > navigationOrder.indexOf($previousPage ?? '/') + ? 200 + : -200 + ); const handleScroll = () => { const currentScrollPosition = window.scrollY; @@ -127,7 +133,7 @@ if (notificationInterval) clearInterval(notificationInterval); }); - $: { + run(() => { if ((data.url === '/' || data.url === '/completed' || data.url === '/schedule') && !$subsPlease) fetch(root(`/api/subsplease?tz=${Intl.DateTimeFormat().resolvedOptions().timeZone}`)) .then((r) => r.json()) @@ -147,7 +153,7 @@ subsPlease.set(r); }); - } + }); </script> <HeadTitle /> @@ -225,7 +231,7 @@ <a class="header-item" href={`https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`} - on:click={() => { + onclick={() => { localStorage.setItem( 'redirect', window.location.origin + window.location.pathname + window.location.search @@ -242,12 +248,12 @@ </div> </div> - <p /> + <p></p> <Notifications item={EventNotification} zIndex={5000}> <Root {data} {way}> {#if $userIdentity.id !== -1} - <slot /> + {@render children?.()} {:else if data.url === '/settings'} <Skeleton grid={true} count={1} height="10vh" /> <Skeleton grid={true} count={1} height="30vh" /> @@ -263,8 +269,19 @@ <style lang="scss"> .header { - font-family: 'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, - Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: + 'DM Sans', + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Open Sans', + 'Helvetica Neue', + sans-serif; font-size: 1.05em; font-weight: 600; padding: 0.8rem 0.4rem; @@ -320,7 +337,10 @@ display: inline-block; vertical-align: middle; border-radius: 8px; - box-shadow: 0 1.5px 9px var(--base01), 0 0 0 4px var(--base0E), 0 4px 30px var(--base01); + box-shadow: + 0 1.5px 9px var(--base01), + 0 0 0 4px var(--base0E), + 0 4px 30px var(--base01); } .separator { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 653c3836..5c17dd7d 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -13,7 +13,7 @@ import Landing from '$lib/Landing.svelte'; import IndexColumn from '$lib/List/Anime/DueIndexColumn.svelte'; - export let data; + let { data } = $props(); let heightObserver: NodeJS.Timeout; @@ -29,7 +29,7 @@ {#if data.user === undefined} <div class="card">Please log in to view due media.</div> - <p /> + <p></p> <Landing /> {:else} diff --git a/src/routes/api/authentication/log-out/+server.ts b/src/routes/api/authentication/log-out/+server.ts index 305c846f..26b5dd2c 100644 --- a/src/routes/api/authentication/log-out/+server.ts +++ b/src/routes/api/authentication/log-out/+server.ts @@ -11,5 +11,5 @@ export const GET = ({ cookies }) => { secure: false }); - throw redirect(303, root('/')); + redirect(303, root('/')); }; diff --git a/src/routes/api/oauth/refresh/+server.ts b/src/routes/api/oauth/refresh/+server.ts index 66b4209c..13f4400c 100644 --- a/src/routes/api/oauth/refresh/+server.ts +++ b/src/routes/api/oauth/refresh/+server.ts @@ -25,6 +25,6 @@ export const GET = async ({ url, cookies }) => { secure: false }); - if (url.searchParams.get('redirect')) throw redirect(303, '/'); + if (url.searchParams.get('redirect')) redirect(303, '/'); else return Response.json(newUser); }; diff --git a/src/routes/completed/+page.svelte b/src/routes/completed/+page.svelte index d483d7fe..73968227 100644 --- a/src/routes/completed/+page.svelte +++ b/src/routes/completed/+page.svelte @@ -12,7 +12,7 @@ import locale from '$stores/locale.js'; import Landing from '$lib/Landing.svelte'; - export let data; + let { data } = $props(); let heightObserver: NodeJS.Timeout; @@ -28,7 +28,7 @@ {#if data.user === undefined} <div class="card">Please log in to view completed media.</div> - <p /> + <p></p> <Landing /> {:else} diff --git a/src/routes/events/+page.svelte b/src/routes/events/+page.svelte index d3270e30..1c6e2524 100644 --- a/src/routes/events/+page.svelte +++ b/src/routes/events/+page.svelte @@ -16,7 +16,7 @@ <Event event={rawEvent} avatar /> {#if i < events.length - 1} - <p /> + <p></p> {/if} {/each} {/if} diff --git a/src/routes/events/group/[group]/+page.svelte b/src/routes/events/group/[group]/+page.svelte index 37c23c40..28974fd3 100644 --- a/src/routes/events/group/[group]/+page.svelte +++ b/src/routes/events/group/[group]/+page.svelte @@ -7,9 +7,9 @@ import Group from '$lib/Events/Group.svelte'; import Event from '$lib/Events/Event.svelte'; - export let data; + let { data } = $props(); - let groupsResponse: Promise<Response>; + let groupsResponse: Promise<Response> = $state(); onMount(async () => { groupsResponse = fetch(root(`/api/events/group?slug=${data.group}`)); @@ -30,14 +30,14 @@ {#if json === null} <Message message="" loader="ripple" slot> This group may not exist. Please - <a href={'#'} on:click={() => location.reload()}>try again</a> later. + <a href={'#'} onclick={() => location.reload()}>try again</a> later. </Message> {:else} {@const group = asGroup(json)} <Group {group} /> - <p /> + <p></p> <details open> <summary>Events</summary> @@ -53,7 +53,7 @@ <Event event={asEvent(rawEvent)} /> {#if i < events.length - 1} - <p /> + <p></p> {/if} {/each} {/if} diff --git a/src/routes/events/groups/+page.svelte b/src/routes/events/groups/+page.svelte index d90cce34..930e2d37 100644 --- a/src/routes/events/groups/+page.svelte +++ b/src/routes/events/groups/+page.svelte @@ -5,7 +5,7 @@ import { onMount } from 'svelte'; import Group from '$lib/Events/Group.svelte'; - let groupsResponse: Promise<Response>; + let groupsResponse: Promise<Response> = $state(); onMount(async () => { groupsResponse = fetch(root('/api/events/groups')); @@ -29,7 +29,7 @@ </a> {#if i < json.length - 1} - <p /> + <p></p> {/if} {/each} {:catch} diff --git a/src/routes/girls/+page.svelte b/src/routes/girls/+page.svelte index 71982c32..ecd4acd0 100644 --- a/src/routes/girls/+page.svelte +++ b/src/routes/girls/+page.svelte @@ -27,7 +27,7 @@ <div> The Senpy Club <span class="opaque">|</span> Anime Girls Holding Programming Books - <p /> + <p></p> <ul> <li> @@ -65,7 +65,7 @@ </div> </div> -<p /> +<p></p> <details class="languages" open> <summary>Languages</summary> diff --git a/src/routes/girls/[language]/+page.svelte b/src/routes/girls/[language]/+page.svelte index 91b18628..d61af7db 100644 --- a/src/routes/girls/[language]/+page.svelte +++ b/src/routes/girls/[language]/+page.svelte @@ -4,7 +4,7 @@ import Skeleton from '$lib/Loading/Skeleton.svelte'; import '$styles/girls.scss'; - export let data; + let { data } = $props(); </script> <div class="card"> diff --git a/src/routes/hololive/[[stream]]/+page.svelte b/src/routes/hololive/[[stream]]/+page.svelte index d5419711..33126762 100644 --- a/src/routes/hololive/[[stream]]/+page.svelte +++ b/src/routes/hololive/[[stream]]/+page.svelte @@ -11,10 +11,10 @@ import Lives from '$lib/Hololive/Lives.svelte'; import { typeSchedule } from '$lib/Hololive/hololive'; - export let data; + let { data } = $props(); - let schedulePromise: Promise<Response>; - let pinnedStreams: string[] = []; + let schedulePromise: Promise<Response> = $state(); + let pinnedStreams: string[] = $state([]); onMount(() => getPinnedStreams()); @@ -66,7 +66,7 @@ {:catch} <Message loader="ripple" slot> {$locale().hololive.parseError} - <a href={'#'} on:click={() => location.reload()}>Try again?</a> + <a href={'#'} onclick={() => location.reload()}>Try again?</a> </Message> {/await} {:else} @@ -77,6 +77,6 @@ {:catch} <Message loader="ripple" slot> {$locale().hololive.loadError} Please - <a href={'#'} on:click={() => location.reload()}>try again</a> later. + <a href={'#'} onclick={() => location.reload()}>try again</a> later. </Message> {/await} diff --git a/src/routes/reader/+page.svelte b/src/routes/reader/+page.svelte index 775d3659..cff5ca3e 100644 --- a/src/routes/reader/+page.svelte +++ b/src/routes/reader/+page.svelte @@ -6,9 +6,9 @@ import { decodeResource, fetchResource, identify, Resource } from '$lib/Reader/resource'; import InputTemplate from '$lib/Tools/InputTemplate.svelte'; - let submission = ''; + let submission = $state(''); - $: resourceIdentity = identify(submission); + let resourceIdentity = $derived(identify(submission)); </script> <InputTemplate field="Manga URL" bind:submission submitText="Read" preserveCase> diff --git a/src/routes/schedule/+page.svelte b/src/routes/schedule/+page.svelte index 70b1e1e4..3393cced 100644 --- a/src/routes/schedule/+page.svelte +++ b/src/routes/schedule/+page.svelte @@ -14,9 +14,9 @@ import Message from '$lib/Loading/Message.svelte'; import subsPlease from '$stores/subsPlease'; - export let data; + let { data } = $props(); - let scheduledMediaPromise: Promise<Partial<Media[]>>; + let scheduledMediaPromise: Promise<Partial<Media[]>> = $state(); const urlParameters = browser ? new URLSearchParams(window.location.search) : null; // let crunchyrollExpanded = false; let forceListMode = parseOrDefault(urlParameters, 'list', false); diff --git a/src/routes/settings/+page.svelte b/src/routes/settings/+page.svelte index 42ee4edd..816eaab7 100644 --- a/src/routes/settings/+page.svelte +++ b/src/routes/settings/+page.svelte @@ -1,4 +1,7 @@ <script lang="ts"> + import { createBubbler, preventDefault } from 'svelte/legacy'; + + const bubble = createBubbler(); /* eslint svelte/no-at-html-tags: "off" */ import Attributions from '$lib/Settings/Categories/Attributions.svelte'; @@ -15,7 +18,7 @@ import SettingSync from '$lib/Settings/Categories/SettingSync.svelte'; import RssFeeds from '$lib/Settings/Categories/RSSFeeds.svelte'; - export let data; + let { data } = $props(); // const pruneUnresolved = async () => { // const unresolved = await chapterDatabase.chapters.where('chapters').equals(-1).toArray(); @@ -71,7 +74,7 @@ </Category> </div> - <p /> + <p></p> <Category title={$locale().settings.display.title}><Display /></Category> <Category title={$locale().settings.calculation.title}><Calculation /></Category> @@ -83,7 +86,7 @@ class="smaller-button button-badge badge-info unclickable-button" title={$locale().settings.debug.tooltips.version} use:tooltip - on:click|preventDefault + onclick={preventDefault(bubble('click'))} >{data.commit.slice(0, 7)} </button></summary > diff --git a/src/routes/tools/+page.svelte b/src/routes/tools/+page.svelte index d1650b34..139588a7 100644 --- a/src/routes/tools/+page.svelte +++ b/src/routes/tools/+page.svelte @@ -4,7 +4,7 @@ import { tools } from '$lib/Tools/tools.js'; import root from '$lib/Utility/root'; - let tool = 'default'; + let tool = $state('default'); </script> <Picker {tool} /> @@ -14,13 +14,13 @@ <div class="card"> <div class="tool-grid"> {#each Object.keys(tools).filter((t) => t !== 'default' && !tools[t].hidden) as t} - <a href={root(`/tools/${tools[t].id}`)} on:click={() => (tool = t)}> + <a href={root(`/tools/${tools[t].id}`)} onclick={() => (tool = t)}> <div class="tool-grid-tool card"> <span class="title"> {tools[t].name()} </span> - <p /> + <p></p> {#if tools[t].description} <span class="description"> @@ -32,7 +32,7 @@ {/each} </div> - <p /> + <p></p> <blockquote style="margin: 0 0 0 1.5rem;"> Have any requests for cool tools that you think others might find useful? Send a private message diff --git a/src/routes/tools/[tool]/+page.svelte b/src/routes/tools/[tool]/+page.svelte index c811cf2a..9c7796ba 100644 --- a/src/routes/tools/[tool]/+page.svelte +++ b/src/routes/tools/[tool]/+page.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { run } from 'svelte/legacy'; + import Hayai from './../../../lib/Tools/Hayai.svelte'; import UmaMusumeBirthdays from './../../../lib/Tools/UmaMusumeBirthdays.svelte'; import ActivityHistory from '$lib/Tools/ActivityHistory/Tool.svelte'; @@ -21,17 +23,19 @@ import SequelCatcher from '$lib/Tools/SequelCatcher/Tool.svelte'; import Tracker from '$lib/Tools/Tracker/Tool.svelte'; - export let data; + let { data } = $props(); - let tool = data.tool ?? 'default'; + let tool = $state(data.tool ?? 'default'); onMount(() => { if (tool === 'default') goto(root('/tools')); }); - $: suggestion = closest(tool, Object.keys(tools)); + let suggestion = $derived(closest(tool, Object.keys(tools))); - $: if (tool == 'girls') goto(root('/girls')); + run(() => { + if (tool == 'girls') goto(root('/girls')); + }); </script> <Picker bind:tool /> @@ -47,7 +51,7 @@ <blockquote style="margin: 0 0 0 1.5rem;"> Did you mean "<a href={root(`/tools/${tools[suggestion].id}`)} - on:click={() => (tool = suggestion)} + onclick={() => (tool = suggestion)} style={suggestion === '...' ? 'pointer-events: none; color: inherit;' : ''} > {suggestion === '...' ? '...' : tools[suggestion].name()}</a diff --git a/src/routes/updates/+page.svelte b/src/routes/updates/+page.svelte index 9af001b4..f2657ab0 100644 --- a/src/routes/updates/+page.svelte +++ b/src/routes/updates/+page.svelte @@ -9,17 +9,17 @@ import { onDestroy, onMount } from 'svelte'; let feed: { items: { title: string; link: string; content: string }[] } | null | undefined = - undefined; + $state(undefined); let novelFeed: | { data: { items: { srcurl: string; postfix?: string; chapter: number; series: { name: string } }[]; }; } - | undefined = undefined; + | undefined = $state(undefined); let startTime: number; - let mangaEndTime: number; - let novelEndTime: number; + let mangaEndTime: number = $state(); + let novelEndTime: number = $state(); let directLink = browser ? new URLSearchParams(window.location.search).has('d') : false; let heightObserver: NodeJS.Timeout; diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index d60ea8e5..1a36ccb5 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -22,10 +22,10 @@ import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; import { graphql } from '$houdini'; - export let data; + let { data } = $props(); - $: ({ Profile } = data); - $: preferences = $Profile.fetching ? undefined : ($Profile.data?.User.preferences as Preferences); + let { Profile } = $derived(data); + let preferences = $derived($Profile.fetching ? undefined : ($Profile.data?.User.preferences as Preferences)); const setCategoriesQuery = graphql(` mutation SetCategories($categories: [String!]!) { @@ -99,20 +99,20 @@ } `); - $: userData = data.userData; + let userData = $derived(data.userData); let error = false; - let schedule: ParseResult | undefined = undefined; + let schedule: ParseResult | undefined = $state(undefined); let draggedCategory: string | null = null; let draggedOverCategory: string | null = null; - $: displayBadges = (username: string, badges: number | string) => + let displayBadges = $derived((username: string, badges: number | string) => $locale({ values: { badges: badges, username } - }).user.profile.badges; + }).user.profile.badges); const handleDragStart = ( event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, @@ -302,7 +302,7 @@ {#if schedule && preferences && preferences.biography && preferences.biography.length > 0} <br /> {:else} - <p /> + <p></p> {/if} {#if $Profile.fetching} @@ -325,7 +325,7 @@ {/if} {#if schedule && preferences && preferences.pinned_hololive_streams.length > 0} - <p /> + <p></p> <div class="card"> <div class="hololive-badges"> @@ -352,14 +352,14 @@ {/if} {#if preferences && userData && userData.id === $identity.id} - <p /> + <p></p> <details open> <summary>{$locale().user.preferences.title}</summary> <input type="checkbox" - on:change={() => { + onchange={() => { if (userData) toggleHideMissingBadgesQuery.mutate(null).then(); }} checked={preferences.hide_missing_badges} @@ -367,18 +367,18 @@ {$locale().user.preferences.hideMissingBadges.title} <SettingHint lineBreak>{$locale().user.preferences.hideMissingBadges.hint}</SettingHint> - <p /> + <p></p> <input type="checkbox" - on:change={() => { + onchange={() => { if (userData) toggleHideAWCBadgesQuery.mutate(null).then(); }} checked={preferences.hide_awc_badges} /> {$locale().user.preferences.hideAWCBadges.title} - <p /> + <p></p> Pinned Categories @@ -387,11 +387,11 @@ <div class="card card-small pinned-category" draggable="true" - on:dragstart={(event) => handleDragStart(event, category)} - on:dragover={handleDragOver} - on:dragenter={(event) => handleDragEnter(event, category)} - on:dragleave={(event) => handleDragLeave(event, category)} - on:drop={handleDrop} + ondragstart={(event) => handleDragStart(event, category)} + ondragover={handleDragOver} + ondragenter={(event) => handleDragEnter(event, category)} + ondragleave={(event) => handleDragLeave(event, category)} + ondrop={handleDrop} role="button" tabindex="0" > @@ -400,7 +400,7 @@ </span> <button - on:click={() => { + onclick={() => { if (userData) toggleCategoryQuery.mutate({ category }).then(); }}>Remove</button > @@ -412,16 +412,16 @@ <input type="text" id="category" placeholder="Category" style="width: 10em;" /> </span> - <button class="button-lined" on:click={toggleCategory}>Add</button> + <button class="button-lined" onclick={toggleCategory}>Add</button> </span> </div> - <p /> + <p></p> Biography <button - on:click={() => { + onclick={() => { if (userData) setBiographyQuery .mutate({ @@ -436,14 +436,14 @@ cols="100" id="biography" placeholder="Markdown supported!" - /> +></textarea> - <p /> + <p></p> Badge Wall Custom CSS <button - on:click={() => { + onclick={() => { if (userData) setBadgeWallCSSQuery .mutate({ @@ -458,7 +458,7 @@ cols="100" id="badgeWallCSS" placeholder="/* Use classes and IDs such as .badges, #badges, .badge, or standard elements like body and details, or anything, as long as it's valid CSS! */" - /> +></textarea> </details> {/if} {/if} diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 44dd852a..8fe2dbbb 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { run } from 'svelte/legacy'; + import AWC from './../../../../lib/User/BadgeWall/AWC.svelte'; import { user, type User } from '$lib/Data/AniList/user'; import type { Badge } from '../../../../graphql/$types'; @@ -24,32 +26,34 @@ import { graphql } from '$houdini'; import type { Preferences } from '../../../../graphql/user/$types'; - export let data; + let { data } = $props(); - $: ({ BadgeWallUser } = data); - $: preferences = $BadgeWallUser.fetching + let { BadgeWallUser } = $derived(data); + let preferences = $derived($BadgeWallUser.fetching ? undefined - : ($BadgeWallUser.data?.User.preferences as Preferences); - - $: if (browser && preferences && preferences.badge_wall_css) { - const sanitise = (css: string) => - css - .replace(/\/\*[\s\S]*?\*\//g, '') - .replace(/<\/?[^>]+(>|$)/g, '') - .replace( - /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi, - '' - ) - .replace(/(behaviour|behavior|moz-binding|content):/gi, '') - .replace(/\s+/g, ' ') - .trim(); - const style = document.createElement('style'); - - style.dataset.badgeWall = 'true'; - style.innerHTML = sanitise(preferences.badge_wall_css); - - document.head.appendChild(style); - } + : ($BadgeWallUser.data?.User.preferences as Preferences)); + + run(() => { + if (browser && preferences && preferences.badge_wall_css) { + const sanitise = (css: string) => + css + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/<\/?[^>]+(>|$)/g, '') + .replace( + /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi, + '' + ) + .replace(/(behaviour|behavior|moz-binding|content):/gi, '') + .replace(/\s+/g, ' ') + .trim(); + const style = document.createElement('style'); + + style.dataset.badgeWall = 'true'; + style.innerHTML = sanitise(preferences.badge_wall_css); + + document.head.appendChild(style); + } + }); const updateBadgeQuery = graphql(` mutation UpdateBadge( @@ -176,26 +180,26 @@ image: string; } - let editMode = false; - let importMode = false; - let error: null | string; - let awcPromise: Promise<Response>; + let editMode = $state(false); + let importMode = $state(false); + let error: null | string = $state(); + let awcPromise: Promise<Response> = $state(); let confirmDelete = 0; - let confirmPrune = 0; - let selectedBadge: IndexedBadge | undefined = undefined; - let loadError: string | null = null; + let confirmPrune = $state(0); + let selectedBadge: IndexedBadge | undefined = $state(undefined); + let loadError: string | null = $state(null); const isId = /^\d+$/.test(data.username); - let importImages: ImportImage[] | undefined = undefined; - let importLinks = false; + let importImages: ImportImage[] | undefined = $state(undefined); + let importLinks = $state(false); let importCategory = ''; - let importReplies = false; + let importReplies = $state(false); let badger: Partial<User>; - let migrateMode = false; - let hideMode = false; + let migrateMode = $state(false); + let hideMode = $state(false); const authorised = authorisedJson.includes($identity.id); - let noticeDismissed = false; + let noticeDismissed = $state(false); - $: categoryFilter = new URLSearchParams($page.url.searchParams).get('category'); + let categoryFilter = $derived(new URLSearchParams($page.url.searchParams).get('category')); type GroupedBadges = { [key: string]: IndexedBadge[] }; @@ -557,7 +561,7 @@ <b>Notice:</b> The Badge Wall overseer system has detected badges containing AI-generated material on your wall. {shadowHiddenCount} of your badges have been shadow hidden. - <p /> + <p></p> You may use the "Un-shadow Hide Badges" button to unhide these badges, from where you will be required to use the hide feature to hide these badges from the public, while allowing them to stay visible to you as the account holder. @@ -568,12 +572,12 @@ material, this includes Badge Wall. If you have collected badges with AI-generated elements, kindly use the hide feature to hide these badges from the public, while allowing them to stay visible to you as the account holder. - <p /> + <p></p> Failure to comply with this request at your earliest convenience will result in the hiding of all badges from your Badge Wall. - <p /> + <p></p> <button - on:click={() => { + onclick={() => { noticeDismissed = true; localStorage.setItem('badgeWallNoticeDismissed', 'true'); @@ -584,11 +588,11 @@ </div> {/if} - <p /> + <p></p> <div class="card"> {#if authorised} - <button on:click={setShadowHide}>Shadow Hide Badges</button> + <button onclick={setShadowHide}>Shadow Hide Badges</button> {/if} {#if isOwner && authorised} @@ -597,7 +601,7 @@ {#if isOwner} <button - on:click={() => { + onclick={() => { selectedBadge = undefined; editMode = !editMode; }} @@ -608,7 +612,7 @@ </button> <span style="margin: 0 0.625rem;">•</span> <button - on:click={() => { + onclick={() => { selectedBadge = undefined; importMode = !importMode; }} @@ -619,7 +623,7 @@ </button> <span style="margin: 0 0.625rem;">•</span> <button - on:click={() => { + onclick={() => { selectedBadge = undefined; migrateMode = !migrateMode; }} @@ -628,7 +632,7 @@ </button> <span style="margin: 0 0.625rem;">•</span> <button - on:click={() => { + onclick={() => { selectedBadge = undefined; hideMode = !hideMode; }} @@ -640,7 +644,7 @@ {#if shadowHidden} <span style="margin: 0 0.625rem;">•</span> - <button on:click={setShadowHide}>Un-shadow Hide Badges</button> + <button onclick={setShadowHide}>Un-shadow Hide Badges</button> {/if} {#if editMode && isOwner} @@ -659,7 +663,7 @@ ) ])} - <p /> + <p></p> {#if error} <p style="color: red;">{error}</p> @@ -709,22 +713,24 @@ header={false} center={false} > - <span slot="title"> - <input - type="text" - placeholder={$locale().user.badges.editMode.category} - name="category" - minlength="1" - maxlength="1000" - size="15" - value={selectedBadge - ? selectedBadge.category === 'Uncategorised' - ? '' - : selectedBadge.category - : ''} - list="categories" - /> - </span> + {#snippet title()} + <span > + <input + type="text" + placeholder={$locale().user.badges.editMode.category} + name="category" + minlength="1" + maxlength="1000" + size="15" + value={selectedBadge + ? selectedBadge.category === 'Uncategorised' + ? '' + : selectedBadge.category + : ''} + list="categories" + /> + </span> + {/snippet} </Dropdown> <span style="float: right;"> <input @@ -736,7 +742,7 @@ <small>Must be full date and time, defaults to now if any fields empty</small> </span> - <p /> + <p></p> <div class="edit-row-2"> <input @@ -762,17 +768,19 @@ header={false} center={false} > - <span slot="title"> - <input - type="text" - placeholder={$locale().user.badges.editMode.designer} - name="designer" - minlength="1" - maxlength="1000" - size="17" - value={selectedBadge ? selectedBadge.designer : ''} - /> - </span> + {#snippet title()} + <span > + <input + type="text" + placeholder={$locale().user.badges.editMode.designer} + name="designer" + minlength="1" + maxlength="1000" + size="17" + value={selectedBadge ? selectedBadge.designer : ''} + /> + </span> + {/snippet} </Dropdown> <Dropdown items={[false, true].map((hidden) => ({ @@ -788,23 +796,25 @@ header={false} center={false} > - <span slot="title"> - <input - type="text" - placeholder="Shown" - name="hidden" - minlength="1" - maxlength="1000" - size="15" - value={selectedBadge - ? selectedBadge.hidden - ? 'Hidden' - : 'Shown' - : 'Shown'} - /> - </span> + {#snippet title()} + <span > + <input + type="text" + placeholder="Shown" + name="hidden" + minlength="1" + maxlength="1000" + size="15" + value={selectedBadge + ? selectedBadge.hidden + ? 'Hidden' + : 'Shown' + : 'Shown'} + /> + </span> + {/snippet} </Dropdown> - <button class="button-lined" on:click={submitBadge} + <button class="button-lined" onclick={submitBadge} >{selectedBadge ? $locale().user.badges.editMode.update : $locale().user.badges.editMode.add}</button @@ -813,7 +823,7 @@ {$locale().user.badges.editMode.or} <button class="button-lined" - on:click={() => { + onclick={() => { if (selectedBadge) removeBadge(selectedBadge); }}>{$locale().user.badges.editMode.delete}</button > @@ -824,7 +834,7 @@ </div> {/if} - <p /> + <p></p> <Badges {ungroupedBadges} @@ -858,7 +868,7 @@ /> {#if authorised} - <button on:click={shadowHideBadge}> + <button onclick={shadowHideBadge}> {#if selectedBadge && selectedBadge.shadow_hidden} Un-shadow {:else} @@ -875,7 +885,7 @@ <Popup fullscreen onLeave={() => (importMode = false)} show={importMode}> {$locale().user.badges.importMode.title} - <p /> + <p></p> <input type="text" @@ -894,7 +904,7 @@ size="20" /> - <p /> + <p></p> <input type="checkbox" id="import_links" name="import_links" bind:checked={importLinks} /> {$locale().user.badges.importMode.importLinks.title} @@ -902,15 +912,15 @@ {$locale().user.badges.importMode.importLinks.hint} </SettingHint> - <p /> + <p></p> <input type="checkbox" id="import_links" name="import_links" bind:checked={importReplies} /> {$locale().user.badges.importMode.importReplies} - <p /> + <p></p> <button - on:click={() => { + onclick={() => { importMode = false; importImages = undefined; }} @@ -918,11 +928,11 @@ > {$locale().user.badges.importMode.cancel} </button> - <button on:click={() => parsePost()} class="button-lined" style="float: right;"> + <button onclick={() => parsePost()} class="button-lined" style="float: right;"> {$locale().user.badges.importMode.fetch} </button> - <p /> + <p></p> <details> <summary>{$locale().user.badges.importMode.dangerous}</summary> @@ -930,7 +940,7 @@ <button class="button-lined no-shadow" data-umami-event="Remove All Badges" - on:click={removeAllBadges} + onclick={removeAllBadges} > {$locale({ values: { @@ -944,7 +954,7 @@ </details> {#if importImages && importImages.length > 0} - <p /> + <p></p> {$locale({ values: { @@ -952,7 +962,7 @@ } }).user.badges.importMode.importConfirm} <button - on:click={() => importBadges()} + onclick={() => importBadges()} class="button-lined no-shadow" data-umami-event="Import Badges" > @@ -969,7 +979,7 @@ <Popup fullscreen onLeave={() => (migrateMode = false)} show={migrateMode}> Migrate Category - <p /> + <p></p> <input type="text" @@ -989,10 +999,10 @@ /> <SettingHint lineBreak>Leave category empty to migrate all to or from uncategorised.</SettingHint> - <p /> + <p></p> <button - on:click={() => { + onclick={() => { importMode = false; importImages = undefined; }} @@ -1000,7 +1010,7 @@ > {$locale().user.badges.importMode.cancel} </button> - <button on:click={() => migrateCategory()} class="button-lined" style="float: right;"> + <button onclick={() => migrateCategory()} class="button-lined" style="float: right;"> Migrate </button> </Popup> @@ -1013,7 +1023,7 @@ versa. </SettingHint> - <p /> + <p></p> <input type="text" @@ -1025,10 +1035,10 @@ /> <SettingHint lineBreak>Leave category field empty to hide all.</SettingHint> - <p /> + <p></p> <button - on:click={() => { + onclick={() => { hideMode = false; importImages = undefined; }} @@ -1036,7 +1046,7 @@ > {$locale().user.badges.importMode.cancel} </button> - <button on:click={() => hideCategory()} class="button-lined" style="float: right;" + <button onclick={() => hideCategory()} class="button-lined" style="float: right;" >Toggle Visibility</button > </Popup> |