/* 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

On this page you can change various settings relating to the appearance and discoverability of your profile and posts.
After changing settings and/or uploading a new avatar or header, be sure to scroll to the bottom of this page and click "Save profile info" to confirm your changes.

Learn more about this settings page (opens in a new tab)
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)