mirror of
https://github.com/mastodon/mastodon
synced 2024-11-30 15:58:14 +09:00
Add ability to search for all accounts when creating a list in web UI
This commit is contained in:
parent
86b42b0957
commit
1f6e616f17
@ -5,3 +5,16 @@ export const apiSubmitAccountNote = (id: string, value: string) =>
|
|||||||
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/note`, {
|
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/note`, {
|
||||||
comment: value,
|
comment: value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const apiFollowAccount = (
|
||||||
|
id: string,
|
||||||
|
params?: {
|
||||||
|
reblogs: boolean;
|
||||||
|
},
|
||||||
|
) =>
|
||||||
|
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/follow`, {
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const apiUnfollowAccount = (id: string) =>
|
||||||
|
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/unfollow`);
|
||||||
|
@ -9,10 +9,12 @@ import { useDebouncedCallback } from 'use-debounce';
|
|||||||
|
|
||||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
||||||
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
||||||
import { fetchFollowing } from 'mastodon/actions/accounts';
|
import { fetchFollowing, fetchRelationships } from 'mastodon/actions/accounts';
|
||||||
import { importFetchedAccounts } from 'mastodon/actions/importer';
|
import { importFetchedAccounts } from 'mastodon/actions/importer';
|
||||||
import { fetchList } from 'mastodon/actions/lists';
|
import { fetchList } from 'mastodon/actions/lists';
|
||||||
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import { apiRequest } from 'mastodon/api';
|
import { apiRequest } from 'mastodon/api';
|
||||||
|
import { apiFollowAccount } from 'mastodon/api/accounts';
|
||||||
import {
|
import {
|
||||||
apiGetAccounts,
|
apiGetAccounts,
|
||||||
apiAddAccountToList,
|
apiAddAccountToList,
|
||||||
@ -35,8 +37,8 @@ import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.list_members', defaultMessage: 'Manage list members' },
|
heading: { id: 'column.list_members', defaultMessage: 'Manage list members' },
|
||||||
placeholder: {
|
placeholder: {
|
||||||
id: 'lists.search_placeholder',
|
id: 'lists.search',
|
||||||
defaultMessage: 'Search people you follow',
|
defaultMessage: 'Search',
|
||||||
},
|
},
|
||||||
enterSearch: { id: 'lists.add_to_list', defaultMessage: 'Add to list' },
|
enterSearch: { id: 'lists.add_to_list', defaultMessage: 'Add to list' },
|
||||||
add: { id: 'lists.add_member', defaultMessage: 'Add' },
|
add: { id: 'lists.add_member', defaultMessage: 'Add' },
|
||||||
@ -53,17 +55,50 @@ const AccountItem: React.FC<{
|
|||||||
onToggle: (accountId: string) => void;
|
onToggle: (accountId: string) => void;
|
||||||
}> = ({ accountId, listId, partOfList, onToggle }) => {
|
}> = ({ accountId, listId, partOfList, onToggle }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const account = useAppSelector((state) => state.accounts.get(accountId));
|
const account = useAppSelector((state) => state.accounts.get(accountId));
|
||||||
|
const relationship = useAppSelector((state) =>
|
||||||
|
accountId ? state.relationships.get(accountId) : undefined,
|
||||||
|
);
|
||||||
|
const following = relationship?.following || relationship?.requested;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (accountId) {
|
||||||
|
dispatch(fetchRelationships([accountId]));
|
||||||
|
}
|
||||||
|
}, [dispatch, accountId]);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
if (partOfList) {
|
if (partOfList) {
|
||||||
void apiRemoveAccountFromList(listId, accountId);
|
void apiRemoveAccountFromList(listId, accountId);
|
||||||
|
onToggle(accountId);
|
||||||
} else {
|
} 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(() => {
|
||||||
|
// Nothing
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}, [dispatch, accountId, following, listId, partOfList, onToggle]);
|
||||||
onToggle(accountId);
|
|
||||||
}, [accountId, listId, partOfList, onToggle]);
|
|
||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
return null;
|
return null;
|
||||||
@ -193,8 +228,7 @@ const ListMembers: React.FC<{
|
|||||||
signal: searchRequestRef.current.signal,
|
signal: searchRequestRef.current.signal,
|
||||||
params: {
|
params: {
|
||||||
q: value,
|
q: value,
|
||||||
resolve: false,
|
resolve: true,
|
||||||
following: true,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
@ -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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -6,3 +6,4 @@ export { ConfirmEditStatusModal } from './edit_status';
|
|||||||
export { ConfirmUnfollowModal } from './unfollow';
|
export { ConfirmUnfollowModal } from './unfollow';
|
||||||
export { ConfirmClearNotificationsModal } from './clear_notifications';
|
export { ConfirmClearNotificationsModal } from './clear_notifications';
|
||||||
export { ConfirmLogOutModal } from './log_out';
|
export { ConfirmLogOutModal } from './log_out';
|
||||||
|
export { ConfirmFollowToListModal } from './follow_to_list';
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
ConfirmUnfollowModal,
|
ConfirmUnfollowModal,
|
||||||
ConfirmClearNotificationsModal,
|
ConfirmClearNotificationsModal,
|
||||||
ConfirmLogOutModal,
|
ConfirmLogOutModal,
|
||||||
|
ConfirmFollowToListModal,
|
||||||
} from './confirmation_modals';
|
} from './confirmation_modals';
|
||||||
import FocalPointModal from './focal_point_modal';
|
import FocalPointModal from './focal_point_modal';
|
||||||
import ImageModal from './image_modal';
|
import ImageModal from './image_modal';
|
||||||
@ -57,6 +58,7 @@ export const MODAL_COMPONENTS = {
|
|||||||
'CONFIRM_UNFOLLOW': () => Promise.resolve({ default: ConfirmUnfollowModal }),
|
'CONFIRM_UNFOLLOW': () => Promise.resolve({ default: ConfirmUnfollowModal }),
|
||||||
'CONFIRM_CLEAR_NOTIFICATIONS': () => Promise.resolve({ default: ConfirmClearNotificationsModal }),
|
'CONFIRM_CLEAR_NOTIFICATIONS': () => Promise.resolve({ default: ConfirmClearNotificationsModal }),
|
||||||
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
|
'CONFIRM_LOG_OUT': () => Promise.resolve({ default: ConfirmLogOutModal }),
|
||||||
|
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
||||||
'MUTE': MuteModal,
|
'MUTE': MuteModal,
|
||||||
'BLOCK': BlockModal,
|
'BLOCK': BlockModal,
|
||||||
'DOMAIN_BLOCK': DomainBlockModal,
|
'DOMAIN_BLOCK': DomainBlockModal,
|
||||||
|
@ -205,6 +205,9 @@
|
|||||||
"confirmations.edit.confirm": "Edit",
|
"confirmations.edit.confirm": "Edit",
|
||||||
"confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?",
|
"confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?",
|
||||||
"confirmations.edit.title": "Overwrite post?",
|
"confirmations.edit.title": "Overwrite post?",
|
||||||
|
"confirmations.follow_to_list.confirm": "Follow and add to list",
|
||||||
|
"confirmations.follow_to_list.message": "You need to be following {name} to add them to a list.",
|
||||||
|
"confirmations.follow_to_list.title": "Follow user?",
|
||||||
"confirmations.logout.confirm": "Log out",
|
"confirmations.logout.confirm": "Log out",
|
||||||
"confirmations.logout.message": "Are you sure you want to log out?",
|
"confirmations.logout.message": "Are you sure you want to log out?",
|
||||||
"confirmations.logout.title": "Log out?",
|
"confirmations.logout.title": "Log out?",
|
||||||
@ -492,7 +495,7 @@
|
|||||||
"lists.replies_policy.list": "Members of the list",
|
"lists.replies_policy.list": "Members of the list",
|
||||||
"lists.replies_policy.none": "No one",
|
"lists.replies_policy.none": "No one",
|
||||||
"lists.save": "Save",
|
"lists.save": "Save",
|
||||||
"lists.search_placeholder": "Search people you follow",
|
"lists.search": "Search",
|
||||||
"lists.show_replies_to": "Include replies from list members to",
|
"lists.show_replies_to": "Include replies from list members to",
|
||||||
"load_pending": "{count, plural, one {# new item} other {# new items}}",
|
"load_pending": "{count, plural, one {# new item} other {# new items}}",
|
||||||
"loading_indicator.label": "Loading…",
|
"loading_indicator.label": "Loading…",
|
||||||
|
Loading…
Reference in New Issue
Block a user