diff options
| author | Fuwn <[email protected]> | 2026-03-01 16:04:11 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-03-01 16:04:11 -0800 |
| commit | 48f0c30d47d62e4f35706edb93a1bb2f97eba14c (patch) | |
| tree | 44866d7a61adfdf01a780e0108c370294d3db78b /src/routes/user | |
| parent | chore(biome): re-enable useAltText rule (diff) | |
| download | due.moe-48f0c30d47d62e4f35706edb93a1bb2f97eba14c.tar.xz due.moe-48f0c30d47d62e4f35706edb93a1bb2f97eba14c.zip | |
chore(biome): enable svelte formatting
Diffstat (limited to 'src/routes/user')
| -rw-r--r-- | src/routes/user/+page.svelte | 44 | ||||
| -rw-r--r-- | src/routes/user/[user]/+page.svelte | 256 | ||||
| -rw-r--r-- | src/routes/user/[user]/badges/+page.svelte | 674 |
3 files changed, 487 insertions, 487 deletions
diff --git a/src/routes/user/+page.svelte b/src/routes/user/+page.svelte index eab089c6..3589f073 100644 --- a/src/routes/user/+page.svelte +++ b/src/routes/user/+page.svelte @@ -1,31 +1,31 @@ <script lang="ts"> - import { browser } from '$app/environment'; - import { goto } from '$app/navigation'; - import type { UserIdentity } from '$lib/Data/AniList/identity'; - import { onMount } from 'svelte'; - import { env } from '$env/dynamic/public'; - import HeadTitle from '$lib/Home/HeadTitle.svelte'; - import root from '$lib/Utility/root'; - import { page } from '$app/stores'; - import localforage from 'localforage'; +import { browser } from '$app/environment'; +import { goto } from '$app/navigation'; +import type { UserIdentity } from '$lib/Data/AniList/identity'; +import { onMount } from 'svelte'; +import { env } from '$env/dynamic/public'; +import HeadTitle from '$lib/Home/HeadTitle.svelte'; +import root from '$lib/Utility/root'; +import { page } from '$app/stores'; +import localforage from 'localforage'; - onMount(async () => { - if (browser) { - const user = ((await localforage.getItem('identity')) as UserIdentity).name; +onMount(async () => { + if (browser) { + const user = ((await localforage.getItem('identity')) as UserIdentity).name; - if (user) { - if (browser && $page.url.searchParams.get('badges') !== null) { - goto(root(`/user/${user}/badges`)); - } else { - goto(root(`/user/${user}`)); - } + if (user) { + if (browser && $page.url.searchParams.get('badges') !== null) { + goto(root(`/user/${user}/badges`)); } else { - goto( - `https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code` - ); + goto(root(`/user/${user}`)); } + } else { + goto( + `https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code` + ); } - }); + } +}); </script> <HeadTitle route="Profile" path="/user" /> diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 3c581c38..dd9d753e 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -1,36 +1,36 @@ <script lang="ts"> - import Spacer from '$lib/Layout/Spacer.svelte'; - import settings from '$stores/settings'; - import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte'; - import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive'; - import HeadTitle from '$lib/Home/HeadTitle.svelte'; - import Message from '$lib/Loading/Message.svelte'; - import { estimatedDayReading } from '$lib/Media/Manga/time'; - import Skeleton from '$lib/Loading/Skeleton.svelte'; - import root from '$lib/Utility/root'; - import locale from '$stores/locale'; - import { onMount } from 'svelte'; - import authorisedUsers from '$lib/Data/Static/authorised.json'; - import tooltip from '$lib/Tooltip/tooltip'; - import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte'; - import identity from '$stores/identity'; - import SettingHint from '$lib/Settings/SettingHint.svelte'; - import proxy from '$lib/Utility/proxy'; - import { parseScheduleHtml } from '$lib/Data/hololive'; - import type { Preferences } from '../../../graphql/$types'; - import SvelteMarkdown from '@humanspeak/svelte-markdown'; - import MarkdownLink from '$lib/MarkdownLink.svelte'; - import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; - import { graphql } from '$houdini'; - - export let data; - - $: ({ Profile } = data); - $: preferences = $Profile.fetching - ? undefined - : ($Profile.data?.User?.preferences as Preferences | undefined); - - const setCategoriesQuery = graphql(` +import Spacer from '$lib/Layout/Spacer.svelte'; +import settings from '$stores/settings'; +import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte'; +import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive'; +import HeadTitle from '$lib/Home/HeadTitle.svelte'; +import Message from '$lib/Loading/Message.svelte'; +import { estimatedDayReading } from '$lib/Media/Manga/time'; +import Skeleton from '$lib/Loading/Skeleton.svelte'; +import root from '$lib/Utility/root'; +import locale from '$stores/locale'; +import { onMount } from 'svelte'; +import authorisedUsers from '$lib/Data/Static/authorised.json'; +import tooltip from '$lib/Tooltip/tooltip'; +import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte'; +import identity from '$stores/identity'; +import SettingHint from '$lib/Settings/SettingHint.svelte'; +import proxy from '$lib/Utility/proxy'; +import { parseScheduleHtml } from '$lib/Data/hololive'; +import type { Preferences } from '../../../graphql/$types'; +import SvelteMarkdown from '@humanspeak/svelte-markdown'; +import MarkdownLink from '$lib/MarkdownLink.svelte'; +import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; +import { graphql } from '$houdini'; + +export let data; + +$: ({ Profile } = data); +$: preferences = $Profile.fetching + ? undefined + : ($Profile.data?.User?.preferences as Preferences | undefined); + +const setCategoriesQuery = graphql(` mutation SetCategories($categories: [String!]!) { setPinnedBadgeWallCategories(categories: $categories) { id @@ -42,7 +42,7 @@ } `); - const toggleCategoryQuery = graphql(` +const toggleCategoryQuery = graphql(` mutation ToggleCategory($category: String!) { togglePinnedBadgeWallCategory(category: $category) { id @@ -54,7 +54,7 @@ } `); - const toggleHideMissingBadgesQuery = graphql(` +const toggleHideMissingBadgesQuery = graphql(` mutation ToggleHideMissingBadges { toggleHideMissingBadges { id @@ -66,7 +66,7 @@ } `); - const toggleHideAWCBadgesQuery = graphql(` +const toggleHideAWCBadgesQuery = graphql(` mutation ToggleHideAWCBadges { toggleHideAWCBadges { id @@ -78,7 +78,7 @@ } `); - const setBiographyQuery = graphql(` +const setBiographyQuery = graphql(` mutation SetBiography($biography: String!) { setBiography(biography: $biography) { id @@ -90,7 +90,7 @@ } `); - const setBadgeWallCSSQuery = graphql(` +const setBadgeWallCSSQuery = graphql(` mutation SetBadgeWallCSS($css: String!) { setBadgeWallCSS(css: $css) { id @@ -102,121 +102,121 @@ } `); - $: userData = data.userData; +$: userData = data.userData; - let error = false; - let schedule: ParseResult | undefined = undefined; - let draggedCategory: string | null = null; - let draggedOverCategory: string | null = null; +let error = false; +let schedule: ParseResult | undefined = undefined; +let draggedCategory: string | null = null; +let draggedOverCategory: string | null = null; - $: displayBadges = (username: string, badges: number | string) => - $locale({ - values: { - badges: badges, - username - } - }).user.profile.badges; - - const handleDragStart = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string | null - ) => { - draggedCategory = category; - - if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'; - }; +$: displayBadges = (username: string, badges: number | string) => + $locale({ + values: { + badges: badges, + username + } + }).user.profile.badges; - const handleDragOver = (event: DragEvent) => { - event.preventDefault(); +const handleDragStart = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null +) => { + draggedCategory = category; - if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'; - }; + if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'; +}; - const handleDragEnter = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string | null - ) => { - event.preventDefault(); +const handleDragOver = (event: DragEvent) => { + event.preventDefault(); - if (draggedCategory !== category && preferences && draggedCategory) { - draggedOverCategory = category; + if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'; +}; - const categories = preferences.pinned_badge_wall_categories; - const draggedIndex = categories.indexOf(draggedCategory); - const targetIndex = categories.indexOf(category || ''); +const handleDragEnter = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null +) => { + event.preventDefault(); - categories.splice(draggedIndex, 1); - categories.splice(targetIndex, 0, draggedCategory); + if (draggedCategory !== category && preferences && draggedCategory) { + draggedOverCategory = category; - preferences.pinned_badge_wall_categories = categories; - } - }; + const categories = preferences.pinned_badge_wall_categories; + const draggedIndex = categories.indexOf(draggedCategory); + const targetIndex = categories.indexOf(category || ''); - const handleDragLeave = ( - event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, - category: string - ) => { - event.preventDefault(); + categories.splice(draggedIndex, 1); + categories.splice(targetIndex, 0, draggedCategory); - if (draggedOverCategory === category && preferences && draggedCategory) { - draggedOverCategory = null; + preferences.pinned_badge_wall_categories = categories; + } +}; - const categories = preferences.pinned_badge_wall_categories; - const draggedIndex = categories.indexOf(draggedCategory); +const handleDragLeave = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string +) => { + event.preventDefault(); - categories.splice(draggedIndex, 1); - categories.splice(categories.indexOf(category) + 1, 0, draggedCategory); + if (draggedOverCategory === category && preferences && draggedCategory) { + draggedOverCategory = null; - preferences.pinned_badge_wall_categories = categories; - } - }; + const categories = preferences.pinned_badge_wall_categories; + const draggedIndex = categories.indexOf(draggedCategory); - const handleDrop = (event: { preventDefault: () => void }) => { - event.preventDefault(); + categories.splice(draggedIndex, 1); + categories.splice(categories.indexOf(category) + 1, 0, draggedCategory); - if (userData && preferences) - setCategoriesQuery - .mutate({ - categories: preferences.pinned_badge_wall_categories + preferences.pinned_badge_wall_categories = categories; + } +}; + +const handleDrop = (event: { preventDefault: () => void }) => { + event.preventDefault(); + + if (userData && preferences) + setCategoriesQuery + .mutate({ + categories: preferences.pinned_badge_wall_categories + }) + .then(); + + draggedCategory = null; + draggedOverCategory = null; +}; + +onMount(async () => { + schedule = typeSchedule( + parseScheduleHtml( + await ( + await fetch(proxy('https://schedule.hololive.tv'), { + headers: { + Cookie: 'timezone=Asia/Tokyo' + } }) - .then(); - - draggedCategory = null; - draggedOverCategory = null; - }; - - onMount(async () => { - schedule = typeSchedule( - parseScheduleHtml( - await ( - await fetch(proxy('https://schedule.hololive.tv'), { - headers: { - Cookie: 'timezone=Asia/Tokyo' - } - }) - ).text() - ) - ); - }); + ).text() + ) + ); +}); - const getBadgeWallCSS = () => - (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value; +const getBadgeWallCSS = () => + (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value; - const getBiography = () => - (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000); +const getBiography = () => + (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000); - const toggleCategory = () => { - if (!userData) return; +const toggleCategory = () => { + if (!userData) return; - const categoryElement = document.getElementById('category') as HTMLInputElement; - const category = categoryElement.value; + const categoryElement = document.getElementById('category') as HTMLInputElement; + const category = categoryElement.value; - toggleCategoryQuery.mutate({ category }).then(); + toggleCategoryQuery.mutate({ category }).then(); - categoryElement.value = ''; - }; + categoryElement.value = ''; +}; - // 8.5827814569536423841e0 +// 8.5827814569536423841e0 </script> <HeadTitle route={`${data.username}'s Profile`} path={`/user/${data.username}`} /> diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index d302de7f..cdb0ca9b 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -1,59 +1,59 @@ <script lang="ts"> - import Spacer from '$lib/Layout/Spacer.svelte'; - import AWC from './../../../../lib/User/BadgeWall/AWC.svelte'; - import { user, type User } from '$lib/Data/AniList/user'; - import type { Badge } from '../../../../graphql/$types'; - import { onDestroy, onMount } from 'svelte'; - import HeadTitle from '$lib/Home/HeadTitle.svelte'; - import { databaseTimeToDate, dateToInputTime, inputTimeToDatabaseTime } from '$lib/Utility/time'; - import proxy from '$lib/Utility/proxy'; - import locale from '$stores/locale'; - import Skeleton from '$lib/Loading/Skeleton.svelte'; - import Message from '$lib/Loading/Message.svelte'; - import Dropdown from '$lib/Layout/Dropdown.svelte'; - import { activityText } from '$lib/Data/AniList/activity'; - import SettingHint from '$lib/Settings/SettingHint.svelte'; - import Popup from '$lib/Layout/Popup.svelte'; - import { page } from '$app/stores'; - import { browser } from '$app/environment'; - import BadgePreview from '$lib/User/BadgeWall/BadgePreview.svelte'; - import authorisedJson from '$lib/Data/Static/authorised.json'; - import identity from '$stores/identity'; - import '$lib/User/BadgeWall/badges.css'; - import Badges from '$lib/User/BadgeWall/Badges.svelte'; - import type { IndexedBadge } from '$lib/User/BadgeWall/badge'; - import { graphql } from '$houdini'; - import type { Preferences } from '../../../../graphql/$types'; - import localforage from 'localforage'; - - export let data; - - $: ({ BadgeWallUser } = data); - $: preferences = $BadgeWallUser.fetching - ? undefined - : ($BadgeWallUser.data?.User?.preferences as Preferences | undefined); - - $: 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(` +import Spacer from '$lib/Layout/Spacer.svelte'; +import AWC from './../../../../lib/User/BadgeWall/AWC.svelte'; +import { user, type User } from '$lib/Data/AniList/user'; +import type { Badge } from '../../../../graphql/$types'; +import { onDestroy, onMount } from 'svelte'; +import HeadTitle from '$lib/Home/HeadTitle.svelte'; +import { databaseTimeToDate, dateToInputTime, inputTimeToDatabaseTime } from '$lib/Utility/time'; +import proxy from '$lib/Utility/proxy'; +import locale from '$stores/locale'; +import Skeleton from '$lib/Loading/Skeleton.svelte'; +import Message from '$lib/Loading/Message.svelte'; +import Dropdown from '$lib/Layout/Dropdown.svelte'; +import { activityText } from '$lib/Data/AniList/activity'; +import SettingHint from '$lib/Settings/SettingHint.svelte'; +import Popup from '$lib/Layout/Popup.svelte'; +import { page } from '$app/stores'; +import { browser } from '$app/environment'; +import BadgePreview from '$lib/User/BadgeWall/BadgePreview.svelte'; +import authorisedJson from '$lib/Data/Static/authorised.json'; +import identity from '$stores/identity'; +import '$lib/User/BadgeWall/badges.css'; +import Badges from '$lib/User/BadgeWall/Badges.svelte'; +import type { IndexedBadge } from '$lib/User/BadgeWall/badge'; +import { graphql } from '$houdini'; +import type { Preferences } from '../../../../graphql/$types'; +import localforage from 'localforage'; + +export let data; + +$: ({ BadgeWallUser } = data); +$: preferences = $BadgeWallUser.fetching + ? undefined + : ($BadgeWallUser.data?.User?.preferences as Preferences | undefined); + +$: 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( $id: Int $post: String @@ -95,7 +95,7 @@ } `); - const pruneBadgesQuery = graphql(` +const pruneBadgesQuery = graphql(` mutation PruneUserBadges { pruneUserBadges { id @@ -117,7 +117,7 @@ } `); - const hideCategoryQuery = graphql(` +const hideCategoryQuery = graphql(` mutation HideCategory($category: String) { hideBadge(category: $category) { id @@ -139,7 +139,7 @@ } `); - const deleteBadgeQuery = graphql(` +const deleteBadgeQuery = graphql(` mutation DeleteBadge($id: Int!) { deleteBadge(id: $id) { id @@ -161,7 +161,7 @@ } `); - const shadowHideBadgeQuery = graphql(` +const shadowHideBadgeQuery = graphql(` mutation ShadowHideBadge($id: Int!, $state: Boolean) { shadowHideBadge(id: $id, state: $state) { id @@ -173,359 +173,359 @@ } `); - interface ImportImage { - link?: string; - image: string; +interface ImportImage { + link?: string; + image: string; +} + +let editMode = false; +let importMode = false; +let error: null | string; +let awcPromise: Promise<Response>; +let confirmDelete = 0; +let confirmPrune = 0; +let selectedBadge: IndexedBadge | undefined = undefined; +let loadError: string | null = null; +const isId = /^\d+$/.test(data.username); +let importImages: ImportImage[] | undefined = undefined; +let importLinks = false; +let importCategory = ''; +let importReplies = false; +let badger: Partial<User> | null; +let migrateMode = false; +let hideMode = false; +const authorised = authorisedJson.includes($identity.id); +let noticeDismissed = false; + +$: categoryFilter = new URLSearchParams($page.url.searchParams).get('category'); +$: loadQueryParameter = new URLSearchParams($page.url.searchParams).get('load'); + +type GroupedBadges = { [key: string]: IndexedBadge[] }; + +const setShadowHide = () => { + if (!badger) { + loadError = 'Something went wrong. Try refreshing.'; + + return; } - let editMode = false; - let importMode = false; - let error: null | string; - let awcPromise: Promise<Response>; - let confirmDelete = 0; - let confirmPrune = 0; - let selectedBadge: IndexedBadge | undefined = undefined; - let loadError: string | null = null; - const isId = /^\d+$/.test(data.username); - let importImages: ImportImage[] | undefined = undefined; - let importLinks = false; - let importCategory = ''; - let importReplies = false; - let badger: Partial<User> | null; - let migrateMode = false; - let hideMode = false; - const authorised = authorisedJson.includes($identity.id); - let noticeDismissed = false; - - $: categoryFilter = new URLSearchParams($page.url.searchParams).get('category'); - $: loadQueryParameter = new URLSearchParams($page.url.searchParams).get('load'); - - type GroupedBadges = { [key: string]: IndexedBadge[] }; - - const setShadowHide = () => { - if (!badger) { - loadError = 'Something went wrong. Try refreshing.'; - - return; - } - - shadowHideBadgeQuery.mutate({ - id: badger.id as number - }); - }; + shadowHideBadgeQuery.mutate({ + id: badger.id as number + }); +}; - onMount(async () => { - if (browser && (await localforage.getItem('badgeWallNoticeDismissed'))) noticeDismissed = true; +onMount(async () => { + if (browser && (await localforage.getItem('badgeWallNoticeDismissed'))) noticeDismissed = true; - badger = isId - ? { - id: parseInt(data.username), - name: 'User' - } - : await user(data.username); + badger = isId + ? { + id: parseInt(data.username), + name: 'User' + } + : await user(data.username); - if (!badger) { - loadError = "Couldn't find this user."; + if (!badger) { + loadError = "Couldn't find this user."; - return; - } + return; + } - awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`)); - }); + awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`)); +}); - onDestroy(() => { - if (browser) - Array.from(document.head.querySelectorAll('style')).forEach((style) => { - if (style.dataset.badgeWall) style.remove(); - }); - }); +onDestroy(() => { + if (browser) + Array.from(document.head.querySelectorAll('style')).forEach((style) => { + if (style.dataset.badgeWall) style.remove(); + }); +}); + +const submitBadge = () => { + const imageURL = document.querySelector('input[name="image_url"]') as HTMLInputElement; + const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement; + const description = document.querySelector('input[name="description"]') as HTMLInputElement; + const time = document.querySelector('input[type="datetime-local"]') as HTMLInputElement; + const category = document.querySelector('input[name="category"]') as HTMLInputElement; + const hidden = document.querySelector('input[name="hidden"]') as HTMLInputElement; + const source = document.querySelector('input[name="source"]') as HTMLInputElement; + const designer = document.querySelector('input[name="designer"]') as HTMLInputElement; + + if (!imageURL.value) { + error = 'Image URL cannot be empty.'; + + return; + } - const submitBadge = () => { - const imageURL = document.querySelector('input[name="image_url"]') as HTMLInputElement; - const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement; - const description = document.querySelector('input[name="description"]') as HTMLInputElement; - const time = document.querySelector('input[type="datetime-local"]') as HTMLInputElement; - const category = document.querySelector('input[name="category"]') as HTMLInputElement; - const hidden = document.querySelector('input[name="hidden"]') as HTMLInputElement; - const source = document.querySelector('input[name="source"]') as HTMLInputElement; - const designer = document.querySelector('input[name="designer"]') as HTMLInputElement; + if ( + !imageURL.value.startsWith('http') || + (activityURL.value.length > 0 && !activityURL.value.startsWith('http')) + ) { + error = 'URLs must start with http or https.'; - if (!imageURL.value) { - error = 'Image URL cannot be empty.'; + return; + } - return; - } + updateBadgeQuery + .mutate({ + id: selectedBadge?.id, + image: imageURL.value, + post: activityURL.value || '#', + description: description.value, + category: category.value, + time: time.value ? inputTimeToDatabaseTime(new Date(time.value)) : undefined, + hidden: hidden.value === 'Hidden', + source: source.value, + designer: designer.value + }) + .then(() => { + error = null; + imageURL.value = ''; + activityURL.value = ''; + description.value = ''; + category.value = ''; + hidden.value = 'Shown'; + selectedBadge = undefined; + source.value = ''; + designer.value = ''; + }); +}; - if ( - !imageURL.value.startsWith('http') || - (activityURL.value.length > 0 && !activityURL.value.startsWith('http')) - ) { - error = 'URLs must start with http or https.'; +const removeAllBadges = () => { + if (confirmPrune === 2) { + confirmPrune = 0; + } else if (confirmPrune === 0) { + confirmPrune = 1; - return; - } + return; + } else { + confirmPrune = 2; - updateBadgeQuery - .mutate({ - id: selectedBadge?.id, - image: imageURL.value, - post: activityURL.value || '#', - description: description.value, - category: category.value, - time: time.value ? inputTimeToDatabaseTime(new Date(time.value)) : undefined, - hidden: hidden.value === 'Hidden', - source: source.value, - designer: designer.value - }) - .then(() => { - error = null; - imageURL.value = ''; - activityURL.value = ''; - description.value = ''; - category.value = ''; - hidden.value = 'Shown'; - selectedBadge = undefined; - source.value = ''; - designer.value = ''; - }); - }; - - const removeAllBadges = () => { - if (confirmPrune === 2) { - confirmPrune = 0; - } else if (confirmPrune === 0) { - confirmPrune = 1; - - return; - } else { - confirmPrune = 2; - - return; - } + return; + } - selectedBadge = undefined; + selectedBadge = undefined; - pruneBadgesQuery.mutate(null).then(); - }; + pruneBadgesQuery.mutate(null).then(); +}; - const removeBadge = (badge: Badge) => { - if (!badge.id) return; +const removeBadge = (badge: Badge) => { + if (!badge.id) return; - if (confirmDelete === badge.id * 2) { - confirmDelete = 0; - } else if (confirmDelete / 4 === badge.id) { - confirmDelete = badge.id * 2; + if (confirmDelete === badge.id * 2) { + confirmDelete = 0; + } else if (confirmDelete / 4 === badge.id) { + confirmDelete = badge.id * 2; - return; - } else { - confirmDelete = badge.id * 2; + return; + } else { + confirmDelete = badge.id * 2; - return; - } + return; + } - selectedBadge = undefined; + selectedBadge = undefined; - deleteBadgeQuery - .mutate({ - id: badge.id - }) - .then(); - }; + deleteBadgeQuery + .mutate({ + id: badge.id + }) + .then(); +}; - const groupBadges = (badges: IndexedBadge[]) => { - const groupedBadges: GroupedBadges = {}; +const groupBadges = (badges: IndexedBadge[]) => { + const groupedBadges: GroupedBadges = {}; - badges.forEach((badge) => { - if (!badge.category) badge.category = 'Uncategorised'; + badges.forEach((badge) => { + if (!badge.category) badge.category = 'Uncategorised'; - if (!groupedBadges[badge.category]) groupedBadges[badge.category] = []; + if (!groupedBadges[badge.category]) groupedBadges[badge.category] = []; - groupedBadges[badge.category].push(badge); - }); + groupedBadges[badge.category].push(badge); + }); - Object.entries(groupedBadges).forEach(([_categoryKey, badges]) => { - badges.forEach((badge, index) => { - badge.index = index; - }); + Object.entries(groupedBadges).forEach(([_categoryKey, badges]) => { + badges.forEach((badge, index) => { + badge.index = index; }); + }); - return Object.entries(groupedBadges) - .sort((a, b) => a[1].length - b[1].length) - .sort((a, b) => { - const pinnedCategories = - preferences && preferences.pinned_badge_wall_categories - ? preferences.pinned_badge_wall_categories - : ([] as string[]); - const aIndex = pinnedCategories.indexOf(a[0]); - const bIndex = pinnedCategories.indexOf(b[0]); + return Object.entries(groupedBadges) + .sort((a, b) => a[1].length - b[1].length) + .sort((a, b) => { + const pinnedCategories = + preferences && preferences.pinned_badge_wall_categories + ? preferences.pinned_badge_wall_categories + : ([] as string[]); + const aIndex = pinnedCategories.indexOf(a[0]); + const bIndex = pinnedCategories.indexOf(b[0]); - if (aIndex === -1 && bIndex === -1) return 0; - if (aIndex === -1) return 1; - if (bIndex === -1) return -1; + if (aIndex === -1 && bIndex === -1) return 0; + if (aIndex === -1) return 1; + if (bIndex === -1) return -1; - return aIndex - bIndex; - }) - .reduce((set: GroupedBadges, [key, value]) => { - set[key] = value; + return aIndex - bIndex; + }) + .reduce((set: GroupedBadges, [key, value]) => { + set[key] = value; - return set; - }, {}); - }; + return set; + }, {}); +}; - const parsePost = async () => { - if (importImages && importImages.length > 0) importImages = undefined; +const parsePost = async () => { + if (importImages && importImages.length > 0) importImages = undefined; - const link = (document.querySelector('#import_activity_url') as HTMLInputElement).value; - const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$1'); - const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$2'); + const link = (document.querySelector('#import_activity_url') as HTMLInputElement).value; + const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$1'); + const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$2'); - if (type !== 'activity') return null; + if (type !== 'activity') return null; - let text = await activityText(parseInt(id), importReplies); + let text = await activityText(parseInt(id), importReplies); - const images: ImportImage[] = []; + const images: ImportImage[] = []; - if (importLinks) { - Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('a')).forEach( - (a) => { - const anchor = a as HTMLAnchorElement; + if (importLinks) { + Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('a')).forEach( + (a) => { + const anchor = a as HTMLAnchorElement; - if (anchor.querySelector('img')) { - images.push({ - link: anchor.href, - image: (anchor.querySelector('img') as HTMLImageElement).src - }); - } + if (anchor.querySelector('img')) { + images.push({ + link: anchor.href, + image: (anchor.querySelector('img') as HTMLImageElement).src + }); } - ); + } + ); - text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, ''); + text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, ''); - Array.from( - new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img') - ).forEach((img) => { + Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img')).forEach( + (img) => { const image = img as HTMLImageElement; images.push({ image: image.src }); - }); - } else { - Array.from( - new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img') - ).forEach((img) => { + } + ); + } else { + Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img')).forEach( + (img) => { const image = img as HTMLImageElement; images.push({ image: image.src }); - }); - } + } + ); + } - importImages = images; - }; + importImages = images; +}; - const importBadges = () => - fetch( - `/api/badges?import=true +const importBadges = () => + fetch( + `/api/badges?import=true ${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ''} `, - { - method: 'PUT', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify( - importImages?.map((image) => ({ - image: image.image, - post: image.link || '#', - category: importCategory - })) - ) - } - ).then(() => { - importMode = false; - importImages = undefined; - }); + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify( + importImages?.map((image) => ({ + image: image.image, + post: image.link || '#', + category: importCategory + })) + ) + } + ).then(() => { + importMode = false; + importImages = undefined; + }); - const migrateCategory = () => { - fetch( - `/api/badges?migrate=true&original=${encodeURIComponent( - (document.querySelector('#migrate_original') as HTMLInputElement).value - )}&new=${encodeURIComponent( - (document.querySelector('#migrate_new') as HTMLInputElement).value - )}`, - { - method: 'PUT' - } - ).then(() => (migrateMode = false)); - }; +const migrateCategory = () => { + fetch( + `/api/badges?migrate=true&original=${encodeURIComponent( + (document.querySelector('#migrate_original') as HTMLInputElement).value + )}&new=${encodeURIComponent( + (document.querySelector('#migrate_new') as HTMLInputElement).value + )}`, + { + method: 'PUT' + } + ).then(() => (migrateMode = false)); +}; - const hideCategory = () => { - hideCategoryQuery - .mutate({ - category: (document.querySelector('#category_hide') as HTMLInputElement).value - }) - .then(() => (hideMode = false)); - }; +const hideCategory = () => { + hideCategoryQuery + .mutate({ + category: (document.querySelector('#category_hide') as HTMLInputElement).value + }) + .then(() => (hideMode = false)); +}; - const removeHiddenBadges = (isOwner: boolean, badges: IndexedBadge[]) => - isOwner || authorised ? badges : badges.filter((b) => !b.hidden && !b.shadow_hidden); +const removeHiddenBadges = (isOwner: boolean, badges: IndexedBadge[]) => + isOwner || authorised ? badges : badges.filter((b) => !b.hidden && !b.shadow_hidden); - const setAdjacentCursor = (badges: IndexedBadge[], direction: number) => { - const currentCategory = selectedBadge?.category || 'Uncategorised'; - const currentBadge = selectedBadge?.index; - const categoryBadges = groupBadges(badges)[currentCategory]; +const setAdjacentCursor = (badges: IndexedBadge[], direction: number) => { + const currentCategory = selectedBadge?.category || 'Uncategorised'; + const currentBadge = selectedBadge?.index; + const categoryBadges = groupBadges(badges)[currentCategory]; - if (!currentCategory || currentBadge === undefined) return; + if (!currentCategory || currentBadge === undefined) return; - let previousBadge = categoryBadges[currentBadge + direction]; + let previousBadge = categoryBadges[currentBadge + direction]; - while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden)) - previousBadge = categoryBadges[previousBadge.index + direction]; + while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden)) + previousBadge = categoryBadges[previousBadge.index + direction]; - if (previousBadge) selectedBadge = previousBadge; - }; + if (previousBadge) selectedBadge = previousBadge; +}; - const adjacentBadgeExists = ( - selectedBadge: IndexedBadge | undefined, - badges: IndexedBadge[], - direction: number - ) => { - const currentCategory = selectedBadge?.category || 'Uncategorised'; - const currentBadge = selectedBadge?.index; - const categoryBadges = groupBadges(badges)[currentCategory]; +const adjacentBadgeExists = ( + selectedBadge: IndexedBadge | undefined, + badges: IndexedBadge[], + direction: number +) => { + const currentCategory = selectedBadge?.category || 'Uncategorised'; + const currentBadge = selectedBadge?.index; + const categoryBadges = groupBadges(badges)[currentCategory]; - if (!currentCategory || currentBadge === undefined || !categoryBadges) return; + if (!currentCategory || currentBadge === undefined || !categoryBadges) return; - let previousBadge = categoryBadges[currentBadge + direction]; + let previousBadge = categoryBadges[currentBadge + direction]; - while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden)) - previousBadge = categoryBadges[previousBadge.index + direction]; + while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden)) + previousBadge = categoryBadges[previousBadge.index + direction]; - return previousBadge; - }; + return previousBadge; +}; - const castAsStringArray = (array: unknown[]) => array as string[]; +const castAsStringArray = (array: unknown[]) => array as string[]; - const castBadgesToIndexedBadges = (array: unknown[]) => array as IndexedBadge[]; +const castBadgesToIndexedBadges = (array: unknown[]) => array as IndexedBadge[]; - const shadowHideBadge = () => { - if (!selectedBadge && !authorised) return; +const shadowHideBadge = () => { + if (!selectedBadge && !authorised) return; - if (!badger) { - loadError = 'Something went wrong. Try refreshing.'; + if (!badger) { + loadError = 'Something went wrong. Try refreshing.'; - return; - } + return; + } - shadowHideBadgeQuery - .mutate({ - id: badger.id as number, - state: selectedBadge?.shadow_hidden as boolean - }) - .then(); - }; + shadowHideBadgeQuery + .mutate({ + id: badger.id as number, + state: selectedBadge?.shadow_hidden as boolean + }) + .then(); +}; </script> <HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} /> |