pl-hooks: Fixes, new hooks
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
e583d15d0d
commit
11a27f9504
15 changed files with 112 additions and 40 deletions
|
@ -11,7 +11,7 @@ import FaviconService from 'pl-fe/utils/favicon-service';
|
||||||
FaviconService.initFaviconService();
|
FaviconService.initFaviconService();
|
||||||
|
|
||||||
const getNotifTotals = (state: RootState): number => {
|
const getNotifTotals = (state: RootState): number => {
|
||||||
const notifications = state.notifications.unread || 0;
|
const notifications = state.notifications.unread;
|
||||||
const reports = state.admin.openReports.count();
|
const reports = state.admin.openReports.count();
|
||||||
const approvals = state.admin.awaitingApproval.count();
|
const approvals = state.admin.awaitingApproval.count();
|
||||||
return notifications + reports + approvals;
|
return notifications + reports + approvals;
|
||||||
|
|
|
@ -433,8 +433,8 @@ const EventHeader: React.FC<IEventHeader> = ({ status }) => {
|
||||||
id='event.participants'
|
id='event.participants'
|
||||||
defaultMessage='{count} {rawCount, plural, one {person} other {people}} going'
|
defaultMessage='{count} {rawCount, plural, one {person} other {people}} going'
|
||||||
values={{
|
values={{
|
||||||
rawCount: event.participants_count || 0,
|
rawCount: event.participants_count,
|
||||||
count: shortNumberFormat(event.participants_count || 0),
|
count: shortNumberFormat(event.participants_count),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -51,7 +51,7 @@ interface GetTextDirectionOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the direction of the text. */
|
/** 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;
|
if (!text) return fallback;
|
||||||
return isRtl(text, confidence) ? 'rtl' : 'ltr';
|
return isRtl(text, confidence) ? 'rtl' : 'ltr';
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,8 +16,8 @@ interface UseAccountOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => {
|
const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => {
|
||||||
const queryClient = usePlHooksQueryClient();
|
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
const accountQuery = useQuery({
|
const accountQuery = useQuery({
|
||||||
queryKey: ['accounts', 'entities', accountId],
|
queryKey: ['accounts', 'entities', accountId],
|
||||||
|
|
|
@ -7,8 +7,8 @@ import { importEntities } from 'pl-hooks/importer';
|
||||||
import { useAccount, type UseAccountOpts } from './useAccount';
|
import { useAccount, type UseAccountOpts } from './useAccount';
|
||||||
|
|
||||||
const useAccountLookup = (acct?: string, opts: UseAccountOpts = {}) => {
|
const useAccountLookup = (acct?: string, opts: UseAccountOpts = {}) => {
|
||||||
const queryClient = usePlHooksQueryClient();
|
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
const { features } = client;
|
const { features } = client;
|
||||||
|
|
||||||
const accountIdQuery = useQuery({
|
const accountIdQuery = useQuery({
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client';
|
||||||
import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
import { usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
||||||
|
|
||||||
const useAccountRelationship = (accountId?: string) => {
|
const useAccountRelationship = (accountId?: string) => {
|
||||||
const queryClient = usePlHooksQueryClient();
|
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['accounts', 'entities', accountId],
|
queryKey: ['accounts', 'entities', accountId],
|
||||||
|
|
21
packages/pl-hooks/lib/hooks/instance/useInstance.ts
Normal file
21
packages/pl-hooks/lib/hooks/instance/useInstance.ts
Normal file
|
@ -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 };
|
|
@ -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 };
|
|
@ -8,8 +8,8 @@ import type { PlApiClient } from 'pl-api';
|
||||||
type Timeline = 'home' | 'notifications';
|
type Timeline = 'home' | 'notifications';
|
||||||
|
|
||||||
const useMarker = (timeline: Timeline) => {
|
const useMarker = (timeline: Timeline) => {
|
||||||
const queryClient = usePlHooksQueryClient();
|
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['markers', timeline],
|
queryKey: ['markers', timeline],
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { usePlHooksApiClient } from 'pl-hooks/contexts/api-client';
|
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 { Timeline } from './useMarkers';
|
||||||
import type { Marker } from 'pl-api';
|
import type { Marker } from 'pl-api';
|
||||||
|
|
||||||
const useUpdateMarkerMutation = (timeline: Timeline) => {
|
const useUpdateMarkerMutation = (timeline: Timeline) => {
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (lastReadId: string) => client.timelines.saveMarkers({
|
mutationFn: (lastReadId: string) => client.timelines.saveMarkers({
|
||||||
|
@ -20,7 +21,7 @@ const useUpdateMarkerMutation = (timeline: Timeline) => {
|
||||||
...marker,
|
...marker,
|
||||||
last_read_id: lastReadId,
|
last_read_id: lastReadId,
|
||||||
}) : undefined),
|
}) : undefined),
|
||||||
});
|
}, queryClient);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { useUpdateMarkerMutation };
|
export { useUpdateMarkerMutation };
|
||||||
|
|
|
@ -25,8 +25,8 @@ const importNotification = (notification: NormalizedNotification) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const useNotification = (notificationId: string) => {
|
const useNotification = (notificationId: string) => {
|
||||||
const queryClient = usePlHooksQueryClient();
|
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
const notificationQuery = useQuery({
|
const notificationQuery = useQuery({
|
||||||
queryKey: ['notifications', 'entities', notificationId],
|
queryKey: ['notifications', 'entities', notificationId],
|
||||||
|
|
|
@ -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 { usePlHooksApiClient } from 'pl-hooks/contexts/api-client';
|
||||||
import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
||||||
|
@ -33,9 +33,13 @@ const importNotifications = (response: PaginatedResponse<BaseNotification>) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const useNotificationList = (params: UseNotificationParams) => {
|
const useNotificationList = (params: UseNotificationParams): Omit<UseInfiniteQueryResult<InfiniteData<{
|
||||||
const queryClient = usePlHooksQueryClient();
|
items: string[];
|
||||||
|
previous: (() => Promise<PaginatedResponse<BaseNotification>>) | null;
|
||||||
|
next: (() => Promise<PaginatedResponse<BaseNotification>>) | null;
|
||||||
|
}, unknown>, Error>, 'data'> & { data: string[] } => {
|
||||||
const { client } = usePlHooksApiClient();
|
const { client } = usePlHooksApiClient();
|
||||||
|
const queryClient = usePlHooksQueryClient();
|
||||||
|
|
||||||
const notificationsQuery = useInfiniteQuery({
|
const notificationsQuery = useInfiniteQuery({
|
||||||
queryKey: getQueryKey(params),
|
queryKey: getQueryKey(params),
|
||||||
|
@ -47,7 +51,7 @@ const useNotificationList = (params: UseNotificationParams) => {
|
||||||
getNextPageParam: (response) => response,
|
getNextPageParam: (response) => response,
|
||||||
}, queryClient);
|
}, queryClient);
|
||||||
|
|
||||||
const data = flattenPages<string>(notificationsQuery.data) || [];
|
const data: string[] = flattenPages<string>(notificationsQuery.data) || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...notificationsQuery,
|
...notificationsQuery,
|
||||||
|
|
|
@ -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 { usePlHooksApiClient } from 'pl-hooks/contexts/api-client';
|
||||||
import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
import { queryClient, usePlHooksQueryClient } from 'pl-hooks/contexts/query-client';
|
||||||
import { importEntities } from 'pl-hooks/importer';
|
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 { normalizeStatus, type Status } from '../../normalizers/normalizeStatus';
|
||||||
|
|
||||||
import type { Account } from 'pl-hooks/normalizers/normalizeAccount';
|
|
||||||
|
|
||||||
// const toServerSideType = (columnType: string): Filter['context'][0] => {
|
// const toServerSideType = (columnType: string): Filter['context'][0] => {
|
||||||
// switch (columnType) {
|
// switch (columnType) {
|
||||||
// case 'home':
|
// case 'home':
|
||||||
|
@ -101,11 +101,14 @@ const useStatus = (statusId?: string, opts: { language?: string } = {}) => {
|
||||||
|
|
||||||
const status = statusQuery.data;
|
const status = statusQuery.data;
|
||||||
|
|
||||||
queryClient.getQueriesData({ queryKey: ['test', ['t']] });
|
const accountsQuery = useQueries({
|
||||||
|
queries: status?.account_ids.map(accountId => ({
|
||||||
const accountsQuery = queryClient.getQueriesData<Account>({
|
queryKey: ['accounts', 'entities', accountId],
|
||||||
queryKey: ['accounts', 'entities', status?.account_ids],
|
queryFn: () => client.accounts.getAccount(accountId!)
|
||||||
});
|
.then(account => (importEntities({ accounts: [account] }, { withParents: false }), account))
|
||||||
|
.then(normalizeAccount),
|
||||||
|
})) || [],
|
||||||
|
}, queryClient);
|
||||||
|
|
||||||
let data: (Status & {
|
let data: (Status & {
|
||||||
account: Account;
|
account: Account;
|
||||||
|
@ -115,8 +118,8 @@ const useStatus = (statusId?: string, opts: { language?: string } = {}) => {
|
||||||
if (status) {
|
if (status) {
|
||||||
data = {
|
data = {
|
||||||
...status,
|
...status,
|
||||||
account: accountsQuery[0][1]!,
|
account: accountsQuery[0].data!,
|
||||||
accounts: accountsQuery.map(([_, account]) => account!).filter(Boolean),
|
accounts: accountsQuery.map(({ data }) => data!).filter(Boolean),
|
||||||
// quote,
|
// quote,
|
||||||
// reblog,
|
// reblog,
|
||||||
// poll
|
// poll
|
||||||
|
|
|
@ -11,9 +11,9 @@ import type {
|
||||||
Status as BaseStatus,
|
Status as BaseStatus,
|
||||||
} from 'pl-api';
|
} from 'pl-api';
|
||||||
|
|
||||||
const importAccount = (account: BaseAccount) => {
|
const importAccount = (account: BaseAccount) => queryClient.setQueryData<BaseAccount>(
|
||||||
return queryClient.setQueryData<BaseAccount>(['accounts', 'entities', account.id], account);
|
['accounts', 'entities', account.id], account,
|
||||||
};
|
);
|
||||||
|
|
||||||
const importGroup = (group: BaseGroup) => queryClient.setQueryData<BaseGroup>(
|
const importGroup = (group: BaseGroup) => queryClient.setQueryData<BaseGroup>(
|
||||||
['groups', 'entities', group.id], group,
|
['groups', 'entities', group.id], group,
|
||||||
|
@ -33,8 +33,7 @@ const importRelationship = (relationship: BaseRelationship) => queryClient.setQu
|
||||||
);
|
);
|
||||||
|
|
||||||
const importStatus = (status: BaseStatus) => queryClient.setQueryData<Status>(
|
const importStatus = (status: BaseStatus) => queryClient.setQueryData<Status>(
|
||||||
['statuses', 'entities', status.id],
|
['statuses', 'entities', status.id], normalizeStatus(status),
|
||||||
_ => normalizeStatus(status),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const isEmpty = (object: Record<string, any>) => !Object.values(object).some(value => value);
|
const isEmpty = (object: Record<string, any>) => !Object.values(object).some(value => value);
|
||||||
|
@ -56,23 +55,30 @@ const importEntities = (entities: {
|
||||||
const relationships: Record<string, BaseRelationship> = {};
|
const relationships: Record<string, BaseRelationship> = {};
|
||||||
const statuses: Record<string, BaseStatus> = {};
|
const statuses: Record<string, BaseStatus> = {};
|
||||||
|
|
||||||
const processAccount = (account: BaseAccount) => {
|
const processAccount = (account: BaseAccount, withSelf = true) => {
|
||||||
|
if (withSelf) accounts[account.id] = account;
|
||||||
|
|
||||||
queryClient.setQueryData<string>(['accounts', 'byAcct', account.acct.toLocaleLowerCase()], account.id);
|
queryClient.setQueryData<string>(['accounts', 'byAcct', account.acct.toLocaleLowerCase()], account.id);
|
||||||
|
|
||||||
if (account.moved) processAccount(account.moved);
|
if (account.moved) processAccount(account.moved);
|
||||||
if (account.relationship) relationships[account.relationship.id] = account.relationship;
|
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);
|
processAccount(notification.account);
|
||||||
if (notification.type === 'move') processAccount(notification.target);
|
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
|
// @ts-ignore
|
||||||
processStatus(notification.status);
|
processStatus(notification.status);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const processStatus = (status: BaseStatus) => {
|
const processStatus = (status: BaseStatus, withSelf = true) => {
|
||||||
|
if (withSelf) statuses[status.id] = status;
|
||||||
|
|
||||||
if (status.account) {
|
if (status.account) {
|
||||||
processAccount(status.account);
|
processAccount(status.account);
|
||||||
}
|
}
|
||||||
|
@ -84,17 +90,14 @@ const importEntities = (entities: {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.withParents) {
|
if (options.withParents) {
|
||||||
entities.accounts?.forEach(account => accounts[account.id] = account);
|
|
||||||
entities.groups?.forEach(group => groups[group.id] = group);
|
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.polls?.forEach(poll => polls[poll.id] = poll);
|
||||||
entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship);
|
entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship);
|
||||||
entities.statuses?.forEach(status => statuses[status.id] = status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entities.accounts?.forEach((account) => processAccount(account));
|
entities.accounts?.forEach((account) => processAccount(account, options.withParents));
|
||||||
entities.notifications?.forEach((notification) => processNotification(notification));
|
entities.notifications?.forEach((notification) => processNotification(notification, options.withParents));
|
||||||
entities.statuses?.forEach((status) => processStatus(status));
|
entities.statuses?.forEach((status) => processStatus(status, options.withParents));
|
||||||
|
|
||||||
if (!isEmpty(accounts)) Object.values(accounts).forEach(importAccount);
|
if (!isEmpty(accounts)) Object.values(accounts).forEach(importAccount);
|
||||||
if (!isEmpty(groups)) Object.values(groups).forEach(importGroup);
|
if (!isEmpty(groups)) Object.values(groups).forEach(importGroup);
|
||||||
|
|
|
@ -4,6 +4,8 @@ export * from './contexts/query-client';
|
||||||
export * from './hooks/accounts/useAccount';
|
export * from './hooks/accounts/useAccount';
|
||||||
export * from './hooks/accounts/useAccountLookup';
|
export * from './hooks/accounts/useAccountLookup';
|
||||||
export * from './hooks/accounts/useAccountRelationship';
|
export * from './hooks/accounts/useAccountRelationship';
|
||||||
|
export * from './hooks/instance/useInstance';
|
||||||
|
export * from './hooks/instance/useTranslationLanguages';
|
||||||
export * from './hooks/markers/useMarkers';
|
export * from './hooks/markers/useMarkers';
|
||||||
export * from './hooks/markers/useUpdateMarkerMutation';
|
export * from './hooks/markers/useUpdateMarkerMutation';
|
||||||
export * from './hooks/notifications/useNotification';
|
export * from './hooks/notifications/useNotification';
|
||||||
|
|
Loading…
Reference in a new issue