[Glitch] Mark pending accounts on the collection detail page
Port b193913f462702981d20d4a58249a1bceaf3b974 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
57ed939d00
commit
1e7c8912d6
@ -87,7 +87,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.variantSubtle {
|
.variantSubtle {
|
||||||
border: 1px solid var(--color-bg-brand-softest);
|
border: 1px solid var(--color-border-brand-soft);
|
||||||
background-color: var(--color-bg-primary);
|
background-color: var(--color-bg-primary);
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
|
|||||||
@ -2,8 +2,12 @@ import { useCallback, useMemo, useRef, useState } from 'react';
|
|||||||
|
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { PendingBadge } from '@/flavours/glitch/components/badge';
|
||||||
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
|
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
|
||||||
import type { ApiCollectionJSON } from 'flavours/glitch/api_types/collections';
|
import type {
|
||||||
|
ApiCollectionJSON,
|
||||||
|
CollectionAccountItem,
|
||||||
|
} from 'flavours/glitch/api_types/collections';
|
||||||
import type { RenderButtonOptions } from 'flavours/glitch/components/account_list_item';
|
import type { RenderButtonOptions } from 'flavours/glitch/components/account_list_item';
|
||||||
import {
|
import {
|
||||||
AccountListItem,
|
AccountListItem,
|
||||||
@ -75,15 +79,22 @@ const SensitiveScreen: React.FC<{
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCollectionAccounts = createAppSelector(
|
type CollectionItemWithAccount = CollectionAccountItem & {
|
||||||
|
account?: Account | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCollectionItems = createAppSelector(
|
||||||
[
|
[
|
||||||
(state) => state.accounts,
|
(state) => state.accounts,
|
||||||
(state, collectionId?: string) =>
|
(state, collectionId?: string) =>
|
||||||
state.collections.collections[collectionId ?? '']?.items,
|
state.collections.collections[collectionId ?? '']?.items,
|
||||||
],
|
],
|
||||||
(accounts, collectionAccountItems) =>
|
(accounts, collectionAccountItems) =>
|
||||||
(collectionAccountItems ?? []).map(({ account_id }) =>
|
(collectionAccountItems ?? []).map(
|
||||||
account_id ? accounts.get(account_id) : null,
|
(item): CollectionItemWithAccount => ({
|
||||||
|
...item,
|
||||||
|
account: item.account_id ? accounts.get(item.account_id) : null,
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -100,22 +111,22 @@ export const CollectionAccountsList: React.FC<{
|
|||||||
|
|
||||||
const relationships = useAppSelector((state) => state.relationships);
|
const relationships = useAppSelector((state) => state.relationships);
|
||||||
const collectionAccounts = useAppSelector((state) =>
|
const collectionAccounts = useAppSelector((state) =>
|
||||||
getCollectionAccounts(state, id),
|
getCollectionItems(state, id),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { visibleAccounts, hiddenAccounts } = useMemo(() => {
|
const { visibleAccounts, hiddenAccounts } = useMemo(() => {
|
||||||
const visibleAccounts: Account[] = [];
|
const visibleAccounts: CollectionItemWithAccount[] = [];
|
||||||
const hiddenAccounts: Account[] = [];
|
const hiddenAccounts: CollectionItemWithAccount[] = [];
|
||||||
|
|
||||||
collectionAccounts.forEach((item) => {
|
collectionAccounts.forEach((item) => {
|
||||||
if (!item) {
|
const { account, account_id } = item;
|
||||||
// We currently simply hide unavailable accounts, this includes
|
|
||||||
// accounts that are pending inclusion; at least for the collection
|
if (!isOwnCollection && !account) {
|
||||||
// owner we should display an indication of pending users
|
// Hide unavailable accounts unless you own this collection
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relationship = relationships.get(item.id);
|
const relationship = account_id ? relationships.get(account_id) : null;
|
||||||
if (relationship?.blocking || relationship?.muting) {
|
if (relationship?.blocking || relationship?.muting) {
|
||||||
hiddenAccounts.push(item);
|
hiddenAccounts.push(item);
|
||||||
} else {
|
} else {
|
||||||
@ -124,7 +135,7 @@ export const CollectionAccountsList: React.FC<{
|
|||||||
});
|
});
|
||||||
|
|
||||||
return { visibleAccounts, hiddenAccounts };
|
return { visibleAccounts, hiddenAccounts };
|
||||||
}, [collectionAccounts, relationships]);
|
}, [collectionAccounts, isOwnCollection, relationships]);
|
||||||
|
|
||||||
const renderAccountItemButton = useCallback(
|
const renderAccountItemButton = useCallback(
|
||||||
({ relationship, accountId }: RenderButtonOptions) => {
|
({ relationship, accountId }: RenderButtonOptions) => {
|
||||||
@ -159,15 +170,16 @@ export const CollectionAccountsList: React.FC<{
|
|||||||
index,
|
index,
|
||||||
totalListLength,
|
totalListLength,
|
||||||
isLastElement,
|
isLastElement,
|
||||||
}: TruncatedListItemInfo<Account>) => (
|
}: TruncatedListItemInfo<CollectionItemWithAccount>) => (
|
||||||
<Article
|
<Article
|
||||||
key={item.id}
|
key={item.id}
|
||||||
aria-posinset={index + 1}
|
aria-posinset={index + 1}
|
||||||
aria-setsize={totalListLength}
|
aria-setsize={totalListLength}
|
||||||
>
|
>
|
||||||
<AccountListItem
|
<AccountListItem
|
||||||
accountId={item.id}
|
accountId={item.account_id}
|
||||||
withBorder={!isLastElement}
|
withBorder={!isLastElement}
|
||||||
|
badge={item.state === 'pending' ? <PendingBadge /> : null}
|
||||||
renderButton={renderAccountItemButton}
|
renderButton={renderAccountItemButton}
|
||||||
/>
|
/>
|
||||||
</Article>
|
</Article>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import { openModal } from '@/flavours/glitch/actions/modal';
|
import { openModal } from '@/flavours/glitch/actions/modal';
|
||||||
import { useAccountHandle } from '@/flavours/glitch/components/display_name/default';
|
import { useAccountHandle } from '@/flavours/glitch/components/display_name/default';
|
||||||
|
import HelpIcon from '@/material-icons/400-24px/help.svg?react';
|
||||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
||||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||||
import type { ApiCollectionJSON } from 'flavours/glitch/api_types/collections';
|
import type { ApiCollectionJSON } from 'flavours/glitch/api_types/collections';
|
||||||
@ -101,6 +102,26 @@ const RevokeControls: React.FC<{
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PendingNote: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<Callout
|
||||||
|
variant='subtle'
|
||||||
|
icon={HelpIcon}
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.pending_accounts.title'
|
||||||
|
defaultMessage='Why am I seeing pending accounts?'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.pending_accounts.message'
|
||||||
|
defaultMessage='Accounts may appear as pending when we’re awaiting a response from the user or their server. Only you can see pending accounts.'
|
||||||
|
/>
|
||||||
|
</Callout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
||||||
collection,
|
collection,
|
||||||
}) => {
|
}) => {
|
||||||
@ -136,6 +157,8 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
|||||||
}
|
}
|
||||||
}, [history, openShareModal, isNewCollection, location.pathname]);
|
}, [history, openShareModal, isNewCollection, location.pathname]);
|
||||||
|
|
||||||
|
const hasPendingAccounts = items.some((item) => item.state === 'pending');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className={classes.header}>
|
<header className={classes.header}>
|
||||||
<div className={classes.titleWithMenu}>
|
<div className={classes.titleWithMenu}>
|
||||||
@ -160,6 +183,7 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{description && <p className={classes.description}>{description}</p>}
|
{description && <p className={classes.description}>{description}</p>}
|
||||||
|
{hasPendingAccounts && <PendingNote />}
|
||||||
{isCurrentUserInCollection && <RevokeControls collection={collection} />}
|
{isCurrentUserInCollection && <RevokeControls collection={collection} />}
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user