aboutsummaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-02-04 20:45:14 -0800
committerFuwn <[email protected]>2024-02-04 20:45:14 -0800
commit126c33520b3e426f3a12ee69d6e6f93e48edff36 (patch)
treeb36710c58e50eff267d5d7d301dd6800296afe5e /src/routes
parentfix(badges): close if (diff)
downloaddue.moe-126c33520b3e426f3a12ee69d6e6f93e48edff36.tar.xz
due.moe-126c33520b3e426f3a12ee69d6e6f93e48edff36.zip
feat(badges): import mode
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/user/[user]/badges/+page.svelte153
1 files changed, 150 insertions, 3 deletions
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
index a5ae83fe..523f9030 100644
--- a/src/routes/user/[user]/badges/+page.svelte
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -15,11 +15,19 @@
import Message from '$lib/Loading/Message.svelte';
import Dropdown from '$lib/Dropdown.svelte';
import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte';
+ import { activityText } from '$lib/AniList/activity.js';
+ import SettingHint from '$lib/Settings/SettingHint.svelte';
// import { io } from 'socket.io-client';
export let data;
+ interface ImportImage {
+ link?: string;
+ image: string;
+ }
+
let editMode = false;
+ let importMode = false;
let currentUserIdentity: ReturnType<typeof userIdentity>;
let error: null | string;
// const socket = io();
@@ -30,7 +38,11 @@
let confirmDelete = 0;
let selectedBadge: Badge | undefined = undefined;
let loadError: string | null = null;
+ const isId = /^\d+$/.test(data.username);
+ let importImages: ImportImage[] | undefined = undefined;
// let badgeCount = 0;
+ let importLinks = false;
+ let importCategory = '';
// $: downloadDisabled = badgeCount > 20;
@@ -50,7 +62,6 @@
onMount(async () => {
// socket.on('badges', (message) => (badges = message));
- const isId = /^\d+$/.test(data.username);
const badger = isId
? {
id: parseInt(data.username),
@@ -67,7 +78,7 @@
badgesPromise = fetch(root(`/api/badges?id=${badger.id}`));
awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`));
- if (data.user) {
+ if (data.user && !isId) {
currentUserIdentity = userIdentity(data.user);
// socket.emit('badges', data.user);
@@ -311,6 +322,71 @@
return url;
};
+
+ 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');
+
+ if (type !== 'activity') return null;
+
+ let text = await activityText(parseInt(id));
+
+ const images: ImportImage[] = [];
+
+ 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
+ });
+ }
+ }
+ );
+
+ text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, '');
+
+ 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) => {
+ const image = img as HTMLImageElement;
+
+ images.push({
+ image: image.src
+ });
+ });
+ }
+
+ importImages = images;
+ };
+
+ const importBadges = () =>
+ importImages?.forEach((image) => {
+ badgesPromise = fetch(
+ `/api/badges?image=${encodeURIComponent(image.image)}&post=${encodeURIComponent(
+ image.link || '#'
+ )}${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ''}`,
+ {
+ method: 'PUT'
+ }
+ );
+ });
</script>
<HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} />
@@ -325,7 +401,7 @@
<Skeleton grid={true} count={100} width="150px" height="170px" />
{:then identity}
- {@const isOwner = identity && identity.name === data.username}
+ {@const isOwner = identity && (isId ? identity.id : identity.name) === data.username}
{#await badgesPromise}
<Message message="Loading badges ..." />
@@ -399,6 +475,18 @@
? $locale().user.badges.editMode.disable
: $locale().user.badges.editMode.enable}
</button>
+ <span style="margin: 0 0.625rem;">•</span>
+ <button
+ on:click={() => {
+ if (importMode) selectedBadge = undefined;
+
+ importMode = !importMode;
+ }}
+ >
+ {importMode
+ ? $locale().user.badges.importMode.disable
+ : $locale().user.badges.importMode.enable}
+ </button>
{#if editMode && isOwner}
{@const groups = groupedBadges
@@ -581,6 +669,65 @@
{/await}
{/if}
+{#if importMode}
+ <div class="popup popup-fullscreen">
+ <div class="card">
+ <SettingHint>Import badges from an activity post</SettingHint>
+
+ <p />
+
+ <input
+ type="text"
+ placeholder={$locale().user.badges.editMode.activityURL}
+ id="import_activity_url"
+ minlength="1"
+ maxlength="1000"
+ size="20"
+ />
+ <input
+ type="text"
+ placeholder={$locale().user.badges.editMode.category}
+ id="import_category"
+ minlength="1"
+ maxlength="1000"
+ size="20"
+ />
+
+ <p />
+
+ <input type="checkbox" id="import_links" name="import_links" bind:checked={importLinks} />
+ Import Links
+ <SettingHint lineBreak>
+ If your images are nested in links, check this box to import the links as well.
+ </SettingHint>
+
+ <p />
+
+ <button
+ on:click={() => {
+ importMode = false;
+ importImages = undefined;
+ }}
+ class="button-lined"
+ >
+ {$locale().user.badges.importMode.cancel}
+ </button>
+ <button on:click={() => parsePost()} class="button-lined" style="float: right;">
+ {$locale().user.badges.importMode.fetch}
+ </button>
+
+ {#if importImages && importImages.length > 0}
+ <p />
+
+ Import {importImages.length} badges?&nbsp;
+ <button on:click={() => importBadges()} class="button-lined no-shadow">
+ {$locale().user.badges.importMode.import}
+ </button>
+ {/if}
+ </div>
+ </div>
+{/if}
+
<style>
/* body {
margin: 0;