/* GoToSocial Copyright (C) GoToSocial Authors admin@gotosocial.org SPDX-License-Identifier: AGPL-3.0-or-later This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import React, { useMemo, useState } from "react"; import { useTextInput, useFileInput, useBoolInput, useFieldArrayInput, } from "../../../lib/form"; import useFormSubmit from "../../../lib/form/submit"; import { useWithFormContext, FormContext } from "../../../lib/form/context"; import { TextInput, TextArea, FileInput, Checkbox, Select } from "../../../components/form/inputs"; import FormWithData from "../../../lib/form/form-with-data"; import FakeProfile from "../../../components/profile"; import MutationButton from "../../../components/form/mutation-button"; import { useAccountThemesQuery, useDeleteAvatarMutation, useDeleteHeaderMutation, } from "../../../lib/query/user"; import { useUpdateCredentialsMutation } from "../../../lib/query/user"; import { useVerifyCredentialsQuery } from "../../../lib/query/login"; import { useInstanceV1Query } from "../../../lib/query/gts-api"; import { Account } from "../../../lib/types/account"; export default function Profile() { return ( ); } interface ProfileFormProps { data: Account; } function ProfileForm({ data: profile }: ProfileFormProps) { const { data: instance } = useInstanceV1Query(); const instanceConfig = React.useMemo(() => { return { allowCustomCSS: instance?.configuration?.accounts?.allow_custom_css === true, maxPinnedFields: instance?.configuration?.accounts?.max_profile_fields ?? 6 }; }, [instance]); // Parse out available theme options into nice format. const { data: themes } = useAccountThemesQuery(); const themeOptions = useMemo(() => { let themeOptions = [ ]; themes?.forEach((theme) => { const value = theme.file_name; let text = theme.title; if (theme.description) { text += " - " + theme.description; } themeOptions.push( ); }); return themeOptions; }, [themes]); const form = { avatar: useFileInput("avatar", { withPreview: true }), avatarDescription: useTextInput("avatar_description", { source: profile }), header: useFileInput("header", { withPreview: true }), headerDescription: useTextInput("header_description", { source: profile }), displayName: useTextInput("display_name", { source: profile }), note: useTextInput("note", { source: profile, valueSelector: (p) => p.source?.note }), bot: useBoolInput("bot", { source: profile }), locked: useBoolInput("locked", { source: profile }), discoverable: useBoolInput("discoverable", { source: profile}), enableRSS: useBoolInput("enable_rss", { source: profile }), hideCollections: useBoolInput("hide_collections", { source: profile }), webVisibility: useTextInput("web_visibility", { source: profile, valueSelector: (p: Account) => p.source?.web_visibility }), webLayout: useTextInput("web_layout", { source: profile, valueSelector: (p: Account) => p.source?.web_layout }), fields: useFieldArrayInput("fields_attributes", { defaultValue: profile?.source?.fields, length: instanceConfig.maxPinnedFields }), customCSS: useTextInput("custom_css", { source: profile, nosubmit: !instanceConfig.allowCustomCSS }), theme: useTextInput("theme", { source: profile }), }; const [ noHeader, setNoHeader ] = useState(!profile.header_media_id); const [ deleteHeader, deleteHeaderRes ] = useDeleteHeaderMutation(); const [ noAvatar, setNoAvatar ] = useState(!profile.avatar_media_id); const [ deleteAvatar, deleteAvatarRes ] = useDeleteAvatarMutation(); const [submitForm, result] = useFormSubmit(form, useUpdateCredentialsMutation(), { changedOnly: true, onFinish: (res) => { if ('data' in res) { form.avatar.reset(); form.header.reset(); setNoAvatar(!res.data.avatar_media_id); setNoHeader(!res.data.header_media_id); } } }); return (

Profile

Header { e.preventDefault(); deleteHeader().then(res => { if ('data' in res) { setNoHeader(true); } }); }} />
Avatar { e.preventDefault(); deleteAvatar().then(res => { if ('data' in res) { setNoAvatar(true); } }); }} />
After choosing theme or layout and saving, open your profile and refresh to see changes. } />

Basic Information

Learn more about these settings (opens in a new tab)