import { createFormControl, createFormGroup } from "solid-forms"; import { Show, createEffect, createSignal, on } from "solid-js"; import { Trans, useLingui } from "@lingui-solid/solid/macro"; import { useQuery, useQueryClient } from "@tanstack/solid-query"; import { API, User } from "stoat.js"; import { useClient } from "@revolt/client"; import { CONFIGURATION } from "@revolt/common"; import { CategoryButton, CircularProgress, Column, Form2, Row, Text, } from "@revolt/ui"; import MdBadge from "@material-design-icons/svg/filled/badge.svg?component-solid"; import { useSettingsNavigation } from "../../Settings"; interface Props { user: User; } export function UserProfileEditor(props: Props) { const { t } = useLingui(); const client = useClient(); const queryClient = useQueryClient(); const profile = useQuery(() => ({ queryKey: ["profile", props.user.id], queryFn: () => props.user.fetchProfile(), refetchOnReconnect: false, refetchOnWindowFocus: false, })); const { navigate } = useSettingsNavigation(); /* eslint-disable solid/reactivity */ const editGroup = createFormGroup({ displayName: createFormControl(props.user.displayName), // username: createFormControl(props.user.username), avatar: createFormControl( props.user.animatedAvatarURL, ), banner: createFormControl(null), bio: createFormControl(""), }); /* eslint-enable solid/reactivity */ // unlike the other forms, this one does not react to // further changes outside of our control because it's // unlikely that the user is going to be doing this const [initialBio, setInitialBio] = createSignal(); // once profile data is loaded, copy it into the form createEffect( on( () => profile.data, (profileData) => { if (profileData) { editGroup.controls.banner.setValue( profileData.animatedBannerURL || null, ); editGroup.controls.bio.setValue(profileData.content || ""); setInitialBio([profileData.content || ""]); } }, ), ); function onReset() { editGroup.controls.displayName.setValue(props.user.displayName); editGroup.controls.avatar.setValue(props.user.animatedAvatarURL); if (profile.data) { editGroup.controls.banner.setValue( profile.data.animatedBannerURL || null, ); editGroup.controls.bio.setValue(profile.data.content || ""); setInitialBio([profile.data.content || ""]); } } async function onSubmit() { const changes: API.DataEditUser = { remove: [], }; if (editGroup.controls.displayName.isDirty) { changes.display_name = editGroup.controls.displayName.value.trim(); } if (editGroup.controls.avatar.isDirty) { if (!editGroup.controls.avatar.value) { changes.remove!.push("Avatar"); } else if (Array.isArray(editGroup.controls.avatar.value)) { changes.avatar = await client().uploadFile( "avatars", editGroup.controls.avatar.value[0], CONFIGURATION.DEFAULT_MEDIA_URL, ); } } if (editGroup.controls.bio.isDirty) { if (!editGroup.controls.bio.value) { changes.remove!.push("ProfileContent"); } else { changes.profile ??= {}; changes.profile.content = editGroup.controls.bio.value; } } let newBannerUrl: string | null = null; if (editGroup.controls.banner.isDirty) { if (!editGroup.controls.banner.value) { changes.remove!.push("ProfileBackground"); } else if (Array.isArray(editGroup.controls.banner.value)) { changes.profile ??= {}; changes.profile.background = await client().uploadFile( "backgrounds", editGroup.controls.banner.value[0], CONFIGURATION.DEFAULT_MEDIA_URL, ); newBannerUrl = `${CONFIGURATION.DEFAULT_MEDIA_URL}/backgrounds/${changes.profile.background}`; } else { newBannerUrl = editGroup.controls.banner.value; } } await props.user.edit(changes); if (editGroup.controls.banner.isDirty && profile.data) { queryClient.setQueryData(["profile", props.user.id], { ...profile.data, animatedBannerURL: newBannerUrl, bannerURL: newBannerUrl, }); } } const submit = Form2.useSubmitHandler(editGroup, onSubmit, onReset); return (
} action="chevron" description={ Go to account settings to edit your username } onClick={() => navigate("account")} > Want to change username? Profile Bio Save
); }