pl-fe: Display block expiration date in blocks list

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-12-29 00:33:17 +01:00
parent 664c7e91a7
commit 11e3a5417d
6 changed files with 40 additions and 7 deletions

View File

@ -28,6 +28,7 @@ import {
asyncRefreshSchema,
authorizationServerMetadataSchema,
backupSchema,
blockedAccountSchema,
bookmarkFolderSchema,
chatMessageSchema,
chatSchema,
@ -2126,7 +2127,7 @@ class PlApiClient {
* @see {@link https://docs.joinmastodon.org/methods/blocks/#get}
*/
getBlocks: async (params?: GetBlocksParams) =>
this.#paginatedGet('/api/v1/blocks', { params }, accountSchema),
this.#paginatedGet('/api/v1/blocks', { params }, blockedAccountSchema),
/**
* Get domain blocks

View File

@ -265,6 +265,21 @@ type CredentialAccount = v.InferOutput<typeof untypedCredentialAccountSchema> &
*/
const credentialAccountSchema: v.BaseSchema<any, CredentialAccount, v.BaseIssue<unknown>> = untypedCredentialAccountSchema as any;
const untypedBlockedAccountSchema = v.pipe(v.any(), preprocessAccount, v.object({
...accountWithMovedAccountSchema.entries,
block_expires_at: v.fallback(v.nullable(datetimeSchema), null),
}));
/**
* @category Entity types
*/
type BlockedAccount = v.InferOutput<typeof untypedBlockedAccountSchema> & WithMoved;
/**
* @category Schemas
*/
const blockedAccountSchema: v.BaseSchema<any, BlockedAccount, v.BaseIssue<unknown>> = untypedBlockedAccountSchema as any;
const untypedMutedAccountSchema = v.pipe(v.any(), preprocessAccount, v.object({
...accountWithMovedAccountSchema.entries,
mute_expires_at: v.fallback(v.nullable(datetimeSchema), null),
@ -283,8 +298,10 @@ const mutedAccountSchema: v.BaseSchema<any, MutedAccount, v.BaseIssue<unknown>>
export {
accountSchema,
credentialAccountSchema,
blockedAccountSchema,
mutedAccountSchema,
type Account,
type CredentialAccount,
type BlockedAccount,
type MutedAccount,
};

View File

@ -110,6 +110,7 @@ interface IAccount {
items?: React.ReactNode;
disabled?: boolean;
muteExpiresAt?: string | null;
blockExpiresAt?: string | null;
}
const Account = ({
@ -138,6 +139,7 @@ const Account = ({
items,
disabled,
muteExpiresAt,
blockExpiresAt,
}: IAccount) => {
const overflowRef = useRef<HTMLDivElement>(null);
const actionRef = useRef<HTMLDivElement>(null);
@ -376,6 +378,14 @@ const Account = ({
</>
)}
{actionType === 'blocking' && blockExpiresAt ? (
<>
<span className='⁂-separator' />
<Text theme='muted' size='sm'><RelativeTimestamp timestamp={blockExpiresAt} futureDate /></Text>
</>
) : null}
{actionType === 'muting' && muteExpiresAt ? (
<>
<span className='⁂-separator' />

View File

@ -43,8 +43,8 @@ const BlocksPage: React.FC = () => {
itemClassName={clsx('pb-4', { 'last:pb-0': !hasNextPage })}
isLoading={isFetching}
>
{data.map((accountId) => (
<AccountContainer key={accountId} id={accountId} actionType='blocking' />
{data.map(([accountId, blockExpiresAt]) => (
<AccountContainer key={accountId} id={accountId} actionType='blocking' blockExpiresAt={blockExpiresAt} />
))}
</ScrollableList>
</Column>

View File

@ -1,9 +1,9 @@
import { makePaginatedResponseQuery } from '../utils/make-paginated-response-query';
import { minifyAccountList, minifyMutedAccountList } from '../utils/minify-list';
import { minifyBlockedAccountList, minifyMutedAccountList } from '../utils/minify-list';
const useBlocks = makePaginatedResponseQuery(
['accountsLists', 'blocked'],
(client) => client.filtering.getBlocks({ with_relationships: true }).then(minifyAccountList),
(client) => client.filtering.getBlocks({ with_relationships: true }).then(minifyBlockedAccountList),
);
const useMutes = makePaginatedResponseQuery(

View File

@ -3,7 +3,7 @@ import { store } from 'pl-fe/store';
import { queryClient } from '../client';
import type { Account, AdminAccount, AdminReport, MutedAccount, PaginatedResponse, Status } from 'pl-api';
import type { Account, AdminAccount, AdminReport, BlockedAccount, MutedAccount, PaginatedResponse, Status } from 'pl-api';
const minifyList = <T1, T2>({ previous, next, items, ...response }: PaginatedResponse<T1>, minifier: (value: T1) => T2, importer?: (items: Array<T1>) => void): PaginatedResponse<T2> => {
importer?.(items);
@ -26,6 +26,11 @@ const minifyAccountList = (response: PaginatedResponse<Account>): PaginatedRespo
store.dispatch(importEntities({ accounts }) as any);
});
const minifyBlockedAccountList = (response: PaginatedResponse<BlockedAccount>): PaginatedResponse<[string, string | null]> =>
minifyList(response, (account) => [account.id, account.block_expires_at], (accounts) => {
store.dispatch(importEntities({ accounts }) as any);
});
const minifyMutedAccountList = (response: PaginatedResponse<MutedAccount>): PaginatedResponse<[string, string | null]> =>
minifyList(response, (account) => [account.id, account.mute_expires_at], (accounts) => {
store.dispatch(importEntities({ accounts }) as any);
@ -75,4 +80,4 @@ const minifyAdminReportList = (response: PaginatedResponse<AdminReport>) =>
}
});
export { minifyList, minifyAccountList, minifyMutedAccountList, minifyStatusList, minifyAdminAccount, minifyAdminAccountList, minifyAdminReport, minifyAdminReportList };
export { minifyList, minifyAccountList, minifyBlockedAccountList, minifyMutedAccountList, minifyStatusList, minifyAdminAccount, minifyAdminAccountList, minifyAdminReport, minifyAdminReportList };