Merge commit 'bca57020a04c552a3c91912a0e0b69ddafaad06a' into glitch-soc/merge-upstream
This commit is contained in:
commit
dc27eccc8e
86 files changed
+701
-266
No files matched your search
@@ -4,12 +4,11 @@ import type { ChangeEventHandler, FC } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { TextArea } from '@/mastodon/components/form_fields';
|
||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||
import { insertEmojiAtPosition } from '@/mastodon/features/emoji/utils';
|
||||
import type { BaseConfirmationModalProps } from '@/mastodon/features/ui/components/confirmation_modals';
|
||||
import { ConfirmationModal } from '@/mastodon/features/ui/components/confirmation_modals';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { patchProfile } from '@/mastodon/reducers/slices/profile_edit';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
@@ -38,10 +37,11 @@ export const BioModal: FC<BaseConfirmationModalProps> = ({ onClose }) => {
|
||||
const titleId = useId();
|
||||
const counterId = useId();
|
||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const accountId = useCurrentAccountId();
|
||||
const account = useAccount(accountId);
|
||||
|
||||
const [newBio, setNewBio] = useState(account?.note_plain ?? '');
|
||||
const { profile: { bio } = {}, isPending } = useAppSelector(
|
||||
(state) => state.profileEdit,
|
||||
);
|
||||
const [newBio, setNewBio] = useState(bio ?? '');
|
||||
const handleChange: ChangeEventHandler<HTMLTextAreaElement> = useCallback(
|
||||
(event) => {
|
||||
setNewBio(event.currentTarget.value);
|
||||
@@ -55,19 +55,22 @@ export const BioModal: FC<BaseConfirmationModalProps> = ({ onClose }) => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (!account) {
|
||||
return <LoadingIndicator />;
|
||||
}
|
||||
const dispatch = useAppDispatch();
|
||||
const handleSave = useCallback(() => {
|
||||
if (!isPending) {
|
||||
void dispatch(patchProfile({ note: newBio })).then(onClose);
|
||||
}
|
||||
}, [dispatch, isPending, newBio, onClose]);
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={intl.formatMessage(
|
||||
account.note_plain ? messages.editTitle : messages.addTitle,
|
||||
)}
|
||||
title={intl.formatMessage(bio ? messages.editTitle : messages.addTitle)}
|
||||
titleId={titleId}
|
||||
confirm={intl.formatMessage(messages.save)}
|
||||
onConfirm={onClose} // To be implemented
|
||||
onConfirm={handleSave}
|
||||
onClose={onClose}
|
||||
updating={isPending}
|
||||
disabled={newBio.length > MAX_BIO_LENGTH}
|
||||
noFocusButton
|
||||
>
|
||||
<div className={classes.inputWrapper}>
|
||||
|
||||
@@ -7,8 +7,8 @@ import { TextInput } from '@/mastodon/components/form_fields';
|
||||
import { insertEmojiAtPosition } from '@/mastodon/features/emoji/utils';
|
||||
import type { BaseConfirmationModalProps } from '@/mastodon/features/ui/components/confirmation_modals';
|
||||
import { ConfirmationModal } from '@/mastodon/features/ui/components/confirmation_modals';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { patchProfile } from '@/mastodon/reducers/slices/profile_edit';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import classes from '../styles.module.scss';
|
||||
|
||||
@@ -37,10 +37,11 @@ export const NameModal: FC<BaseConfirmationModalProps> = ({ onClose }) => {
|
||||
const titleId = useId();
|
||||
const counterId = useId();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const accountId = useCurrentAccountId();
|
||||
const account = useAccount(accountId);
|
||||
|
||||
const [newName, setNewName] = useState(account?.display_name ?? '');
|
||||
const { profile: { displayName } = {}, isPending } = useAppSelector(
|
||||
(state) => state.profileEdit,
|
||||
);
|
||||
const [newName, setNewName] = useState(displayName ?? '');
|
||||
const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(
|
||||
(event) => {
|
||||
setNewName(event.currentTarget.value);
|
||||
@@ -54,13 +55,22 @@ export const NameModal: FC<BaseConfirmationModalProps> = ({ onClose }) => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const handleSave = useCallback(() => {
|
||||
if (!isPending) {
|
||||
void dispatch(patchProfile({ display_name: newName })).then(onClose);
|
||||
}
|
||||
}, [dispatch, isPending, newName, onClose]);
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={intl.formatMessage(messages.editTitle)}
|
||||
titleId={titleId}
|
||||
confirm={intl.formatMessage(messages.save)}
|
||||
onConfirm={onClose} // To be implemented
|
||||
onConfirm={handleSave}
|
||||
onClose={onClose}
|
||||
updating={isPending}
|
||||
disabled={newName.length > MAX_NAME_LENGTH}
|
||||
noCloseOnConfirm
|
||||
noFocusButton
|
||||
>
|
||||
|
||||
@@ -14,7 +14,11 @@ import {
|
||||
fetchFeaturedTags,
|
||||
fetchSuggestedTags,
|
||||
} from '@/mastodon/reducers/slices/profile_edit';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
import {
|
||||
createAppSelector,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '@/mastodon/store';
|
||||
|
||||
import { AccountEditColumn, AccountEditEmptyColumn } from './components/column';
|
||||
import { AccountEditItemList } from './components/item_list';
|
||||
@@ -28,14 +32,23 @@ const messages = defineMessages({
|
||||
},
|
||||
});
|
||||
|
||||
const selectTags = createAppSelector(
|
||||
[(state) => state.profileEdit],
|
||||
(profileEdit) => ({
|
||||
tags: profileEdit.tags ?? [],
|
||||
tagSuggestions: profileEdit.tagSuggestions ?? [],
|
||||
isLoading: !profileEdit.tags || !profileEdit.tagSuggestions,
|
||||
isPending: profileEdit.isPending,
|
||||
}),
|
||||
);
|
||||
|
||||
export const AccountEditFeaturedTags: FC = () => {
|
||||
const accountId = useCurrentAccountId();
|
||||
const account = useAccount(accountId);
|
||||
const intl = useIntl();
|
||||
|
||||
const { tags, tagSuggestions, isLoading, isPending } = useAppSelector(
|
||||
(state) => state.profileEdit,
|
||||
);
|
||||
const { tags, tagSuggestions, isLoading, isPending } =
|
||||
useAppSelector(selectTags);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
|
||||
@@ -7,13 +7,17 @@ import { useHistory } from 'react-router-dom';
|
||||
|
||||
import type { ModalType } from '@/mastodon/actions/modal';
|
||||
import { openModal } from '@/mastodon/actions/modal';
|
||||
import { AccountBio } from '@/mastodon/components/account_bio';
|
||||
import { Avatar } from '@/mastodon/components/avatar';
|
||||
import { DisplayNameSimple } from '@/mastodon/components/display_name/simple';
|
||||
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
|
||||
import { EmojiHTML } from '@/mastodon/components/emoji/html';
|
||||
import { useElementHandledLink } from '@/mastodon/components/status/handled_link';
|
||||
import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import { fetchFeaturedTags } from '@/mastodon/reducers/slices/profile_edit';
|
||||
import {
|
||||
fetchFeaturedTags,
|
||||
fetchProfile,
|
||||
} from '@/mastodon/reducers/slices/profile_edit';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { AccountEditColumn, AccountEditEmptyColumn } from './components/column';
|
||||
@@ -82,11 +86,10 @@ export const AccountEdit: FC = () => {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { tags: featuredTags, isLoading: isTagsLoading } = useAppSelector(
|
||||
(state) => state.profileEdit,
|
||||
);
|
||||
const { profile, tags = [] } = useAppSelector((state) => state.profileEdit);
|
||||
useEffect(() => {
|
||||
void dispatch(fetchFeaturedTags());
|
||||
void dispatch(fetchProfile());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleOpenModal = useCallback(
|
||||
@@ -107,14 +110,20 @@ export const AccountEdit: FC = () => {
|
||||
history.push('/profile/featured_tags');
|
||||
}, [history]);
|
||||
|
||||
if (!accountId || !account) {
|
||||
// Normally we would use the account emoji, but we want all custom emojis to be available to render after editing.
|
||||
const emojis = useAppSelector((state) => state.custom_emojis);
|
||||
const htmlHandlers = useElementHandledLink({
|
||||
hashtagAccountId: profile?.id,
|
||||
});
|
||||
|
||||
if (!accountId || !account || !profile) {
|
||||
return <AccountEditEmptyColumn notFound={!accountId} />;
|
||||
}
|
||||
|
||||
const headerSrc = autoPlayGif ? account.header : account.header_static;
|
||||
const hasName = !!account.display_name;
|
||||
const hasBio = !!account.note_plain;
|
||||
const hasTags = !isTagsLoading && featuredTags.length > 0;
|
||||
const headerSrc = autoPlayGif ? profile.header : profile.headerStatic;
|
||||
const hasName = !!profile.displayName;
|
||||
const hasBio = !!profile.bio;
|
||||
const hasTags = tags.length > 0;
|
||||
|
||||
return (
|
||||
<AccountEditColumn
|
||||
@@ -128,62 +137,64 @@ export const AccountEdit: FC = () => {
|
||||
<Avatar account={account} size={80} className={classes.avatar} />
|
||||
</header>
|
||||
|
||||
<AccountEditSection
|
||||
title={messages.displayNameTitle}
|
||||
description={messages.displayNamePlaceholder}
|
||||
showDescription={!hasName}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleNameEdit}
|
||||
item={messages.displayNameTitle}
|
||||
edit={hasName}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<DisplayNameSimple account={account} />
|
||||
</AccountEditSection>
|
||||
<CustomEmojiProvider emojis={emojis}>
|
||||
<AccountEditSection
|
||||
title={messages.displayNameTitle}
|
||||
description={messages.displayNamePlaceholder}
|
||||
showDescription={!hasName}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleNameEdit}
|
||||
item={messages.displayNameTitle}
|
||||
edit={hasName}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EmojiHTML htmlString={profile.displayName} {...htmlHandlers} />
|
||||
</AccountEditSection>
|
||||
|
||||
<AccountEditSection
|
||||
title={messages.bioTitle}
|
||||
description={messages.bioPlaceholder}
|
||||
showDescription={!hasBio}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleBioEdit}
|
||||
item={messages.bioTitle}
|
||||
edit={hasBio}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<AccountBio accountId={accountId} />
|
||||
</AccountEditSection>
|
||||
<AccountEditSection
|
||||
title={messages.bioTitle}
|
||||
description={messages.bioPlaceholder}
|
||||
showDescription={!hasBio}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleBioEdit}
|
||||
item={messages.bioTitle}
|
||||
edit={hasBio}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EmojiHTML htmlString={profile.bio} {...htmlHandlers} />
|
||||
</AccountEditSection>
|
||||
|
||||
<AccountEditSection
|
||||
title={messages.customFieldsTitle}
|
||||
description={messages.customFieldsPlaceholder}
|
||||
showDescription
|
||||
/>
|
||||
<AccountEditSection
|
||||
title={messages.customFieldsTitle}
|
||||
description={messages.customFieldsPlaceholder}
|
||||
showDescription
|
||||
/>
|
||||
|
||||
<AccountEditSection
|
||||
title={messages.featuredHashtagsTitle}
|
||||
description={messages.featuredHashtagsPlaceholder}
|
||||
showDescription={!hasTags}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleFeaturedTagsEdit}
|
||||
edit={hasTags}
|
||||
item={messages.featuredHashtagsItem}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{featuredTags.map((tag) => `#${tag.name}`).join(', ')}
|
||||
</AccountEditSection>
|
||||
<AccountEditSection
|
||||
title={messages.featuredHashtagsTitle}
|
||||
description={messages.featuredHashtagsPlaceholder}
|
||||
showDescription={!hasTags}
|
||||
buttons={
|
||||
<EditButton
|
||||
onClick={handleFeaturedTagsEdit}
|
||||
edit={hasTags}
|
||||
item={messages.featuredHashtagsItem}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{tags.map((tag) => `#${tag.name}`).join(', ')}
|
||||
</AccountEditSection>
|
||||
|
||||
<AccountEditSection
|
||||
title={messages.profileTabTitle}
|
||||
description={messages.profileTabSubtitle}
|
||||
showDescription
|
||||
/>
|
||||
<AccountEditSection
|
||||
title={messages.profileTabTitle}
|
||||
description={messages.profileTabSubtitle}
|
||||
showDescription
|
||||
/>
|
||||
</CustomEmojiProvider>
|
||||
</AccountEditColumn>
|
||||
);
|
||||
};
|
||||
@@ -262,6 +262,11 @@ svg.badgeIcon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See: https://stackoverflow.com/questions/13226296/is-scrollwidth-property-of-a-span-not-working-on-chrome
|
||||
[data-contents] {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.fieldVerified {
|
||||
|
||||
Reference in new issue
Block a user