Merge commit '66fdd3ae65e13349fbc0b2818d4b91a389075553' into glitch-soc/main
This commit is contained in:
commit
b9014ec220
184 files changed
+1237
-1059
No files matched your search
@@ -19,17 +19,17 @@ import type { Account } from '@/mastodon/models/account';
|
||||
import { getAccountHidden } from '@/mastodon/selectors/accounts';
|
||||
import { useAppSelector, useAppDispatch } from '@/mastodon/store';
|
||||
|
||||
import { FamiliarFollowers } from '../../../components/familiar_followers';
|
||||
|
||||
import { AccountName } from './account_name';
|
||||
import { AccountSubscriptionForm } from './account_subscription_form';
|
||||
import { AccountBadges } from './badges';
|
||||
import { AccountButtons } from './buttons';
|
||||
import { FamiliarFollowers } from './familiar_followers';
|
||||
import { AccountHeaderFields } from './fields';
|
||||
import { MemorialNote } from './memorial_note';
|
||||
import { MovedNote } from './moved_note';
|
||||
import { AccountNote as AccountNoteRedesign } from './note';
|
||||
import { AccountNote } from './note';
|
||||
import { AccountNumberFields } from './number_fields';
|
||||
import redesignClasses from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
import { AccountTabs } from './tabs';
|
||||
|
||||
const titleFromAccount = (account: Account) => {
|
||||
@@ -111,12 +111,7 @@ export const AccountHeader: React.FC<{
|
||||
<FollowRequestNoteContainer account={account} />
|
||||
)}
|
||||
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__image',
|
||||
redesignClasses.header,
|
||||
)}
|
||||
>
|
||||
<div className={classNames('account__header__image', classes.header)}>
|
||||
{!suspendedOrHidden && (
|
||||
<img
|
||||
src={autoPlayGif ? account.header : account.header_static}
|
||||
@@ -126,16 +121,11 @@ export const AccountHeader: React.FC<{
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__bar',
|
||||
redesignClasses.barWrapper,
|
||||
)}
|
||||
>
|
||||
<div className={classNames('account__header__bar', classes.barWrapper)}>
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__tabs',
|
||||
redesignClasses.avatarWrapper,
|
||||
classes.avatarWrapper,
|
||||
)}
|
||||
>
|
||||
<a
|
||||
@@ -156,31 +146,32 @@ export const AccountHeader: React.FC<{
|
||||
<div
|
||||
className={classNames(
|
||||
'account__header__tabs__name',
|
||||
redesignClasses.displayNameWrapper,
|
||||
classes.displayNameWrapper,
|
||||
)}
|
||||
>
|
||||
<AccountName accountId={accountId} />
|
||||
<AccountButtons
|
||||
accountId={accountId}
|
||||
className={redesignClasses.buttonsDesktop}
|
||||
className={classes.buttonsDesktop}
|
||||
noShare={!isMe || 'share' in navigator}
|
||||
forceMenu={'share' in navigator}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<AccountBadges accountId={accountId} />
|
||||
|
||||
<AccountNumberFields accountId={accountId} />
|
||||
|
||||
{!isMe && !suspendedOrHidden && (
|
||||
<FamiliarFollowers accountId={accountId} />
|
||||
<FamiliarFollowers
|
||||
accountId={accountId}
|
||||
className={classes.familiarFollowers}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!suspendedOrHidden && (
|
||||
<div className='account__header__extra'>
|
||||
<div className='account__header__bio'>
|
||||
{me && account.id !== me && (
|
||||
<AccountNoteRedesign accountId={accountId} />
|
||||
<AccountNote accountId={accountId} />
|
||||
)}
|
||||
|
||||
<AccountBio
|
||||
@@ -188,7 +179,7 @@ export const AccountHeader: React.FC<{
|
||||
accountId={accountId}
|
||||
className={classNames(
|
||||
'account__header__content',
|
||||
redesignClasses.bio,
|
||||
classes.bio,
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -203,8 +194,8 @@ export const AccountHeader: React.FC<{
|
||||
|
||||
<AccountButtons
|
||||
className={classNames(
|
||||
redesignClasses.buttonsMobile,
|
||||
!isIntersecting && redesignClasses.buttonsMobileIsStuck,
|
||||
classes.buttonsMobile,
|
||||
!isIntersecting && classes.buttonsMobileIsStuck,
|
||||
)}
|
||||
accountId={accountId}
|
||||
noShare
|
||||
|
||||
@@ -21,7 +21,8 @@ import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react';
|
||||
import HelpIcon from '@/material-icons/400-24px/help.svg?react';
|
||||
import DomainIcon from '@/material-icons/400-24px/language.svg?react';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import { AccountBadges } from './badges';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const messages = defineMessages({
|
||||
lockedInfo: {
|
||||
@@ -77,6 +78,8 @@ export const AccountName: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
domain={domain}
|
||||
isSelf={account.id === me}
|
||||
/>
|
||||
|
||||
<AccountBadges accountId={accountId} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+5
-2
@@ -3,6 +3,7 @@ import { useState, useCallback, useId } from 'react';
|
||||
import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
|
||||
import type { IntlShape } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
@@ -18,7 +19,7 @@ import type { FieldStatus } from 'mastodon/components/form_fields';
|
||||
import { TextInputField } from 'mastodon/components/form_fields/text_input_field';
|
||||
import { useAppSelector } from 'mastodon/store';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const messages = defineMessages({
|
||||
emailInvalid: {
|
||||
@@ -127,7 +128,9 @@ export const AccountSubscriptionForm: React.FC<{ accountId: string }> = ({
|
||||
|
||||
if (submitted) {
|
||||
return (
|
||||
<div className={classes.bannerBaseCentered}>
|
||||
<div
|
||||
className={classNames(classes.bannerBase, classes.bannerBaseCentered)}
|
||||
>
|
||||
<div className={classes.bannerTextAndActions}>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
|
||||
@@ -16,6 +16,8 @@ import { useAccount } from '@/mastodon/hooks/useAccount';
|
||||
import type { AccountRole } from '@/mastodon/models/account';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
const account = useAccount(accountId);
|
||||
const localDomain = useAppSelector(
|
||||
@@ -101,7 +103,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <div className={'account__header__badges'}>{badges}</div>;
|
||||
return <div className={classes.badges}>{badges}</div>;
|
||||
};
|
||||
|
||||
function isAdminBadge(role: AccountRole) {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Avatar } from '@/mastodon/components/avatar';
|
||||
import { AvatarGroup } from '@/mastodon/components/avatar_group';
|
||||
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||
import type { Account } from '@/mastodon/models/account';
|
||||
|
||||
import { useFetchFamiliarFollowers } from '../hooks/familiar_followers';
|
||||
|
||||
const FamiliarFollowersReadout: React.FC<{ familiarFollowers: Account[] }> = ({
|
||||
familiarFollowers,
|
||||
}) => {
|
||||
const messageData = {
|
||||
name1: (
|
||||
<LinkedDisplayName
|
||||
displayProps={{ account: familiarFollowers.at(0), variant: 'simple' }}
|
||||
/>
|
||||
),
|
||||
name2: (
|
||||
<LinkedDisplayName
|
||||
displayProps={{ account: familiarFollowers.at(1), variant: 'simple' }}
|
||||
/>
|
||||
),
|
||||
othersCount: familiarFollowers.length - 2,
|
||||
};
|
||||
|
||||
if (familiarFollowers.length === 1) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='account.familiar_followers_one'
|
||||
defaultMessage='Followed by {name1}'
|
||||
values={messageData}
|
||||
/>
|
||||
);
|
||||
} else if (familiarFollowers.length === 2) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='account.familiar_followers_two'
|
||||
defaultMessage='Followed by {name1} and {name2}'
|
||||
values={messageData}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='account.familiar_followers_many'
|
||||
defaultMessage='Followed by {name1}, {name2}, and {othersCount, plural, one {one other you know} other {# others you know}}'
|
||||
values={messageData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const FamiliarFollowers: React.FC<{ accountId: string }> = ({
|
||||
accountId,
|
||||
}) => {
|
||||
const { familiarFollowers, isLoading } = useFetchFamiliarFollowers({
|
||||
accountId,
|
||||
});
|
||||
|
||||
if (isLoading || familiarFollowers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account__header__familiar-followers'>
|
||||
<AvatarGroup compact>
|
||||
{familiarFollowers.slice(0, 3).map((account) => (
|
||||
<Avatar withLink key={account.id} account={account} size={28} />
|
||||
))}
|
||||
</AvatarGroup>
|
||||
<span>
|
||||
<FamiliarFollowersReadout familiarFollowers={familiarFollowers} />
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -23,7 +23,7 @@ import { cleanExtraEmojis } from '../../emoji/normalize';
|
||||
import type { AccountField } from '../common';
|
||||
import { useFieldHtml } from '../hooks/useFieldHtml';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const verifyMessage = defineMessage({
|
||||
id: 'account.link_verified_on',
|
||||
@@ -285,11 +285,14 @@ function useColumnWrap() {
|
||||
if (!item) {
|
||||
break;
|
||||
}
|
||||
|
||||
const { ele, span } = item;
|
||||
|
||||
if (i < row.length - 1) {
|
||||
ele.dataset.cols = span.toString();
|
||||
remainingRowSpan -= span;
|
||||
} else if (
|
||||
row.length > 1 &&
|
||||
row.length === halfColSpan &&
|
||||
span === 1 &&
|
||||
remainingRowSpan > 1
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { FC } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import {
|
||||
blockAccount,
|
||||
followAccount,
|
||||
pinAccount,
|
||||
unblockAccount,
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
} from '@/mastodon/actions/accounts';
|
||||
import { removeAccountFromFollowers } from '@/mastodon/actions/accounts_typed';
|
||||
import { showAlert } from '@/mastodon/actions/alerts';
|
||||
import { initBlockModal } from '@/mastodon/actions/blocks';
|
||||
import { directCompose, mentionCompose } from '@/mastodon/actions/compose';
|
||||
import {
|
||||
initDomainBlockModal,
|
||||
@@ -40,7 +40,7 @@ import PersonRemoveIcon from '@/material-icons/400-24px/person_remove.svg?react'
|
||||
import ReportIcon from '@/material-icons/400-24px/report.svg?react';
|
||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
const intl = useIntl();
|
||||
@@ -61,7 +61,7 @@ export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
return [];
|
||||
}
|
||||
|
||||
return redesignMenuItems({
|
||||
return getMenuItems({
|
||||
account,
|
||||
signedIn: !isMe && signedIn,
|
||||
permissions,
|
||||
@@ -223,7 +223,7 @@ const redesignMessages = defineMessages({
|
||||
},
|
||||
});
|
||||
|
||||
function redesignMenuItems({
|
||||
function getMenuItems({
|
||||
account,
|
||||
signedIn,
|
||||
permissions,
|
||||
@@ -435,7 +435,7 @@ function redesignMenuItems({
|
||||
if (relationship?.blocking) {
|
||||
dispatch(unblockAccount(account.id));
|
||||
} else {
|
||||
dispatch(blockAccount(account.id));
|
||||
dispatch(initBlockModal(account));
|
||||
}
|
||||
},
|
||||
dangerous: true,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { IconButton } from '@/mastodon/components/icon_button';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
import EditIcon from '@/material-icons/400-24px/edit_square.svg?react';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: {
|
||||
|
||||
+19
-14
@@ -28,14 +28,12 @@
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
align-items: baseline;
|
||||
|
||||
> h1 {
|
||||
display: inline;
|
||||
font-size: 22px;
|
||||
line-height: normal;
|
||||
white-space: initial;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +41,10 @@
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.badges {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.handleHelpButton {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
@@ -191,6 +193,10 @@ $button-fallback-breakpoint: $button-breakpoint + 55px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.familiarFollowers {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.note {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
@@ -406,6 +412,15 @@ $button-fallback-breakpoint: $button-breakpoint + 55px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.bannerBaseCentered {
|
||||
min-height: 146px;
|
||||
align-items: center;
|
||||
|
||||
.bannerTextAndActions {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.bannerTextAndActions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -426,16 +441,6 @@ $button-fallback-breakpoint: $button-breakpoint + 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.bannerBaseCentered {
|
||||
composes: bannerBase;
|
||||
min-height: 146px;
|
||||
align-items: center;
|
||||
|
||||
.bannerTextAndActions {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.bannerInputButton {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@@ -10,7 +10,7 @@ import { useAccountId } from '@/mastodon/hooks/useAccountId';
|
||||
|
||||
import { areCollectionsEnabled } from '../../collections/utils';
|
||||
|
||||
import classes from './redesign.module.scss';
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
const isActive: Required<NavLinkProps>['isActive'] = (match, location) =>
|
||||
match?.url === location.pathname ||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { fetchAccountsFamiliarFollowers } from '@/mastodon/actions/accounts_familiar_followers';
|
||||
import { useIdentity } from '@/mastodon/identity_context';
|
||||
import { getAccountFamiliarFollowers } from '@/mastodon/selectors/accounts';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
|
||||
export const useFetchFamiliarFollowers = ({
|
||||
accountId,
|
||||
}: {
|
||||
accountId?: string;
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const familiarFollowers = useAppSelector((state) =>
|
||||
accountId ? getAccountFamiliarFollowers(state, accountId) : null,
|
||||
);
|
||||
const { signedIn } = useIdentity();
|
||||
|
||||
const hasNoData = familiarFollowers === null;
|
||||
|
||||
useEffect(() => {
|
||||
if (hasNoData && signedIn && accountId && accountId !== me) {
|
||||
void dispatch(fetchAccountsFamiliarFollowers({ id: accountId }));
|
||||
}
|
||||
}, [dispatch, accountId, hasNoData, signedIn]);
|
||||
|
||||
return {
|
||||
familiarFollowers: hasNoData ? [] : familiarFollowers,
|
||||
isLoading: hasNoData,
|
||||
};
|
||||
};
|
||||
@@ -3,22 +3,17 @@ import { useCallback, useRef, useState } from 'react';
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import type { ApiCollectionJSON } from 'mastodon/api_types/collections';
|
||||
import { Account } from 'mastodon/components/account';
|
||||
import type { RenderButtonOptions } from 'mastodon/components/account_list_item';
|
||||
import {
|
||||
AccountListItem,
|
||||
AccountListItemFollowButton,
|
||||
} from 'mastodon/components/account_list_item';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { Callout } from 'mastodon/components/callout';
|
||||
import { FollowButton } from 'mastodon/components/follow_button';
|
||||
import {
|
||||
NumberFields,
|
||||
NumberFieldsItem,
|
||||
} from 'mastodon/components/number_fields';
|
||||
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||
import {
|
||||
Article,
|
||||
ItemList,
|
||||
} from 'mastodon/components/scrollable_list/components';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import { useAccount } from 'mastodon/hooks/useAccount';
|
||||
import { useRelationship } from 'mastodon/hooks/useRelationship';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
|
||||
import { useConfirmRevoke } from './revoke_collection_inclusion_modal';
|
||||
@@ -31,99 +26,6 @@ const messages = defineMessages({
|
||||
},
|
||||
});
|
||||
|
||||
const AccountItem: React.FC<{
|
||||
accountId: string | undefined;
|
||||
collectionOwnerId: string;
|
||||
onRevoke: () => void;
|
||||
withBio?: boolean;
|
||||
withBorder?: boolean;
|
||||
}> = ({
|
||||
accountId,
|
||||
collectionOwnerId,
|
||||
onRevoke,
|
||||
withBio = true,
|
||||
withBorder = true,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const account = useAccount(accountId);
|
||||
const relationship = useRelationship(accountId);
|
||||
|
||||
if (!accountId || !account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// When viewing your own collection, only show the Follow button
|
||||
// for accounts you're not following (anymore).
|
||||
// Otherwise, always show the follow button in its various states.
|
||||
const isOwnAccount = accountId === me;
|
||||
const withoutButton =
|
||||
isOwnAccount ||
|
||||
!relationship ||
|
||||
(collectionOwnerId === me &&
|
||||
(relationship.following || relationship.requested));
|
||||
|
||||
return (
|
||||
<div className={classes.accountItemWrapper} data-with-border={withBorder}>
|
||||
<Account
|
||||
minimal
|
||||
id={accountId}
|
||||
withBio={withBio}
|
||||
withBorder={false}
|
||||
withMenu={false}
|
||||
className={classes.accountItem}
|
||||
extraAccountInfo={
|
||||
<NumberFields>
|
||||
<NumberFieldsItem
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='account.followers'
|
||||
defaultMessage='Followers'
|
||||
/>
|
||||
}
|
||||
hint={intl.formatNumber(account.followers_count)}
|
||||
>
|
||||
<ShortNumber value={account.followers_count} />
|
||||
</NumberFieldsItem>
|
||||
|
||||
<NumberFieldsItem
|
||||
label={
|
||||
<FormattedMessage id='account.posts' defaultMessage='Posts' />
|
||||
}
|
||||
hint={intl.formatNumber(account.statuses_count)}
|
||||
>
|
||||
<ShortNumber value={account.statuses_count} />
|
||||
</NumberFieldsItem>
|
||||
|
||||
<NumberFieldsItem
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='account.last_active'
|
||||
defaultMessage='Last active'
|
||||
/>
|
||||
}
|
||||
>
|
||||
<RelativeTimestamp
|
||||
long
|
||||
timestamp={account.last_status_at}
|
||||
noFuture
|
||||
/>
|
||||
</NumberFieldsItem>
|
||||
</NumberFields>
|
||||
}
|
||||
/>
|
||||
{!withoutButton && <FollowButton compact accountId={accountId} />}
|
||||
{isOwnAccount && (
|
||||
<Button secondary compact onClick={onRevoke}>
|
||||
<FormattedMessage
|
||||
id='collections.detail.revoke_inclusion'
|
||||
defaultMessage='Remove me'
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SensitiveScreen: React.FC<{
|
||||
sensitive: boolean | undefined;
|
||||
focusTargetRef: React.RefObject<HTMLHeadingElement>;
|
||||
@@ -158,6 +60,7 @@ const SensitiveScreen: React.FC<{
|
||||
/>
|
||||
}
|
||||
onPrimary={showAnyway}
|
||||
className={classes.sensitiveScreen}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='collections.detail.sensitive_note'
|
||||
@@ -176,14 +79,37 @@ export const CollectionAccountsList: React.FC<{
|
||||
const listHeadingRef = useRef<HTMLHeadingElement>(null);
|
||||
|
||||
const isOwnCollection = collection?.account_id === me;
|
||||
const { items = [] } = collection ?? {};
|
||||
const { items = [], account_id: collectionOwnerId } = collection ?? {};
|
||||
|
||||
const renderAccountItemButton = useCallback(
|
||||
({ relationship, accountId }: RenderButtonOptions) => {
|
||||
// When viewing your own collection, only show the Follow button
|
||||
// for accounts you're not following anymore.
|
||||
const withoutButton =
|
||||
!relationship ||
|
||||
(collectionOwnerId === me &&
|
||||
(relationship.following || relationship.requested));
|
||||
|
||||
if (withoutButton) return null;
|
||||
|
||||
if (accountId === me) {
|
||||
return (
|
||||
<Button secondary compact onClick={confirmRevoke}>
|
||||
<FormattedMessage
|
||||
id='collections.detail.revoke_inclusion'
|
||||
defaultMessage='Remove me'
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return <AccountListItemFollowButton accountId={accountId} />;
|
||||
},
|
||||
[collectionOwnerId, confirmRevoke],
|
||||
);
|
||||
|
||||
return (
|
||||
<ItemList
|
||||
isLoading={isLoading}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
className={classes.itemList}
|
||||
>
|
||||
<>
|
||||
<h3
|
||||
className={classes.columnSubheading}
|
||||
tabIndex={-1}
|
||||
@@ -207,22 +133,27 @@ export const CollectionAccountsList: React.FC<{
|
||||
sensitive={!isOwnCollection && collection.sensitive}
|
||||
focusTargetRef={listHeadingRef}
|
||||
>
|
||||
{items.map(({ account_id }, index) => (
|
||||
<Article
|
||||
key={account_id}
|
||||
aria-posinset={index + 1}
|
||||
aria-setsize={items.length}
|
||||
>
|
||||
<AccountItem
|
||||
withBorder={index !== items.length - 1}
|
||||
accountId={account_id}
|
||||
collectionOwnerId={collection.account_id}
|
||||
onRevoke={confirmRevoke}
|
||||
/>
|
||||
</Article>
|
||||
))}
|
||||
<ItemList
|
||||
isLoading={isLoading}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
>
|
||||
{items.map(({ account_id }, index) => (
|
||||
<Article
|
||||
key={account_id}
|
||||
aria-posinset={index + 1}
|
||||
aria-setsize={items.length}
|
||||
>
|
||||
<AccountListItem
|
||||
accountId={account_id}
|
||||
withBorder={index !== items.length - 1}
|
||||
stats={['followers', 'last-active']}
|
||||
renderButton={renderAccountItemButton}
|
||||
/>
|
||||
</Article>
|
||||
))}
|
||||
</ItemList>
|
||||
</SensitiveScreen>
|
||||
)}
|
||||
</ItemList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import { useAccountHandle } from '@/mastodon/components/display_name/default';
|
||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||
import type { ApiCollectionJSON } from 'mastodon/api_types/collections';
|
||||
import { Badge } from 'mastodon/components/badge';
|
||||
import { Callout } from 'mastodon/components/callout';
|
||||
import { Column } from 'mastodon/components/column';
|
||||
import { ColumnHeader } from 'mastodon/components/column_header';
|
||||
@@ -138,7 +139,7 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
||||
<header className={classes.header}>
|
||||
<div className={classes.titleWithMenu}>
|
||||
<div className={classes.titleWrapper}>
|
||||
{tag && <span className={classes.tag}>#{tag.name}</span>}
|
||||
{tag && <Badge label={`#${tag.name}`} icon={null} />}
|
||||
<h2 className={classes.name}>{name}</h2>
|
||||
<AuthorNote id={account_id} />
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 24px;
|
||||
padding: 16px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.titleWithMenu {
|
||||
@@ -20,15 +21,6 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
background: var(--color-bg-secondary);
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
@@ -71,45 +63,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.itemList {
|
||||
padding-inline: 24px;
|
||||
.sensitiveScreen {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.columnSubheading {
|
||||
padding-bottom: 12px;
|
||||
padding-inline: 16px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.accountItemWrapper {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
padding-block: 16px;
|
||||
|
||||
&[data-with-border='true'] {
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
}
|
||||
|
||||
:global(.account__note) {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
line-clamp: 3;
|
||||
}
|
||||
|
||||
// Hide 'No description provided' message added by `Account` component
|
||||
:global(.account__note--missing) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.accountItem {
|
||||
--account-name-size: 15px;
|
||||
--account-handle-color: var(--color-text-secondary);
|
||||
--account-handle-size: 13px;
|
||||
--account-bio-color: var(--color-text-primary);
|
||||
--account-bio-size: 13px;
|
||||
--account-outer-spacing: 0;
|
||||
|
||||
flex-grow: 1;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
|
||||
import { Account } from '@/mastodon/components/account';
|
||||
import { AccountListItem } from '@/mastodon/components/account_list_item';
|
||||
import { Column } from '@/mastodon/components/column';
|
||||
import { ColumnBackButton } from '@/mastodon/components/column_back_button';
|
||||
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
|
||||
@@ -53,12 +53,12 @@ export const AccountList: FC<AccountListProps> = ({
|
||||
}
|
||||
const children =
|
||||
list?.items.map((followerId) => (
|
||||
<Account key={followerId} id={followerId} />
|
||||
<AccountListItem key={followerId} accountId={followerId} />
|
||||
)) ?? [];
|
||||
|
||||
if (prependAccountId) {
|
||||
children.unshift(
|
||||
<Account key={prependAccountId} id={prependAccountId} minimal />,
|
||||
<AccountListItem key={prependAccountId} accountId={prependAccountId} />,
|
||||
);
|
||||
}
|
||||
return children;
|
||||
|
||||
+5
-6
@@ -16,12 +16,12 @@ import {
|
||||
} from 'mastodon/actions/suggestions';
|
||||
import type { ApiSuggestionSourceJSON } from 'mastodon/api_types/suggestions';
|
||||
import { Avatar } from 'mastodon/components/avatar';
|
||||
import { Badge, VerifiedBadge } from 'mastodon/components/badge';
|
||||
import { DisplayName } from 'mastodon/components/display_name';
|
||||
import { FollowButton } from 'mastodon/components/follow_button';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import { VerifiedBadge } from 'mastodon/components/verified_badge';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
@@ -110,13 +110,12 @@ const Source: React.FC<{ id: ApiSuggestionSourceJSON }> = ({ id }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
<Badge
|
||||
className='inline-follow-suggestions__body__scrollable__card__text-stack__source'
|
||||
title={hint}
|
||||
>
|
||||
<Icon id='' icon={InfoIcon} />
|
||||
<span>{label}</span>
|
||||
</div>
|
||||
label={label}
|
||||
icon={<InfoIcon />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
apiRemoveAccountFromList,
|
||||
} from 'mastodon/api/lists';
|
||||
import { Avatar } from 'mastodon/components/avatar';
|
||||
import { VerifiedBadge } from 'mastodon/components/badge';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { Column } from 'mastodon/components/column';
|
||||
import { ColumnHeader } from 'mastodon/components/column_header';
|
||||
@@ -27,7 +28,6 @@ import { FollowersCounter } from 'mastodon/components/counters';
|
||||
import { DisplayName } from 'mastodon/components/display_name';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import { VerifiedBadge } from 'mastodon/components/verified_badge';
|
||||
import { useSearchAccounts } from 'mastodon/hooks/useSearchAccounts';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
Reference in new issue
Block a user