From 11a27f9504ba193cc14fd7c651ea2379ed71fbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Tue, 22 Oct 2024 15:28:57 +0200 Subject: [PATCH] pl-hooks: Fixes, new hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- packages/pl-fe/src/components/helmet.tsx | 2 +- .../event/components/event-header.tsx | 4 +- packages/pl-fe/src/utils/rtl.ts | 2 +- .../pl-hooks/lib/hooks/accounts/useAccount.ts | 2 +- .../lib/hooks/accounts/useAccountLookup.ts | 2 +- .../hooks/accounts/useAccountRelationship.ts | 2 +- .../lib/hooks/instance/useInstance.ts | 21 ++++++++++ .../hooks/instance/useTranslationLanguages.ts | 38 +++++++++++++++++++ .../pl-hooks/lib/hooks/markers/useMarkers.ts | 2 +- .../hooks/markers/useUpdateMarkerMutation.ts | 5 ++- .../hooks/notifications/useNotification.ts | 2 +- .../notifications/useNotificationList.ts | 12 ++++-- .../pl-hooks/lib/hooks/statuses/useStatus.ts | 23 ++++++----- packages/pl-hooks/lib/importer.ts | 33 ++++++++-------- packages/pl-hooks/lib/main.ts | 2 + 15 files changed, 112 insertions(+), 40 deletions(-) create mode 100644 packages/pl-hooks/lib/hooks/instance/useInstance.ts create mode 100644 packages/pl-hooks/lib/hooks/instance/useTranslationLanguages.ts diff --git a/packages/pl-fe/src/components/helmet.tsx b/packages/pl-fe/src/components/helmet.tsx index 7e5be97a5..644c37b29 100644 --- a/packages/pl-fe/src/components/helmet.tsx +++ b/packages/pl-fe/src/components/helmet.tsx @@ -11,7 +11,7 @@ import FaviconService from 'pl-fe/utils/favicon-service'; FaviconService.initFaviconService(); const getNotifTotals = (state: RootState): number => { - const notifications = state.notifications.unread || 0; + const notifications = state.notifications.unread; const reports = state.admin.openReports.count(); const approvals = state.admin.awaitingApproval.count(); return notifications + reports + approvals; diff --git a/packages/pl-fe/src/features/event/components/event-header.tsx b/packages/pl-fe/src/features/event/components/event-header.tsx index 07cdde057..07a87190a 100644 --- a/packages/pl-fe/src/features/event/components/event-header.tsx +++ b/packages/pl-fe/src/features/event/components/event-header.tsx @@ -433,8 +433,8 @@ const EventHeader: React.FC = ({ status }) => { id='event.participants' defaultMessage='{count} {rawCount, plural, one {person} other {people}} going' values={{ - rawCount: event.participants_count || 0, - count: shortNumberFormat(event.participants_count || 0), + rawCount: event.participants_count, + count: shortNumberFormat(event.participants_count), }} /> diff --git a/packages/pl-fe/src/utils/rtl.ts b/packages/pl-fe/src/utils/rtl.ts index 0a223a382..8ed46df37 100644 --- a/packages/pl-fe/src/utils/rtl.ts +++ b/packages/pl-fe/src/utils/rtl.ts @@ -51,7 +51,7 @@ interface GetTextDirectionOpts { } /** Get the direction of the text. */ -const getTextDirection = (text: string, { fallback = 'ltr', confidence }: GetTextDirectionOpts = {}): 'ltr' | 'rtl' => { +const getTextDirection = (text?: string, { fallback = 'ltr', confidence }: GetTextDirectionOpts = {}): 'ltr' | 'rtl' => { if (!text) return fallback; return isRtl(text, confidence) ? 'rtl' : 'ltr'; }; diff --git a/packages/pl-hooks/lib/hooks/accounts/useAccount.ts b/packages/pl-hooks/lib/hooks/accounts/useAccount.ts index 0616fe0c6..89d3944c4 100644 --- a/packages/pl-hooks/lib/hooks/accounts/useAccount.ts +++ b/packages/pl-hooks/lib/hooks/accounts/useAccount.ts @@ -16,8 +16,8 @@ interface UseAccountOpts { } const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => { - const queryClient = usePlHooksQueryClient(); const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); const accountQuery = useQuery({ queryKey: ['accounts', 'entities', accountId], diff --git a/packages/pl-hooks/lib/hooks/accounts/useAccountLookup.ts b/packages/pl-hooks/lib/hooks/accounts/useAccountLookup.ts index 719ce86e4..4db410267 100644 --- a/packages/pl-hooks/lib/hooks/accounts/useAccountLookup.ts +++ b/packages/pl-hooks/lib/hooks/accounts/useAccountLookup.ts @@ -7,8 +7,8 @@ import { importEntities } from 'pl-hooks/importer'; import { useAccount, type UseAccountOpts } from './useAccount'; const useAccountLookup = (acct?: string, opts: UseAccountOpts = {}) => { - const queryClient = usePlHooksQueryClient(); const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); const { features } = client; const accountIdQuery = useQuery({ diff --git a/packages/pl-hooks/lib/hooks/accounts/useAccountRelationship.ts b/packages/pl-hooks/lib/hooks/accounts/useAccountRelationship.ts index a61f3a762..4f99191f9 100644 --- a/packages/pl-hooks/lib/hooks/accounts/useAccountRelationship.ts +++ b/packages/pl-hooks/lib/hooks/accounts/useAccountRelationship.ts @@ -4,8 +4,8 @@ import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; const useAccountRelationship = (accountId?: string) => { - const queryClient = usePlHooksQueryClient(); const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); return useQuery({ queryKey: ['accounts', 'entities', accountId], diff --git a/packages/pl-hooks/lib/hooks/instance/useInstance.ts b/packages/pl-hooks/lib/hooks/instance/useInstance.ts new file mode 100644 index 000000000..b39752145 --- /dev/null +++ b/packages/pl-hooks/lib/hooks/instance/useInstance.ts @@ -0,0 +1,21 @@ +import { useQuery } from '@tanstack/react-query'; +import { instanceSchema } from 'pl-api'; +import * as v from 'valibot'; + +import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; +import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; + +const placeholderData = v.parse(instanceSchema, {}); + +const useInstance = () => { + const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); + + return useQuery({ + queryKey: ['instance'], + queryFn: client.instance.getInstance, + placeholderData, + }, queryClient); +}; + +export { useInstance }; diff --git a/packages/pl-hooks/lib/hooks/instance/useTranslationLanguages.ts b/packages/pl-hooks/lib/hooks/instance/useTranslationLanguages.ts new file mode 100644 index 000000000..cd1a713d2 --- /dev/null +++ b/packages/pl-hooks/lib/hooks/instance/useTranslationLanguages.ts @@ -0,0 +1,38 @@ +import { useQuery } from '@tanstack/react-query'; + +import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; +import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; + +import { useInstance } from './useInstance'; + +const useTranslationLanguages = () => { + const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); + const { data: instance } = useInstance(); + + const { + allow_unauthenticated: allowUnauthenticated, + } = instance!.pleroma.metadata.translation; + + const getTranslationLanguages = async () => { + const metadata = instance!.pleroma.metadata; + + if (metadata.translation.source_languages?.length) { + return Object.fromEntries(metadata.translation.source_languages.map(source => [ + source, + metadata.translation.target_languages!.filter(lang => lang !== source), + ])); + } + + return client.instance.getInstanceTranslationLanguages(); + }; + + return useQuery({ + queryKey: ['instance', 'translationLanguages'], + queryFn: getTranslationLanguages, + placeholderData: {}, + enabled: allowUnauthenticated && client.features.translations, + }, queryClient); +}; + +export { useTranslationLanguages }; diff --git a/packages/pl-hooks/lib/hooks/markers/useMarkers.ts b/packages/pl-hooks/lib/hooks/markers/useMarkers.ts index cdadad248..a6e8c90af 100644 --- a/packages/pl-hooks/lib/hooks/markers/useMarkers.ts +++ b/packages/pl-hooks/lib/hooks/markers/useMarkers.ts @@ -8,8 +8,8 @@ import type { PlApiClient } from 'pl-api'; type Timeline = 'home' | 'notifications'; const useMarker = (timeline: Timeline) => { - const queryClient = usePlHooksQueryClient(); const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); return useQuery({ queryKey: ['markers', timeline], diff --git a/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts b/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts index c19d2e9c5..96d9bdb99 100644 --- a/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts +++ b/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts @@ -1,13 +1,14 @@ import { useMutation } from '@tanstack/react-query'; import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; -import { queryClient } from 'pl-hooks/contexts/query-client'; +import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; import type { Timeline } from './useMarkers'; import type { Marker } from 'pl-api'; const useUpdateMarkerMutation = (timeline: Timeline) => { const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); return useMutation({ mutationFn: (lastReadId: string) => client.timelines.saveMarkers({ @@ -20,7 +21,7 @@ const useUpdateMarkerMutation = (timeline: Timeline) => { ...marker, last_read_id: lastReadId, }) : undefined), - }); + }, queryClient); }; export { useUpdateMarkerMutation }; diff --git a/packages/pl-hooks/lib/hooks/notifications/useNotification.ts b/packages/pl-hooks/lib/hooks/notifications/useNotification.ts index bbaf1749a..d03d0b961 100644 --- a/packages/pl-hooks/lib/hooks/notifications/useNotification.ts +++ b/packages/pl-hooks/lib/hooks/notifications/useNotification.ts @@ -25,8 +25,8 @@ const importNotification = (notification: NormalizedNotification) => { }; const useNotification = (notificationId: string) => { - const queryClient = usePlHooksQueryClient(); const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); const notificationQuery = useQuery({ queryKey: ['notifications', 'entities', notificationId], diff --git a/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts b/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts index cea3e2874..7d2d5ca8d 100644 --- a/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts +++ b/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts @@ -1,4 +1,4 @@ -import { useInfiniteQuery } from '@tanstack/react-query'; +import { InfiniteData, useInfiniteQuery, UseInfiniteQueryResult } from '@tanstack/react-query'; import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; @@ -33,9 +33,13 @@ const importNotifications = (response: PaginatedResponse) => { }; }; -const useNotificationList = (params: UseNotificationParams) => { - const queryClient = usePlHooksQueryClient(); +const useNotificationList = (params: UseNotificationParams): Omit Promise>) | null; + next: (() => Promise>) | null; +}, unknown>, Error>, 'data'> & { data: string[] } => { const { client } = usePlHooksApiClient(); + const queryClient = usePlHooksQueryClient(); const notificationsQuery = useInfiniteQuery({ queryKey: getQueryKey(params), @@ -47,7 +51,7 @@ const useNotificationList = (params: UseNotificationParams) => { getNextPageParam: (response) => response, }, queryClient); - const data = flattenPages(notificationsQuery.data) || []; + const data: string[] = flattenPages(notificationsQuery.data) || []; return { ...notificationsQuery, diff --git a/packages/pl-hooks/lib/hooks/statuses/useStatus.ts b/packages/pl-hooks/lib/hooks/statuses/useStatus.ts index f33de5f3f..a9483c345 100644 --- a/packages/pl-hooks/lib/hooks/statuses/useStatus.ts +++ b/packages/pl-hooks/lib/hooks/statuses/useStatus.ts @@ -1,13 +1,13 @@ -import { useQuery } from '@tanstack/react-query'; +import { useQueries, useQuery } from '@tanstack/react-query'; import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client'; import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client'; import { importEntities } from 'pl-hooks/importer'; +import { useAccount } from 'pl-hooks/main'; +import { type Account, normalizeAccount } from 'pl-hooks/normalizers/normalizeAccount'; import { normalizeStatus, type Status } from '../../normalizers/normalizeStatus'; -import type { Account } from 'pl-hooks/normalizers/normalizeAccount'; - // const toServerSideType = (columnType: string): Filter['context'][0] => { // switch (columnType) { // case 'home': @@ -101,11 +101,14 @@ const useStatus = (statusId?: string, opts: { language?: string } = {}) => { const status = statusQuery.data; - queryClient.getQueriesData({ queryKey: ['test', ['t']] }); - - const accountsQuery = queryClient.getQueriesData({ - queryKey: ['accounts', 'entities', status?.account_ids], - }); + const accountsQuery = useQueries({ + queries: status?.account_ids.map(accountId => ({ + queryKey: ['accounts', 'entities', accountId], + queryFn: () => client.accounts.getAccount(accountId!) + .then(account => (importEntities({ accounts: [account] }, { withParents: false }), account)) + .then(normalizeAccount), + })) || [], + }, queryClient); let data: (Status & { account: Account; @@ -115,8 +118,8 @@ const useStatus = (statusId?: string, opts: { language?: string } = {}) => { if (status) { data = { ...status, - account: accountsQuery[0][1]!, - accounts: accountsQuery.map(([_, account]) => account!).filter(Boolean), + account: accountsQuery[0].data!, + accounts: accountsQuery.map(({ data }) => data!).filter(Boolean), // quote, // reblog, // poll diff --git a/packages/pl-hooks/lib/importer.ts b/packages/pl-hooks/lib/importer.ts index 3e6224997..a203c98aa 100644 --- a/packages/pl-hooks/lib/importer.ts +++ b/packages/pl-hooks/lib/importer.ts @@ -11,9 +11,9 @@ import type { Status as BaseStatus, } from 'pl-api'; -const importAccount = (account: BaseAccount) => { - return queryClient.setQueryData(['accounts', 'entities', account.id], account); -}; +const importAccount = (account: BaseAccount) => queryClient.setQueryData( + ['accounts', 'entities', account.id], account, +); const importGroup = (group: BaseGroup) => queryClient.setQueryData( ['groups', 'entities', group.id], group, @@ -33,8 +33,7 @@ const importRelationship = (relationship: BaseRelationship) => queryClient.setQu ); const importStatus = (status: BaseStatus) => queryClient.setQueryData( - ['statuses', 'entities', status.id], - _ => normalizeStatus(status), + ['statuses', 'entities', status.id], normalizeStatus(status), ); const isEmpty = (object: Record) => !Object.values(object).some(value => value); @@ -56,23 +55,30 @@ const importEntities = (entities: { const relationships: Record = {}; const statuses: Record = {}; - const processAccount = (account: BaseAccount) => { + const processAccount = (account: BaseAccount, withSelf = true) => { + if (withSelf) accounts[account.id] = account; + queryClient.setQueryData(['accounts', 'byAcct', account.acct.toLocaleLowerCase()], account.id); if (account.moved) processAccount(account.moved); if (account.relationship) relationships[account.relationship.id] = account.relationship; }; - const processNotification = (notification: DeduplicatedNotification) => { + const processNotification = (notification: DeduplicatedNotification, withSelf = true) => { + if (withSelf) notifications[notification.id] = notification; + processAccount(notification.account); if (notification.type === 'move') processAccount(notification.target); - if (['mention', 'status', 'reblog', 'favourite', 'poll', 'update', 'emoji_reaction', 'event_reminder', 'participation_accepted', 'participation_request'].includes(notification.type)) + if (['mention', 'status', 'reblog', 'favourite', 'poll', 'update', 'emoji_reaction', 'event_reminder', 'participation_accepted', 'participation_request'].includes(notification.type)) { // @ts-ignore processStatus(notification.status); + } }; - const processStatus = (status: BaseStatus) => { + const processStatus = (status: BaseStatus, withSelf = true) => { + if (withSelf) statuses[status.id] = status; + if (status.account) { processAccount(status.account); } @@ -84,17 +90,14 @@ const importEntities = (entities: { }; if (options.withParents) { - entities.accounts?.forEach(account => accounts[account.id] = account); entities.groups?.forEach(group => groups[group.id] = group); - entities.notifications?.forEach(notification => notifications[notification.id] = notification); entities.polls?.forEach(poll => polls[poll.id] = poll); entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship); - entities.statuses?.forEach(status => statuses[status.id] = status); } - entities.accounts?.forEach((account) => processAccount(account)); - entities.notifications?.forEach((notification) => processNotification(notification)); - entities.statuses?.forEach((status) => processStatus(status)); + entities.accounts?.forEach((account) => processAccount(account, options.withParents)); + entities.notifications?.forEach((notification) => processNotification(notification, options.withParents)); + entities.statuses?.forEach((status) => processStatus(status, options.withParents)); if (!isEmpty(accounts)) Object.values(accounts).forEach(importAccount); if (!isEmpty(groups)) Object.values(groups).forEach(importGroup); diff --git a/packages/pl-hooks/lib/main.ts b/packages/pl-hooks/lib/main.ts index 9223d8d29..8ba82bc4f 100644 --- a/packages/pl-hooks/lib/main.ts +++ b/packages/pl-hooks/lib/main.ts @@ -4,6 +4,8 @@ export * from './contexts/query-client'; export * from './hooks/accounts/useAccount'; export * from './hooks/accounts/useAccountLookup'; export * from './hooks/accounts/useAccountRelationship'; +export * from './hooks/instance/useInstance'; +export * from './hooks/instance/useTranslationLanguages'; export * from './hooks/markers/useMarkers'; export * from './hooks/markers/useUpdateMarkerMutation'; export * from './hooks/notifications/useNotification';