1
0
Fork 0
forked from gitea/nas

Merge remote-tracking branch 'parent/main' into upstream-20241203

This commit is contained in:
KMY 2024-12-04 11:56:14 +09:00
commit 0a0b0d46ea
52 changed files with 599 additions and 451 deletions

View file

@ -15,11 +15,11 @@ import DisabledIcon from '@/material-icons/400-24px/close-fill.svg?react';
import EnabledIcon from '@/material-icons/400-24px/done-fill.svg?react';
import ExpandMoreIcon from '@/material-icons/400-24px/expand_more.svg?react';
import { fetchServer, fetchExtendedDescription, fetchDomainBlocks } from 'mastodon/actions/server';
import { Account } from 'mastodon/components/account';
import Column from 'mastodon/components/column';
import { Icon } from 'mastodon/components/icon';
import { ServerHeroImage } from 'mastodon/components/server_hero_image';
import { Skeleton } from 'mastodon/components/skeleton';
import Account from 'mastodon/containers/account_container';
import LinkFooter from 'mastodon/features/ui/components/link_footer';
const messages = defineMessages({

View file

@ -1,6 +1,7 @@
/* eslint-disable react/jsx-no-useless-fragment */
import { FormattedMessage, FormattedNumber } from 'react-intl';
import { domain } from 'mastodon/initial_state';
import type { Percentiles } from 'mastodon/models/annual_report';
export const Percentile: React.FC<{
@ -12,7 +13,7 @@ export const Percentile: React.FC<{
<div className='annual-report__bento__box annual-report__summary__percentile'>
<FormattedMessage
id='annual_report.summary.percentile.text'
defaultMessage='<topLabel>That puts you in the top</topLabel><percentage></percentage><bottomLabel>of Mastodon users.</bottomLabel>'
defaultMessage='<topLabel>That puts you in the top</topLabel><percentage></percentage><bottomLabel>of {domain} users.</bottomLabel>'
values={{
topLabel: (str) => (
<div className='annual-report__summary__percentile__label'>
@ -44,6 +45,8 @@ export const Percentile: React.FC<{
)}
</div>
),
domain,
}}
>
{(message) => <>{message}</>}

View file

@ -9,11 +9,11 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import BlockIcon from '@/material-icons/400-24px/block-fill.svg?react';
import { Account } from 'mastodon/components/account';
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
import Column from '../ui/components/column';
const messages = defineMessages({
@ -70,7 +70,7 @@ class Blocks extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} defaultAction='block' />,
<Account key={id} id={id} defaultAction='block' />,
)}
</ScrollableList>
</Column>

View file

@ -6,7 +6,7 @@ import { useSelector, useDispatch } from 'react-redux';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import { cancelReplyCompose } from 'mastodon/actions/compose';
import Account from 'mastodon/components/account';
import { Account } from 'mastodon/components/account';
import { IconButton } from 'mastodon/components/icon_button';
import { me } from 'mastodon/initial_state';
@ -20,7 +20,6 @@ const messages = defineMessages({
export const NavigationBar = () => {
const dispatch = useDispatch();
const intl = useIntl();
const account = useSelector(state => state.getIn(['accounts', me]));
const isReplying = useSelector(state => !!state.getIn(['compose', 'in_reply_to']));
const handleCancelClick = useCallback(() => {
@ -29,7 +28,7 @@ export const NavigationBar = () => {
return (
<div className='navigation-bar'>
<Account account={account} minimal />
<Account id={me} minimal />
{isReplying ? <IconButton title={intl.formatMessage(messages.cancel)} iconComponent={CloseIcon} onClick={handleCancelClick} /> : <ActionBar />}
</div>
);

View file

@ -6,6 +6,7 @@ import FindInPageIcon from '@/material-icons/400-24px/find_in_page.svg?react';
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import { expandSearch } from 'mastodon/actions/search';
import { Account } from 'mastodon/components/account';
import { Icon } from 'mastodon/components/icon';
import { LoadMore } from 'mastodon/components/load_more';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
@ -13,7 +14,6 @@ import { SearchSection } from 'mastodon/features/explore/components/search_secti
import { useAppDispatch, useAppSelector } from 'mastodon/store';
import { ImmutableHashtag as Hashtag } from '../../../components/hashtag';
import AccountContainer from '../../../containers/account_container';
import StatusContainer from '../../../containers/status_container';
const INITIAL_PAGE_LIMIT = 10;
@ -49,7 +49,7 @@ export const SearchResults = () => {
if (results.get('accounts') && results.get('accounts').size > 0) {
accounts = (
<SearchSection title={<><Icon id='users' icon={PeopleIcon} /><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></>}>
{withoutLastResult(results.get('accounts')).map(accountId => <AccountContainer key={accountId} id={accountId} />)}
{withoutLastResult(results.get('accounts')).map(accountId => <Account key={accountId} id={accountId} />)}
{(results.get('accounts').size > INITIAL_PAGE_LIMIT && results.get('accounts').size % INITIAL_PAGE_LIMIT === 1) && <LoadMore visible onClick={handleLoadMoreAccounts} />}
</SearchSection>
);

View file

@ -10,12 +10,13 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react';
import { fetchEmojiReactions, expandEmojiReactions } from 'mastodon/actions/interactions';
import { Account } from 'mastodon/components/account';
import ColumnHeader from 'mastodon/components/column_header';
import { Icon } from 'mastodon/components/icon';
import ScrollableList from 'mastodon/components/scrollable_list';
import AccountContainer from 'mastodon/containers/account_container';
import Column from 'mastodon/features/ui/components/column';
@ -101,11 +102,11 @@ class EmojiReactions extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{Object.keys(groups).map((key) =>(
<AccountContainer key={key} id={key} withNote={false} hideButtons>
<Account key={key} id={key} hideButtons>
<div style={{ 'maxWidth': '100px' }}>
{groups[key].map((value, index2) => <EmojiView key={index2} name={value.name} url={value.url} staticUrl={value.static_url} />)}
</div>
</AccountContainer>
</Account>
))}
</ScrollableList>

View file

@ -13,10 +13,10 @@ import FindInPageIcon from '@/material-icons/400-24px/find_in_page.svg?react';
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import { submitSearch, expandSearch } from 'mastodon/actions/search';
import { Account } from 'mastodon/components/account';
import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
import { Icon } from 'mastodon/components/icon';
import ScrollableList from 'mastodon/components/scrollable_list';
import Account from 'mastodon/containers/account_container';
import Status from 'mastodon/containers/status_container';
import { SearchSection } from './components/search_section';

View file

@ -14,11 +14,11 @@ import { debounce } from 'lodash';
import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react';
import { fetchFavourites, expandFavourites } from 'mastodon/actions/interactions';
import { Account } from 'mastodon/components/account';
import ColumnHeader from 'mastodon/components/column_header';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import ScrollableList from 'mastodon/components/scrollable_list';
import AccountContainer from 'mastodon/containers/account_container';
import Column from 'mastodon/features/ui/components/column';
const messages = defineMessages({
@ -89,7 +89,7 @@ class Favourites extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />,
<Account key={id} id={id} />,
)}
</ScrollableList>

View file

@ -8,6 +8,7 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import { Account } from 'mastodon/components/account';
import { TimelineHint } from 'mastodon/components/timeline_hint';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import { isHideItem, me } from 'mastodon/initial_state';
@ -24,7 +25,6 @@ import {
import { ColumnBackButton } from '../../components/column_back_button';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
import { LimitedAccountHint } from '../account_timeline/components/limited_account_hint';
import HeaderContainer from '../account_timeline/containers/header_container';
import Column from '../ui/components/column';
@ -179,7 +179,7 @@ class Followers extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{forceEmptyState ? [] : accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />,
<Account key={id} id={id} />,
)}
</ScrollableList>
</Column>

View file

@ -8,6 +8,7 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import { Account } from 'mastodon/components/account';
import { TimelineHint } from 'mastodon/components/timeline_hint';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import { isHideItem, me } from 'mastodon/initial_state';
@ -24,7 +25,6 @@ import {
import { ColumnBackButton } from '../../components/column_back_button';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
import { LimitedAccountHint } from '../account_timeline/components/limited_account_hint';
import HeaderContainer from '../account_timeline/containers/header_container';
import Column from '../ui/components/column';
@ -177,7 +177,7 @@ class Following extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{forceEmptyState ? [] : filteredAccountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />,
<Account key={id} id={id} />,
)}
</ScrollableList>
</Column>

View file

@ -9,9 +9,13 @@ import { useDebouncedCallback } from 'use-debounce';
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
import { fetchRelationships } from 'mastodon/actions/accounts';
import { showAlertForError } from 'mastodon/actions/alerts';
import { importFetchedAccounts } from 'mastodon/actions/importer';
import { fetchList } from 'mastodon/actions/lists';
import { openModal } from 'mastodon/actions/modal';
import { apiRequest } from 'mastodon/api';
import { apiFollowAccount } from 'mastodon/api/accounts';
import {
apiGetAccounts,
apiAddAccountToList,
@ -28,13 +32,14 @@ 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 { me } from 'mastodon/initial_state';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
const messages = defineMessages({
heading: { id: 'column.list_members', defaultMessage: 'Manage list members' },
placeholder: {
id: 'lists.search_placeholder',
defaultMessage: 'Search people you follow',
id: 'lists.search',
defaultMessage: 'Search',
},
enterSearch: { id: 'lists.add_to_list', defaultMessage: 'Add to list' },
add: { id: 'lists.add_member', defaultMessage: 'Add' },
@ -51,17 +56,51 @@ const AccountItem: React.FC<{
onToggle: (accountId: string) => void;
}> = ({ accountId, listId, partOfList, onToggle }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const account = useAppSelector((state) => state.accounts.get(accountId));
const relationship = useAppSelector((state) =>
accountId ? state.relationships.get(accountId) : undefined,
);
const following =
accountId === me || relationship?.following || relationship?.requested;
useEffect(() => {
if (accountId) {
dispatch(fetchRelationships([accountId]));
}
}, [dispatch, accountId]);
const handleClick = useCallback(() => {
if (partOfList) {
void apiRemoveAccountFromList(listId, accountId);
onToggle(accountId);
} else {
void apiAddAccountToList(listId, accountId);
if (following) {
void apiAddAccountToList(listId, accountId);
onToggle(accountId);
} else {
dispatch(
openModal({
modalType: 'CONFIRM_FOLLOW_TO_LIST',
modalProps: {
accountId,
onConfirm: () => {
apiFollowAccount(accountId)
.then(() => apiAddAccountToList(listId, accountId))
.then(() => {
onToggle(accountId);
return '';
})
.catch((err: unknown) => {
dispatch(showAlertForError(err));
});
},
},
}),
);
}
}
onToggle(accountId);
}, [accountId, listId, partOfList, onToggle]);
}, [dispatch, accountId, following, listId, partOfList, onToggle]);
if (!account) {
return null;
@ -187,8 +226,7 @@ const ListMembers: React.FC<{
signal: searchRequestRef.current.signal,
params: {
q: value,
resolve: false,
following: true,
resolve: true,
},
})
.then((data) => {

View file

@ -11,10 +11,10 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import { fetchMentionedUsers, expandMentionedUsers } from 'mastodon/actions/interactions';
import { Account } from 'mastodon/components/account';
import ColumnHeader from 'mastodon/components/column_header';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import ScrollableList from 'mastodon/components/scrollable_list';
import AccountContainer from 'mastodon/containers/account_container';
import Column from 'mastodon/features/ui/components/column';
const mapStateToProps = (state, props) => ({
@ -74,7 +74,7 @@ class MentionedUsers extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />,
<Account key={id} id={id} />,
)}
</ScrollableList>

View file

@ -11,11 +11,11 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import VolumeOffIcon from '@/material-icons/400-24px/volume_off.svg?react';
import { Account } from 'mastodon/components/account';
import { fetchMutes, expandMutes } from '../../actions/mutes';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
import Column from '../ui/components/column';
const messages = defineMessages({
@ -72,7 +72,7 @@ class Mutes extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} defaultAction='mute' />,
<Account key={id} id={id} defaultAction='mute' />,
)}
</ScrollableList>

View file

@ -20,9 +20,9 @@ import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react';
import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import { Account } from 'mastodon/components/account';
import EmojiView from 'mastodon/components/emoji_view';
import { Icon } from 'mastodon/components/icon';
import AccountContainer from 'mastodon/containers/account_container';
import StatusContainer from 'mastodon/containers/status_container';
import { me } from 'mastodon/initial_state';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -153,7 +153,7 @@ class Notification extends ImmutablePureComponent {
</span>
</div>
<AccountContainer id={account.get('id')} hidden={this.props.hidden} />
<Account id={account.get('id')} hidden={this.props.hidden} />
</div>
</HotKeys>
);
@ -173,7 +173,7 @@ class Notification extends ImmutablePureComponent {
</span>
</div>
<FollowRequestContainer id={account.get('id')} withNote={false} hidden={this.props.hidden} />
<FollowRequestContainer id={account.get('id')} hidden={this.props.hidden} />
</div>
</HotKeys>
);
@ -533,7 +533,7 @@ class Notification extends ImmutablePureComponent {
</span>
</div>
<AccountContainer id={account.get('id')} hidden={this.props.hidden} />
<Account id={account.get('id')} hidden={this.props.hidden} />
</div>
</HotKeys>
);

View file

@ -14,11 +14,11 @@ import { fetchSuggestions } from 'mastodon/actions/suggestions';
import { markAsPartial } from 'mastodon/actions/timelines';
import { apiRequest } from 'mastodon/api';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
import { Account } from 'mastodon/components/account';
import { Column } from 'mastodon/components/column';
import { ColumnHeader } from 'mastodon/components/column_header';
import { ColumnSearchHeader } from 'mastodon/components/column_search_header';
import ScrollableList from 'mastodon/components/scrollable_list';
import Account from 'mastodon/containers/account_container';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
const messages = defineMessages({
@ -170,12 +170,7 @@ export const Follows: React.FC<{
}
>
{displayedAccountIds.map((accountId) => (
<Account
/* @ts-expect-error inferred props are wrong */
id={accountId}
key={accountId}
withBio
/>
<Account id={accountId} key={accountId} withBio />
))}
</ScrollableList>

View file

@ -11,13 +11,13 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react';
import { Account } from 'mastodon/components/account';
import { Icon } from 'mastodon/components/icon';
import { fetchReblogs, expandReblogs } from '../../actions/interactions';
import ColumnHeader from '../../components/column_header';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
import Column from '../ui/components/column';
const messages = defineMessages({
@ -88,7 +88,7 @@ class Reblogs extends ImmutablePureComponent {
bindToDocument={!multiColumn}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />,
<Account key={id} id={id} />,
)}
</ScrollableList>

View file

@ -0,0 +1,43 @@
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useAppSelector } from 'mastodon/store';
import type { BaseConfirmationModalProps } from './confirmation_modal';
import { ConfirmationModal } from './confirmation_modal';
const messages = defineMessages({
title: {
id: 'confirmations.follow_to_list.title',
defaultMessage: 'Follow user?',
},
confirm: {
id: 'confirmations.follow_to_list.confirm',
defaultMessage: 'Follow and add to list',
},
});
export const ConfirmFollowToListModal: React.FC<
{
accountId: string;
onConfirm: () => void;
} & BaseConfirmationModalProps
> = ({ accountId, onConfirm, onClose }) => {
const intl = useIntl();
const account = useAppSelector((state) => state.accounts.get(accountId));
return (
<ConfirmationModal
title={intl.formatMessage(messages.title)}
message={
<FormattedMessage
id='confirmations.follow_to_list.message'
defaultMessage='You need to be following {name} to add them to a list.'
values={{ name: <strong>@{account?.acct}</strong> }}
/>
}
confirm={intl.formatMessage(messages.confirm)}
onConfirm={onConfirm}
onClose={onClose}
/>
);
};

View file

@ -9,3 +9,4 @@ export { ConfirmEditStatusModal } from './edit_status';
export { ConfirmUnfollowModal } from './unfollow';
export { ConfirmClearNotificationsModal } from './clear_notifications';
export { ConfirmLogOutModal } from './log_out';
export { ConfirmFollowToListModal } from './follow_to_list';

View file

@ -41,6 +41,7 @@ import {
ConfirmUnfollowModal,
ConfirmClearNotificationsModal,
ConfirmLogOutModal,
ConfirmFollowToListModal,
} from './confirmation_modals';
import FocalPointModal from './focal_point_modal';
import ImageModal from './image_modal';
@ -65,6 +66,7 @@ export const MODAL_COMPONENTS = {
'CONFIRM_UNFOLLOW': () => Promise.resolve({ default: ConfirmUnfollowModal }),
'CONFIRM_CLEAR_NOTIFICATIONS': () => Promise.resolve({ default: ConfirmClearNotificationsModal }),
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
'MUTE': MuteModal,
'BLOCK': BlockModal,
'DOMAIN_BLOCK': DomainBlockModal,