diff --git a/frontend/src/lib/components/IconButton.svelte b/frontend/src/lib/components/IconButton.svelte new file mode 100644 index 0000000..2c1d72e --- /dev/null +++ b/frontend/src/lib/components/IconButton.svelte @@ -0,0 +1,16 @@ + + +{tooltip} + diff --git a/frontend/src/routes/edit/profile/+page.svelte b/frontend/src/routes/edit/profile/+page.svelte index eb88ab7..28f85f6 100644 --- a/frontend/src/routes/edit/profile/+page.svelte +++ b/frontend/src/routes/edit/profile/+page.svelte @@ -14,6 +14,7 @@ import { Alert, Button, FormGroup, Icon, Input } from "sveltestrap"; import { encode } from "base64-arraybuffer"; import { apiFetchClient } from "$lib/api/fetch"; + import IconButton from "$lib/components/IconButton.svelte"; const MAX_AVATAR_BYTES = 1_000_000; @@ -25,6 +26,7 @@ let bio: string = $userStore?.bio || ""; let display_name: string = $userStore?.display_name || ""; + let links: string[] = $userStore ? window.structuredClone($userStore.links) : []; let names: FieldEntry[] = $userStore ? window.structuredClone($userStore.names) : []; let pronouns: Pronoun[] = $userStore ? window.structuredClone($userStore.pronouns) : []; let fields: Field[] = $userStore ? window.structuredClone($userStore.fields) : []; @@ -32,10 +34,15 @@ let avatar: string | null; let avatar_files: FileList | null; + let newName = ""; + let newPronouns = ""; + let newPronounsDisplay = ""; + let newLink = ""; + let modified = false; $: redirectIfNoAuth($userStore); - $: modified = isModified(bio, display_name, names, pronouns, fields); + $: modified = isModified(bio, display_name, links, names, pronouns, fields, avatar); $: getAvatar(avatar_files).then((b64) => (avatar = b64)); const redirectIfNoAuth = (user: MeUser | null) => { @@ -47,14 +54,17 @@ const isModified = ( bio: string, display_name: string, + links: string[], names: FieldEntry[], pronouns: Pronoun[], fields: Field[], + avatar: string | null, ) => { if (!$userStore) return false; if (bio !== $userStore.bio) return true; if (display_name !== $userStore.display_name) return true; + if (!linksEqual(links, $userStore.links)) return true; if (!fieldsEqual(fields, $userStore.fields)) return true; if (!namesEqual(names, $userStore.names)) return true; if (!pronounsEqual(pronouns, $userStore.pronouns)) return true; @@ -92,6 +102,11 @@ return true; }; + const linksEqual = (arr1: string[], arr2: string[]) => { + if (arr1.length !== arr2.length) return false; + return arr1.every((_, i) => arr1[i] === arr2[i]); + }; + const getAvatar = async (list: FileList | null) => { if (!list || list.length === 0) return null; if (list[0].size > MAX_AVATAR_BYTES) return null; @@ -140,12 +155,53 @@ pronouns[newIndex] = temp; }; + const addName = () => { + names = [...names, { value: newName, status: WordStatus.Okay }]; + newName = ""; + }; + + const addPronouns = () => { + pronouns = [ + ...pronouns, + { pronouns: newPronouns, display_text: newPronounsDisplay || null, status: WordStatus.Okay }, + ]; + newPronouns = ""; + newPronounsDisplay = ""; + }; + + const addLink = () => { + links = [...links, newLink]; + newLink = ""; + }; + + const removeName = (index: number) => { + if (names.length === 1) names = []; + else if (index === 0) names = names.slice(1); + else if (index === names.length - 1) names = names.slice(0, names.length - 1); + else names = [...names.slice(0, index - 1), ...names.slice(0, index + 1)]; + }; + + const removePronoun = (index: number) => { + if (pronouns.length === 1) pronouns = []; + else if (index === 0) pronouns = pronouns.slice(1); + else if (index === pronouns.length - 1) pronouns = pronouns.slice(0, pronouns.length - 1); + else pronouns = [...pronouns.slice(0, index - 1), ...pronouns.slice(0, index + 1)]; + }; + + const removeLink = (index: number) => { + if (links.length === 1) links = []; + else if (index === 0) links = links.slice(1); + else if (index === links.length - 1) links = links.slice(0, links.length - 1); + else links = [...links.slice(0, index - 1), ...links.slice(0, index + 1)]; + }; + const updateUser = async () => { try { const resp = await apiFetchClient("/users/@me", "PATCH", { display_name, avatar, bio, + links, names, pronouns, fields, @@ -227,46 +283,71 @@ - - - - - - + /> + removeName(index)} + /> {/each} +
+ + addName()} /> +
+ +
+

Links

+ {#each links as _, index} +
+ + removeLink(index)} + /> +
+ {/each} +
+ + addLink()} /> +
@@ -282,46 +363,59 @@ - - - - - - + /> + removePronoun(index)} + />
{/each} +
+ + + addPronouns()} + /> +