diff --git a/frontend/src/routes/edit/EditablePronouns.svelte b/frontend/src/routes/edit/EditablePronouns.svelte
index b1df161..d1a1548 100644
--- a/frontend/src/routes/edit/EditablePronouns.svelte
+++ b/frontend/src/routes/edit/EditablePronouns.svelte
@@ -1,5 +1,6 @@
@@ -75,31 +55,17 @@
click={toggleDisplay}
/>
- {textFor(pronoun.status)}
+ {currentPreference.tooltip}
-
+
- (pronoun.status = WordStatus.Favourite)}
- active={pronoun.status === WordStatus.Favourite}>Favourite
- (pronoun.status = WordStatus.Okay)}
- active={pronoun.status === WordStatus.Okay}>Okay
- (pronoun.status = WordStatus.Jokingly)}
- active={pronoun.status === WordStatus.Jokingly}>Jokingly
- (pronoun.status = WordStatus.FriendsOnly)}
- active={pronoun.status === WordStatus.FriendsOnly}>Friends only
- (pronoun.status = WordStatus.Avoid)}
- active={pronoun.status === WordStatus.Avoid}>Avoid
+ {#each preferenceIds as id}
+ (pronoun.status = id)} active={pronoun.status === id}>
+
+ {mergedPreferences[id].tooltip}
+
+ {/each}
diff --git a/frontend/src/routes/edit/FieldEntry.svelte b/frontend/src/routes/edit/FieldEntry.svelte
index d03595d..2a9b086 100644
--- a/frontend/src/routes/edit/FieldEntry.svelte
+++ b/frontend/src/routes/edit/FieldEntry.svelte
@@ -1,5 +1,6 @@
@@ -58,30 +36,17 @@
- {textFor(status)}
+ {currentPreference.tooltip}
-
+
- (status = WordStatus.Favourite)}
- active={status === WordStatus.Favourite}>Favourite
- (status = WordStatus.Okay)} active={status === WordStatus.Okay}
- >Okay
- (status = WordStatus.Jokingly)}
- active={status === WordStatus.Jokingly}>Jokingly
- (status = WordStatus.FriendsOnly)}
- active={status === WordStatus.FriendsOnly}>Friends only
- (status = WordStatus.Avoid)}
- active={status === WordStatus.Avoid}>Avoid
+ {#each preferenceIds as id}
+ (status = id)} active={status === id}>
+
+ {mergedPreferences[id].tooltip}
+
+ {/each}
diff --git a/frontend/src/routes/edit/member/[id]/+page.svelte b/frontend/src/routes/edit/member/[id]/+page.svelte
index fe3d6f8..f095364 100644
--- a/frontend/src/routes/edit/member/[id]/+page.svelte
+++ b/frontend/src/routes/edit/member/[id]/+page.svelte
@@ -153,10 +153,9 @@
if (list[0].size > MAX_AVATAR_BYTES) {
addToast({
header: "Avatar too large",
- body:
- `This avatar is too large, please resize it (maximum is ${prettyBytes(
- MAX_AVATAR_BYTES,
- )}, the file you tried to upload is ${prettyBytes(list[0].size)})`,
+ body: `This avatar is too large, please resize it (maximum is ${prettyBytes(
+ MAX_AVATAR_BYTES,
+ )}, the file you tried to upload is ${prettyBytes(list[0].size)})`,
});
return null;
}
@@ -440,6 +439,7 @@
moveName(index, true)}
moveDown={() => moveName(index, false)}
remove={() => removeName(index)}
@@ -479,6 +479,7 @@
{#each pronouns as _, index}
movePronoun(index, true)}
moveDown={() => movePronoun(index, false)}
remove={() => removePronoun(index)}
@@ -520,6 +521,7 @@
{#each fields as _, index}
removeField(index)}
moveField={(up) => moveField(index, up)}
/>
diff --git a/frontend/src/routes/edit/profile/+page.svelte b/frontend/src/routes/edit/profile/+page.svelte
index 4134de4..a3ef65c 100644
--- a/frontend/src/routes/edit/profile/+page.svelte
+++ b/frontend/src/routes/edit/profile/+page.svelte
@@ -8,6 +8,8 @@
type FieldEntry,
type MeUser,
type Pronoun,
+ PreferenceSize,
+ type CustomPreferences,
} from "$lib/api/entities";
import FallbackImage from "$lib/components/FallbackImage.svelte";
import { userStore } from "$lib/store";
@@ -37,6 +39,7 @@
import { charCount, renderMarkdown } from "$lib/utils";
import MarkdownHelp from "../MarkdownHelp.svelte";
import prettyBytes from "pretty-bytes";
+ import CustomPreference from "./CustomPreference.svelte";
const MAX_AVATAR_BYTES = 1_000_000;
@@ -52,6 +55,7 @@
let pronouns: Pronoun[] = window.structuredClone(data.user.pronouns);
let fields: Field[] = window.structuredClone(data.user.fields);
let list_private = data.user.list_private;
+ let custom_preferences = window.structuredClone(data.user.custom_preferences);
let avatar: string | null;
let avatar_files: FileList | null;
@@ -60,6 +64,9 @@
let newPronouns = "";
let newLink = "";
+ let preferenceIds: string[];
+ $: preferenceIds = Object.keys(custom_preferences);
+
let modified = false;
$: modified = isModified(
@@ -73,6 +80,7 @@
avatar,
member_title,
list_private,
+ custom_preferences,
);
$: getAvatar(avatar_files).then((b64) => (avatar = b64));
@@ -87,6 +95,7 @@
avatar: string | null,
member_title: string,
list_private: boolean,
+ custom_preferences: CustomPreferences,
) => {
if (bio !== (user.bio || "")) return true;
if (display_name !== (user.display_name || "")) return true;
@@ -95,6 +104,7 @@
if (!fieldsEqual(fields, user.fields)) return true;
if (!namesEqual(names, user.names)) return true;
if (!pronounsEqual(pronouns, user.pronouns)) return true;
+ if (!customPreferencesEqual(custom_preferences, user.custom_preferences)) return true;
if (avatar !== null) return true;
if (list_private !== user.list_private) return true;
@@ -136,6 +146,21 @@
return arr1.every((_, i) => arr1[i] === arr2[i]);
};
+ const customPreferencesEqual = (obj1: CustomPreferences, obj2: CustomPreferences) => {
+ return Object.keys(obj1)
+ .map((key) => {
+ if (!(key in obj2)) return false;
+ return (
+ obj1[key].icon === obj2[key].icon &&
+ obj1[key].tooltip === obj2[key].tooltip &&
+ obj1[key].favourite === obj2[key].favourite &&
+ obj1[key].muted === obj2[key].muted &&
+ obj1[key].size === obj2[key].size
+ );
+ })
+ .every((entry) => entry);
+ };
+
const getAvatar = async (list: FileList | null) => {
if (!list || list.length === 0) return null;
if (list[0].size > MAX_AVATAR_BYTES) {
@@ -226,6 +251,19 @@
newLink = "";
};
+ const addPreference = () => {
+ const id = crypto.randomUUID();
+
+ custom_preferences[id] = {
+ icon: "question",
+ tooltip: "New preference",
+ size: PreferenceSize.Normal,
+ muted: false,
+ favourite: false,
+ };
+ custom_preferences = custom_preferences;
+ };
+
const removeName = (index: number) => {
names.splice(index, 1);
names = [...names];
@@ -246,6 +284,11 @@
fields = [...fields];
};
+ const removePreference = (id: string) => {
+ delete custom_preferences[id];
+ custom_preferences = custom_preferences;
+ };
+
const updateUser = async () => {
const toastId = addToast({
header: "Saving changes",
@@ -264,6 +307,7 @@
fields,
member_title,
list_private,
+ custom_preferences,
});
data.user = resp;
@@ -367,6 +411,7 @@
moveName(index, true)}
moveDown={() => moveName(index, false)}
remove={() => removeName(index)}
@@ -447,6 +492,7 @@
{#each fields as _, index}
removeField(index)}
moveField={(up) => moveField(index, up)}
/>
@@ -478,7 +524,7 @@
-
+
+
+
+ Preferences
+
+ {#each preferenceIds as id}
+ removePreference(id)}
+ />
+ {/each}
+
diff --git a/frontend/src/routes/edit/profile/CustomPreference.svelte b/frontend/src/routes/edit/profile/CustomPreference.svelte
new file mode 100644
index 0000000..84e49a0
--- /dev/null
+++ b/frontend/src/routes/edit/profile/CustomPreference.svelte
@@ -0,0 +1,86 @@
+
+
+
+
+ Change icon
+
+
+
+
+
+
+
+
+ {#each filteredIcons as icon}
+ (preference.icon = icon)}
+ > {icon}
+ {:else}
+ Start typing to filter
+ {/each}
+
+
+
+ Change text size
+
+
+
+
+
+ (preference.size = PreferenceSize.Large)}>Large
+ (preference.size = PreferenceSize.Normal)}>Medium
+ (preference.size = PreferenceSize.Small)}>Small
+
+
+
+
+
+