Compare commits
1 Commits
master
...
fix-unfoll
Author | SHA1 | Date |
---|---|---|
unknown | 9fcc4233eb |
|
@ -4,10 +4,10 @@ import { useDispatch } from 'react-redux';
|
|||
|
||||
import { unblockDomain } from 'soapbox/actions/domain_blocks';
|
||||
|
||||
import IconButton from './icon_button';
|
||||
import Icon from './icon';
|
||||
import { Button } from './ui';
|
||||
|
||||
const messages = defineMessages({
|
||||
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
||||
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
|
||||
});
|
||||
|
||||
|
@ -19,29 +19,27 @@ const Domain: React.FC<IDomain> = ({ domain }) => {
|
|||
const dispatch = useDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
// const onBlockDomain = () => {
|
||||
// dispatch(openModal('CONFIRM', {
|
||||
// icon: require('@tabler/icons/ban.svg'),
|
||||
// heading: <FormattedMessage id='confirmations.domain_block.heading' defaultMessage='Block {domain}' values={{ domain }} />,
|
||||
// message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />,
|
||||
// confirm: intl.formatMessage(messages.blockDomainConfirm),
|
||||
// onConfirm: () => dispatch(blockDomain(domain)),
|
||||
// }));
|
||||
// }
|
||||
|
||||
const handleDomainUnblock = () => {
|
||||
dispatch(unblockDomain(domain));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='domain'>
|
||||
<div className='domain__wrapper'>
|
||||
<span className='domain__domain-name'>
|
||||
<strong>{domain}</strong>
|
||||
</span>
|
||||
<div className='domain__wrapper flex justify-between items-center'>
|
||||
<div className='flex gap-1 items-center'>
|
||||
<Icon src={require('@tabler/icons/world.svg')} />
|
||||
<strong className='text-gray-700 dark:text-white'>{domain}</strong>
|
||||
</div>
|
||||
|
||||
<div className='domain__buttons'>
|
||||
<IconButton active src={require('@tabler/icons/lock-open.svg')} title={intl.formatMessage(messages.unblockDomain, { domain })} onClick={handleDomainUnblock} />
|
||||
<Button theme='ghost' onClick={handleDomainUnblock}>
|
||||
<div className='flex gap-1 items-center'>
|
||||
<Icon src={require('@tabler/icons/lock-open.svg')} />
|
||||
<span>
|
||||
{ intl.formatMessage(messages.unblockDomain) }
|
||||
</span>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,19 +23,12 @@ const Blocks: React.FC = () => {
|
|||
|
||||
const accountIds = useAppSelector((state) => state.user_lists.blocks.items);
|
||||
const hasMore = useAppSelector((state) => !!state.user_lists.blocks.next);
|
||||
const loading = useAppSelector((state) => state.user_lists.blocks.isLoading);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchBlocks());
|
||||
}, []);
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
<Column>
|
||||
<Spinner />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />;
|
||||
|
||||
return (
|
||||
|
@ -45,12 +38,16 @@ const Blocks: React.FC = () => {
|
|||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
hasMore={hasMore}
|
||||
emptyMessage={emptyMessage}
|
||||
itemClassName='pb-4'
|
||||
itemClassName='flex flex-col gap-3 pb-4'
|
||||
>
|
||||
{accountIds.map((id) =>
|
||||
<AccountContainer key={id} id={id} actionType='blocking' />,
|
||||
)}
|
||||
{
|
||||
loading && <Spinner />
|
||||
}
|
||||
</ScrollableList>
|
||||
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,19 +26,13 @@ const DomainBlocks: React.FC = () => {
|
|||
|
||||
const domains = useAppSelector((state) => state.domain_lists.blocks.items);
|
||||
const hasMore = useAppSelector((state) => !!state.domain_lists.blocks.next);
|
||||
const loading = useAppSelector((state) => state.domain_lists.blocks.isLoading);
|
||||
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchDomainBlocks());
|
||||
}, []);
|
||||
|
||||
if (!domains) {
|
||||
return (
|
||||
<Column>
|
||||
<Spinner />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.domain_blocks' defaultMessage='There are no hidden domains yet.' />;
|
||||
|
||||
return (
|
||||
|
@ -48,10 +42,16 @@ const DomainBlocks: React.FC = () => {
|
|||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
hasMore={hasMore}
|
||||
emptyMessage={emptyMessage}
|
||||
itemClassName='flex flex-col gap-3'
|
||||
>
|
||||
{domains.map((domain) =>
|
||||
<Domain key={domain} domain={domain} />,
|
||||
)}
|
||||
{domains.map((domain) => (
|
||||
<div className='rounded p-1 bg-gray-100 dark:bg-slate-900'>
|
||||
<Domain key={domain} domain={domain} />
|
||||
</div>
|
||||
))}
|
||||
{
|
||||
loading && <Spinner />
|
||||
}
|
||||
</ScrollableList>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -26,24 +26,18 @@ const FollowRequests: React.FC = () => {
|
|||
|
||||
const accountIds = useAppSelector((state) => state.user_lists.follow_requests.items);
|
||||
const hasMore = useAppSelector((state) => !!state.user_lists.follow_requests.next);
|
||||
const loading = useAppSelector((state) => state.user_lists.mutes.isLoading);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchFollowRequests());
|
||||
}, []);
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
<Column>
|
||||
<Spinner />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.follow_requests' defaultMessage="You don't have any follow requests yet. When you receive one, it will show up here." />;
|
||||
|
||||
return (
|
||||
<Column icon='user-plus' label={intl.formatMessage(messages.heading)}>
|
||||
<ScrollableList
|
||||
className='flex flex-col gap-3'
|
||||
scrollKey='follow_requests'
|
||||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
hasMore={hasMore}
|
||||
|
@ -52,6 +46,9 @@ const FollowRequests: React.FC = () => {
|
|||
{accountIds.map(id =>
|
||||
<AccountAuthorize key={id} id={id} />,
|
||||
)}
|
||||
{
|
||||
loading && <Spinner />
|
||||
}
|
||||
</ScrollableList>
|
||||
</Column>
|
||||
);
|
||||
|
|
|
@ -23,19 +23,13 @@ const Mutes: React.FC = () => {
|
|||
|
||||
const accountIds = useAppSelector((state) => state.user_lists.mutes.items);
|
||||
const hasMore = useAppSelector((state) => !!state.user_lists.mutes.next);
|
||||
const loading = useAppSelector((state) => state.user_lists.mutes.isLoading);
|
||||
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchMutes());
|
||||
}, []);
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
<Column>
|
||||
<Spinner />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />;
|
||||
|
||||
return (
|
||||
|
@ -45,12 +39,16 @@ const Mutes: React.FC = () => {
|
|||
onLoadMore={() => handleLoadMore(dispatch)}
|
||||
hasMore={hasMore}
|
||||
emptyMessage={emptyMessage}
|
||||
itemClassName='pb-4'
|
||||
itemClassName='flex flex-col gap-3 pb-4'
|
||||
>
|
||||
{accountIds.map((id) =>
|
||||
<AccountContainer key={id} id={id} actionType='muting' />,
|
||||
)}
|
||||
{
|
||||
loading && <Spinner />
|
||||
}
|
||||
</ScrollableList>
|
||||
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"account.badges.bot": "Robot",
|
||||
"account.birthday": "Born {date}",
|
||||
"account.birthday_today": "Birthday is today!",
|
||||
"account.block": "Bloquer @{name}",
|
||||
"account.block": "Bloquer",
|
||||
"account.block_domain": "Tout masquer venant de {domain}",
|
||||
"account.blocked": "Bloqué",
|
||||
"account.chat": "Chat with @{name}",
|
||||
|
@ -36,7 +36,7 @@
|
|||
"account.member_since": "Joined {date}",
|
||||
"account.mention": "Mentionner",
|
||||
"account.moved_to": "{name} a déménagé vers :",
|
||||
"account.mute": "Masquer @{name}",
|
||||
"account.mute": "Masquer",
|
||||
"account.muted": "Muted",
|
||||
"account.never_active": "Jamais",
|
||||
"account.no_fields": "Cette section est vide pour le moment.",
|
||||
|
@ -57,12 +57,12 @@
|
|||
"account.subscribe.failure": "An error occurred trying to subscribed to this account.",
|
||||
"account.subscribe.success": "You have subscribed to this account.",
|
||||
"account.today": "Aujourd'hui",
|
||||
"account.unblock": "Débloquer @{name}",
|
||||
"account.unblock_domain": "Ne plus masquer {domain}",
|
||||
"account.unblock": "Débloquer",
|
||||
"account.unblock_domain": "Ne plus masquer",
|
||||
"account.unendorse": "Ne plus recommander sur le profil",
|
||||
"account.unendorse.success": "You are no longer featuring @{acct}",
|
||||
"account.unfollow": "Ne plus suivre",
|
||||
"account.unmute": "Ne plus masquer @{name}",
|
||||
"account.unmute": "Ne plus masquer",
|
||||
"account.unsubscribe": "Unsubscribe to notifications from @{name}",
|
||||
"account.unsubscribe.failure": "An error occurred trying to unsubscribed to this account.",
|
||||
"account.unsubscribe.success": "You have unsubscribed from this account.",
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
DOMAIN_BLOCKS_FETCH_SUCCESS,
|
||||
DOMAIN_BLOCKS_EXPAND_SUCCESS,
|
||||
DOMAIN_UNBLOCK_SUCCESS,
|
||||
DOMAIN_BLOCKS_FETCH_REQUEST,
|
||||
} from '../actions/domain_blocks';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
|
@ -11,6 +12,7 @@ import type { AnyAction } from 'redux';
|
|||
const BlocksRecord = ImmutableRecord({
|
||||
items: ImmutableOrderedSet<string>(),
|
||||
next: null as string | null,
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
const ReducerRecord = ImmutableRecord({
|
||||
|
@ -21,8 +23,12 @@ type State = ReturnType<typeof ReducerRecord>;
|
|||
|
||||
export default function domainLists(state: State = ReducerRecord(), action: AnyAction) {
|
||||
switch (action.type) {
|
||||
case DOMAIN_BLOCKS_FETCH_REQUEST:
|
||||
return state.setIn(['blocks', 'isLoading'], true);
|
||||
case DOMAIN_BLOCKS_FETCH_SUCCESS:
|
||||
return state.setIn(['blocks', 'items'], ImmutableOrderedSet(action.domains)).setIn(['blocks', 'next'], action.next);
|
||||
return state
|
||||
.setIn(['blocks', 'isLoading'], false)
|
||||
.setIn(['blocks', 'items'], ImmutableOrderedSet(action.domains)).setIn(['blocks', 'next'], action.next);
|
||||
case DOMAIN_BLOCKS_EXPAND_SUCCESS:
|
||||
return state.updateIn(['blocks', 'items'], set => (set as ImmutableOrderedSet<string>).union(action.domains)).setIn(['blocks', 'next'], action.next);
|
||||
case DOMAIN_UNBLOCK_SUCCESS:
|
||||
|
|
|
@ -16,10 +16,12 @@ import {
|
|||
FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||
PINNED_ACCOUNTS_FETCH_SUCCESS,
|
||||
BIRTHDAY_REMINDERS_FETCH_SUCCESS,
|
||||
FOLLOW_REQUESTS_FETCH_REQUEST,
|
||||
} from '../actions/accounts';
|
||||
import {
|
||||
BLOCKS_FETCH_SUCCESS,
|
||||
BLOCKS_EXPAND_SUCCESS,
|
||||
BLOCKS_FETCH_REQUEST,
|
||||
} from '../actions/blocks';
|
||||
import {
|
||||
DIRECTORY_FETCH_REQUEST,
|
||||
|
@ -47,6 +49,7 @@ import {
|
|||
import {
|
||||
MUTES_FETCH_SUCCESS,
|
||||
MUTES_EXPAND_SUCCESS,
|
||||
MUTES_FETCH_REQUEST,
|
||||
} from '../actions/mutes';
|
||||
import {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
|
@ -98,9 +101,15 @@ type Items = ImmutableOrderedSet<string>;
|
|||
type NestedListPath = ['followers' | 'following' | 'reblogged_by' | 'favourited_by' | 'reactions' | 'groups' | 'groups_removed_accounts' | 'pinned' | 'birthday_reminders' | 'familiar_followers', string];
|
||||
type ListPath = ['follow_requests' | 'blocks' | 'mutes' | 'directory'];
|
||||
|
||||
const loadingList = (state: State, path: ListPath) => {
|
||||
const current = state.getIn(path) as List;
|
||||
return state.setIn(path, current.set('isLoading', true));
|
||||
};
|
||||
|
||||
const normalizeList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next?: string | null) => {
|
||||
|
||||
return state.setIn(path, ListRecord({
|
||||
isLoading: false,
|
||||
next,
|
||||
items: ImmutableOrderedSet(accounts.map(item => item.id)),
|
||||
}));
|
||||
|
@ -108,13 +117,15 @@ const normalizeList = (state: State, path: NestedListPath | ListPath, accounts:
|
|||
|
||||
const appendToList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next: string | null) => {
|
||||
return state.updateIn(path, map => {
|
||||
return (map as List).set('next', next).update('items', list => (list as Items).concat(accounts.map(item => item.id)));
|
||||
return (map as List)
|
||||
.set('next', next).update('items', list => (list as Items).concat(accounts.map(item => item.id)));
|
||||
});
|
||||
};
|
||||
|
||||
const removeFromList = (state: State, path: NestedListPath | ListPath, accountId: string) => {
|
||||
return state.updateIn(path, map => {
|
||||
return (map as List).update('items', list => (list as Items).filterNot(item => item === accountId));
|
||||
return (map as List)
|
||||
.update('items', list => (list as Items).filterNot(item => item === accountId));
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -126,6 +137,12 @@ const normalizeFollowRequest = (state: State, notification: APIEntity) => {
|
|||
|
||||
export default function userLists(state = ReducerRecord(), action: AnyAction) {
|
||||
switch (action.type) {
|
||||
case BLOCKS_FETCH_REQUEST:
|
||||
return loadingList(state, ['blocks']);
|
||||
case MUTES_FETCH_REQUEST:
|
||||
return loadingList(state, ['mutes']);
|
||||
case FOLLOW_REQUESTS_FETCH_REQUEST:
|
||||
return loadingList(state, ['follow_requests']);
|
||||
case FOLLOWERS_FETCH_SUCCESS:
|
||||
return normalizeList(state, ['followers', action.id], action.accounts, action.next);
|
||||
case FOLLOWERS_EXPAND_SUCCESS:
|
||||
|
|
Loading…
Reference in New Issue