[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:
diondiondion 2026-04-28 18:31:18 +02:00 committed by Claire
parent 57ed939d00
commit 1e7c8912d6
3 changed files with 52 additions and 16 deletions

View File

@ -87,7 +87,7 @@
}
.variantSubtle {
border: 1px solid var(--color-bg-brand-softest);
border: 1px solid var(--color-border-brand-soft);
background-color: var(--color-bg-primary);
.icon {

View File

@ -2,8 +2,12 @@ import { useCallback, useMemo, useRef, useState } from 'react';
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 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 {
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, collectionId?: string) =>
state.collections.collections[collectionId ?? '']?.items,
],
(accounts, collectionAccountItems) =>
(collectionAccountItems ?? []).map(({ account_id }) =>
account_id ? accounts.get(account_id) : null,
(collectionAccountItems ?? []).map(
(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 collectionAccounts = useAppSelector((state) =>
getCollectionAccounts(state, id),
getCollectionItems(state, id),
);
const { visibleAccounts, hiddenAccounts } = useMemo(() => {
const visibleAccounts: Account[] = [];
const hiddenAccounts: Account[] = [];
const visibleAccounts: CollectionItemWithAccount[] = [];
const hiddenAccounts: CollectionItemWithAccount[] = [];
collectionAccounts.forEach((item) => {
if (!item) {
// We currently simply hide unavailable accounts, this includes
// accounts that are pending inclusion; at least for the collection
// owner we should display an indication of pending users
const { account, account_id } = item;
if (!isOwnCollection && !account) {
// Hide unavailable accounts unless you own this collection
return;
}
const relationship = relationships.get(item.id);
const relationship = account_id ? relationships.get(account_id) : null;
if (relationship?.blocking || relationship?.muting) {
hiddenAccounts.push(item);
} else {
@ -124,7 +135,7 @@ export const CollectionAccountsList: React.FC<{
});
return { visibleAccounts, hiddenAccounts };
}, [collectionAccounts, relationships]);
}, [collectionAccounts, isOwnCollection, relationships]);
const renderAccountItemButton = useCallback(
({ relationship, accountId }: RenderButtonOptions) => {
@ -159,15 +170,16 @@ export const CollectionAccountsList: React.FC<{
index,
totalListLength,
isLastElement,
}: TruncatedListItemInfo<Account>) => (
}: TruncatedListItemInfo<CollectionItemWithAccount>) => (
<Article
key={item.id}
aria-posinset={index + 1}
aria-setsize={totalListLength}
>
<AccountListItem
accountId={item.id}
accountId={item.account_id}
withBorder={!isLastElement}
badge={item.state === 'pending' ? <PendingBadge /> : null}
renderButton={renderAccountItemButton}
/>
</Article>

View File

@ -8,6 +8,7 @@ import { Link } from 'react-router-dom';
import { openModal } from '@/flavours/glitch/actions/modal';
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 ShareIcon from '@/material-icons/400-24px/share.svg?react';
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 were awaiting a response from the user or their server. Only you can see pending accounts.'
/>
</Callout>
);
};
const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
collection,
}) => {
@ -136,6 +157,8 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
}
}, [history, openShareModal, isNewCollection, location.pathname]);
const hasPendingAccounts = items.some((item) => item.state === 'pending');
return (
<header className={classes.header}>
<div className={classes.titleWithMenu}>
@ -160,6 +183,7 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
</div>
</div>
{description && <p className={classes.description}>{description}</p>}
{hasPendingAccounts && <PendingNote />}
{isCurrentUserInCollection && <RevokeControls collection={collection} />}
</header>
);