aboutsummaryrefslogtreecommitdiff
path: root/src/routes/user
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-03-01 16:04:11 -0800
committerFuwn <[email protected]>2026-03-01 16:04:11 -0800
commit48f0c30d47d62e4f35706edb93a1bb2f97eba14c (patch)
tree44866d7a61adfdf01a780e0108c370294d3db78b /src/routes/user
parentchore(biome): re-enable useAltText rule (diff)
downloaddue.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.svelte44
-rw-r--r--src/routes/user/[user]/+page.svelte256
-rw-r--r--src/routes/user/[user]/badges/+page.svelte674
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}`} />