pl-fe: migrate status translations to tanstack query
Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
parent
a99c61d454
commit
f0542c2a62
8 changed files with 134 additions and 145 deletions
|
@ -9,7 +9,7 @@ import { setComposeToStatus } from './compose';
|
|||
import { importEntities } from './importer';
|
||||
import { deleteFromTimelines } from './timelines';
|
||||
|
||||
import type { CreateStatusParams, Status as BaseStatus, ScheduledStatus, Translation } from 'pl-api';
|
||||
import type { CreateStatusParams, Status as BaseStatus, ScheduledStatus } from 'pl-api';
|
||||
import type { Status } from 'pl-fe/normalizers/status';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
import type { IntlShape } from 'react-intl';
|
||||
|
@ -48,11 +48,6 @@ const STATUS_HIDE_MEDIA = 'STATUS_HIDE_MEDIA' as const;
|
|||
const STATUS_EXPAND_SPOILER = 'STATUS_EXPAND_SPOILER' as const;
|
||||
const STATUS_COLLAPSE_SPOILER = 'STATUS_COLLAPSE_SPOILER' as const;
|
||||
|
||||
const STATUS_TRANSLATE_REQUEST = 'STATUS_TRANSLATE_REQUEST' as const;
|
||||
const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS' as const;
|
||||
const STATUS_TRANSLATE_FAIL = 'STATUS_TRANSLATE_FAIL' as const;
|
||||
const STATUS_TRANSLATE_UNDO = 'STATUS_TRANSLATE_UNDO' as const;
|
||||
|
||||
const STATUS_UNFILTER = 'STATUS_UNFILTER' as const;
|
||||
|
||||
const STATUS_LANGUAGE_CHANGE = 'STATUS_LANGUAGE_CHANGE' as const;
|
||||
|
@ -269,75 +264,54 @@ const expandStatusSpoiler = (statusIds: string[] | string) => {
|
|||
};
|
||||
};
|
||||
|
||||
let TRANSLATIONS_QUEUE: Set<string> = new Set();
|
||||
let TRANSLATIONS_TIMEOUT: NodeJS.Timeout | null = null;
|
||||
// let TRANSLATIONS_QUEUE: Set<string> = new Set();
|
||||
// let TRANSLATIONS_TIMEOUT: NodeJS.Timeout | null = null;
|
||||
|
||||
const translateStatus = (statusId: string, targetLanguage: string, lazy?: boolean) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const client = getClient(getState);
|
||||
const features = client.features;
|
||||
// const translateStatus = (statusId: string, targetLanguage: string, lazy?: boolean) =>
|
||||
// (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
// const client = getClient(getState);
|
||||
// const features = client.features;
|
||||
|
||||
dispatch<StatusesAction>({ type: STATUS_TRANSLATE_REQUEST, statusId });
|
||||
// const handleTranslateMany = () => {
|
||||
// const copy = [...TRANSLATIONS_QUEUE];
|
||||
// TRANSLATIONS_QUEUE = new Set();
|
||||
// if (TRANSLATIONS_TIMEOUT) clearTimeout(TRANSLATIONS_TIMEOUT);
|
||||
|
||||
const handleTranslateMany = () => {
|
||||
const copy = [...TRANSLATIONS_QUEUE];
|
||||
TRANSLATIONS_QUEUE = new Set();
|
||||
if (TRANSLATIONS_TIMEOUT) clearTimeout(TRANSLATIONS_TIMEOUT);
|
||||
// return client.statuses.translateStatuses(copy, targetLanguage).then((response) => {
|
||||
// response.forEach((translation) => {
|
||||
// dispatch<StatusesAction>({
|
||||
// type: STATUS_TRANSLATE_SUCCESS,
|
||||
// statusId: translation.id,
|
||||
// translation: translation,
|
||||
// });
|
||||
|
||||
return client.statuses.translateStatuses(copy, targetLanguage).then((response) => {
|
||||
response.forEach((translation) => {
|
||||
dispatch<StatusesAction>({
|
||||
type: STATUS_TRANSLATE_SUCCESS,
|
||||
statusId: translation.id,
|
||||
translation: translation,
|
||||
});
|
||||
// copy
|
||||
// .filter((statusId) => !response.some(({ id }) => id === statusId))
|
||||
// .forEach((statusId) => dispatch<StatusesAction>({
|
||||
// type: STATUS_TRANSLATE_FAIL,
|
||||
// statusId,
|
||||
// }));
|
||||
// });
|
||||
// }).catch(error => {
|
||||
// dispatch<StatusesAction>({
|
||||
// type: STATUS_TRANSLATE_FAIL,
|
||||
// statusId,
|
||||
// error,
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
|
||||
copy
|
||||
.filter((statusId) => !response.some(({ id }) => id === statusId))
|
||||
.forEach((statusId) => dispatch<StatusesAction>({
|
||||
type: STATUS_TRANSLATE_FAIL,
|
||||
statusId,
|
||||
}));
|
||||
});
|
||||
}).catch(error => {
|
||||
dispatch<StatusesAction>({
|
||||
type: STATUS_TRANSLATE_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
});
|
||||
});
|
||||
};
|
||||
// if (features.lazyTranslations && lazy) {
|
||||
// TRANSLATIONS_QUEUE.add(statusId);
|
||||
|
||||
if (features.lazyTranslations && lazy) {
|
||||
TRANSLATIONS_QUEUE.add(statusId);
|
||||
// if (TRANSLATIONS_TIMEOUT) clearTimeout(TRANSLATIONS_TIMEOUT);
|
||||
// TRANSLATIONS_TIMEOUT = setTimeout(() => handleTranslateMany(), 3000);
|
||||
// } else if (features.lazyTranslations && TRANSLATIONS_QUEUE.size) {
|
||||
// TRANSLATIONS_QUEUE.add(statusId);
|
||||
|
||||
if (TRANSLATIONS_TIMEOUT) clearTimeout(TRANSLATIONS_TIMEOUT);
|
||||
TRANSLATIONS_TIMEOUT = setTimeout(() => handleTranslateMany(), 3000);
|
||||
} else if (features.lazyTranslations && TRANSLATIONS_QUEUE.size) {
|
||||
TRANSLATIONS_QUEUE.add(statusId);
|
||||
|
||||
handleTranslateMany();
|
||||
} else {
|
||||
return client.statuses.translateStatus(statusId, targetLanguage).then(response => {
|
||||
dispatch<StatusesAction>({
|
||||
type: STATUS_TRANSLATE_SUCCESS,
|
||||
statusId,
|
||||
translation: response,
|
||||
});
|
||||
}).catch(error => {
|
||||
dispatch<StatusesAction>({
|
||||
type: STATUS_TRANSLATE_FAIL,
|
||||
statusId,
|
||||
error,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const undoStatusTranslation = (statusId: string) => ({
|
||||
type: STATUS_TRANSLATE_UNDO,
|
||||
statusId,
|
||||
});
|
||||
// handleTranslateMany();
|
||||
// }
|
||||
// };
|
||||
|
||||
const unfilterStatus = (statusId: string) => ({
|
||||
type: STATUS_UNFILTER,
|
||||
|
@ -376,10 +350,6 @@ type StatusesAction =
|
|||
| ReturnType<typeof revealStatusMedia>
|
||||
| ReturnType<typeof collapseStatusSpoiler>
|
||||
| ReturnType<typeof expandStatusSpoiler>
|
||||
| { type: typeof STATUS_TRANSLATE_REQUEST; statusId: string }
|
||||
| { type: typeof STATUS_TRANSLATE_SUCCESS; statusId: string | null; translation: Translation }
|
||||
| { type: typeof STATUS_TRANSLATE_FAIL; statusId: string; error?: unknown }
|
||||
| ReturnType<typeof undoStatusTranslation>
|
||||
| ReturnType<typeof unfilterStatus>
|
||||
| ReturnType<typeof changeStatusLanguage>;
|
||||
|
||||
|
@ -409,10 +379,6 @@ export {
|
|||
STATUS_HIDE_MEDIA,
|
||||
STATUS_EXPAND_SPOILER,
|
||||
STATUS_COLLAPSE_SPOILER,
|
||||
STATUS_TRANSLATE_REQUEST,
|
||||
STATUS_TRANSLATE_SUCCESS,
|
||||
STATUS_TRANSLATE_FAIL,
|
||||
STATUS_TRANSLATE_UNDO,
|
||||
STATUS_UNFILTER,
|
||||
STATUS_LANGUAGE_CHANGE,
|
||||
createStatus,
|
||||
|
@ -430,8 +396,6 @@ export {
|
|||
toggleStatusMediaHidden,
|
||||
expandStatusSpoiler,
|
||||
collapseStatusSpoiler,
|
||||
translateStatus,
|
||||
undoStatusTranslation,
|
||||
unfilterStatus,
|
||||
changeStatusLanguage,
|
||||
type StatusesAction,
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useClient } from 'pl-fe/hooks/use-client';
|
||||
|
||||
import type { Translation } from 'pl-api';
|
||||
|
||||
const useStatusTranslation = (statusId: string, targetLanguage?: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useQuery<Translation | false>({
|
||||
queryKey: ['statuses', 'translations', statusId, targetLanguage],
|
||||
queryFn: () => client.statuses.translateStatus(statusId, targetLanguage)
|
||||
.then(translation => translation).catch(() => false),
|
||||
enabled: !!targetLanguage,
|
||||
});
|
||||
};
|
||||
|
||||
export { useStatusTranslation };
|
|
@ -11,7 +11,7 @@ import { toggleBookmark, toggleDislike, toggleFavourite, togglePin, toggleReblog
|
|||
import { deleteStatusModal, toggleStatusSensitivityModal } from 'pl-fe/actions/moderation';
|
||||
import { initReport, ReportableEntities } from 'pl-fe/actions/reports';
|
||||
import { changeSetting } from 'pl-fe/actions/settings';
|
||||
import { deleteStatus, editStatus, toggleMuteStatus, translateStatus, undoStatusTranslation } from 'pl-fe/actions/statuses';
|
||||
import { deleteStatus, editStatus, toggleMuteStatus } from 'pl-fe/actions/statuses';
|
||||
import { deleteFromTimelines } from 'pl-fe/actions/timelines';
|
||||
import { useBlockGroupMember } from 'pl-fe/api/hooks/groups/use-block-group-member';
|
||||
import { useDeleteGroupStatus } from 'pl-fe/api/hooks/groups/use-delete-group-status';
|
||||
|
@ -33,6 +33,7 @@ import { useSettings } from 'pl-fe/hooks/use-settings';
|
|||
import { useChats } from 'pl-fe/queries/chats';
|
||||
import { RootState } from 'pl-fe/store';
|
||||
import { useModalsStore } from 'pl-fe/stores/modals';
|
||||
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
|
||||
import toast from 'pl-fe/toast';
|
||||
import copy from 'pl-fe/utils/copy';
|
||||
|
||||
|
@ -574,7 +575,6 @@ interface IMenuButton extends IActionButton {
|
|||
const MenuButton: React.FC<IMenuButton> = ({
|
||||
status,
|
||||
statusActionButtonTheme,
|
||||
withLabels,
|
||||
me,
|
||||
expandable,
|
||||
fromBookmarks,
|
||||
|
@ -585,6 +585,8 @@ const MenuButton: React.FC<IMenuButton> = ({
|
|||
const match = useRouteMatch<{ groupId: string }>('/groups/:groupId');
|
||||
const { boostModal } = useSettings();
|
||||
|
||||
const { statuses: statusesMeta, fetchTranslation, hideTranslation } = useStatusMetaStore();
|
||||
const targetLanguage = statusesMeta[status.id]?.targetLanguage;
|
||||
const { openModal } = useModalsStore();
|
||||
const { group } = useGroup((status.group as Group)?.id as string);
|
||||
const deleteGroupStatus = useDeleteGroupStatus(group as Group, status.id);
|
||||
|
@ -774,10 +776,10 @@ const MenuButton: React.FC<IMenuButton> = ({
|
|||
};
|
||||
|
||||
const handleTranslate = () => {
|
||||
if (status.translation) {
|
||||
dispatch(undoStatusTranslation(status.id));
|
||||
if (targetLanguage) {
|
||||
hideTranslation(status.id);
|
||||
} else {
|
||||
dispatch(translateStatus(status.id, intl.locale));
|
||||
fetchTranslation(status.id, intl.locale);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -941,7 +943,7 @@ const MenuButton: React.FC<IMenuButton> = ({
|
|||
}
|
||||
|
||||
if (autoTranslating) {
|
||||
if (status.translation) {
|
||||
if (targetLanguage) {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.hideTranslation),
|
||||
action: handleTranslate,
|
||||
|
|
|
@ -3,6 +3,7 @@ import React, { useState, useRef, useLayoutEffect, useMemo, useEffect } from 're
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { collapseStatusSpoiler, expandStatusSpoiler } from 'pl-fe/actions/statuses';
|
||||
import { useStatusTranslation } from 'pl-fe/api/hooks/statuses/use-status-translation';
|
||||
import Icon from 'pl-fe/components/icon';
|
||||
import Button from 'pl-fe/components/ui/button';
|
||||
import Stack from 'pl-fe/components/ui/stack';
|
||||
|
@ -11,6 +12,7 @@ import Emojify from 'pl-fe/features/emoji/emojify';
|
|||
import QuotedStatus from 'pl-fe/features/status/containers/quoted-status-container';
|
||||
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
|
||||
import { useSettings } from 'pl-fe/hooks/use-settings';
|
||||
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
|
||||
import { onlyEmoji as isOnlyEmoji } from 'pl-fe/utils/rich-content';
|
||||
|
||||
import { getTextDirection } from '../utils/rtl';
|
||||
|
@ -91,6 +93,9 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
const node = useRef<HTMLDivElement>(null);
|
||||
const spoilerNode = useRef<HTMLSpanElement>(null);
|
||||
|
||||
const { statuses: statusesMeta } = useStatusMetaStore();
|
||||
const { data: translation } = useStatusTranslation(status.id, statusesMeta[status.id]?.targetLanguage);
|
||||
|
||||
const maybeSetCollapsed = (): void => {
|
||||
if (!node.current) return;
|
||||
|
||||
|
@ -125,12 +130,12 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
|
|||
});
|
||||
|
||||
const content = useMemo(
|
||||
(): string => translatable && status.translation
|
||||
? status.translation.content!
|
||||
(): string => translation
|
||||
? translation.content
|
||||
: (status.content_map && status.currentLanguage)
|
||||
? (status.content_map[status.currentLanguage] || status.content)
|
||||
: status.content,
|
||||
[status.content, status.translation, status.currentLanguage],
|
||||
[status.content, translation, status.currentLanguage],
|
||||
);
|
||||
|
||||
const { content: parsedContent, hashtags } = useMemo(() => parseContent({
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { translateStatus, undoStatusTranslation } from 'pl-fe/actions/statuses';
|
||||
import { useTranslationLanguages } from 'pl-fe/api/hooks/instance/use-translation-languages';
|
||||
import { useStatusTranslation } from 'pl-fe/api/hooks/statuses/use-status-translation';
|
||||
import HStack from 'pl-fe/components/ui/hstack';
|
||||
import Icon from 'pl-fe/components/ui/icon';
|
||||
import Stack from 'pl-fe/components/ui/stack';
|
||||
import Text from 'pl-fe/components/ui/text';
|
||||
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
|
||||
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
|
||||
import { useFeatures } from 'pl-fe/hooks/use-features';
|
||||
import { useInstance } from 'pl-fe/hooks/use-instance';
|
||||
import { useSettings } from 'pl-fe/hooks/use-settings';
|
||||
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
|
||||
|
||||
import type { Status } from 'pl-fe/normalizers/status';
|
||||
|
||||
interface ITranslateButton {
|
||||
status: Pick<Status, 'id' | 'account' | 'content' | 'content_map' | 'language' | 'translating' | 'translation' | 'visibility'>;
|
||||
status: Pick<Status, 'id' | 'account' | 'content' | 'content_map' | 'language' | 'visibility'>;
|
||||
}
|
||||
|
||||
const TranslateButton: React.FC<ITranslateButton> = ({ status }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const features = useFeatures();
|
||||
const instance = useInstance();
|
||||
|
@ -30,6 +29,10 @@ const TranslateButton: React.FC<ITranslateButton> = ({ status }) => {
|
|||
|
||||
const me = useAppSelector((state) => state.me);
|
||||
const { translationLanguages } = useTranslationLanguages();
|
||||
const { statuses: statusesMeta, fetchTranslation, hideTranslation } = useStatusMetaStore();
|
||||
|
||||
const targetLanguage = statusesMeta[status.id]?.targetLanguage;
|
||||
const translationQuery = useStatusTranslation(status.id, targetLanguage);
|
||||
|
||||
const {
|
||||
allow_remote: allowRemote,
|
||||
|
@ -43,45 +46,45 @@ const TranslateButton: React.FC<ITranslateButton> = ({ status }) => {
|
|||
const handleTranslate: React.MouseEventHandler<HTMLButtonElement> = (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (status.translation) {
|
||||
dispatch(undoStatusTranslation(status.id));
|
||||
if (targetLanguage) {
|
||||
hideTranslation(status.id);
|
||||
} else {
|
||||
dispatch(translateStatus(status.id, intl.locale));
|
||||
fetchTranslation(status.id, intl.locale);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (status.translation === null && settings.autoTranslate && features.translations && renderTranslate && supportsLanguages && status.translation !== false && status.language !== null && !knownLanguages.includes(status.language)) {
|
||||
dispatch(translateStatus(status.id, intl.locale, true));
|
||||
if (translationQuery.data === undefined && settings.autoTranslate && features.translations && renderTranslate && supportsLanguages && translationQuery.data !== false && status.language !== null && !knownLanguages.includes(status.language)) {
|
||||
fetchTranslation(status.id, intl.locale);
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!features.translations || !renderTranslate || !supportsLanguages || status.translation === false) return null;
|
||||
if (!features.translations || !renderTranslate || !supportsLanguages || translationQuery.data === false) return null;
|
||||
|
||||
const button = (
|
||||
<button className='w-fit' onClick={handleTranslate}>
|
||||
<HStack alignItems='center' space={1} className='text-primary-600 hover:underline dark:text-gray-600'>
|
||||
<Icon src={require('@tabler/icons/outline/language.svg')} className='size-4' />
|
||||
<span>
|
||||
{status.translation ? (
|
||||
{translationQuery.data ? (
|
||||
<FormattedMessage id='status.show_original' defaultMessage='Show original' />
|
||||
) : status.translating ? (
|
||||
) : translationQuery.isLoading ? (
|
||||
<FormattedMessage id='status.translating' defaultMessage='Translating…' />
|
||||
) : (
|
||||
<FormattedMessage id='status.translate' defaultMessage='Translate' />
|
||||
)}
|
||||
</span>
|
||||
{status.translating && (
|
||||
{translationQuery.isLoading && (
|
||||
<Icon src={require('@tabler/icons/outline/loader-2.svg')} className='size-4 animate-spin' />
|
||||
)}
|
||||
</HStack>
|
||||
</button>
|
||||
);
|
||||
|
||||
if (status.translation) {
|
||||
if (translationQuery.data) {
|
||||
const languageNames = new Intl.DisplayNames([intl.locale], { type: 'language' });
|
||||
const languageName = languageNames.of(status.language!);
|
||||
const provider = status.translation.provider;
|
||||
const provider = translationQuery.data.provider;
|
||||
|
||||
return (
|
||||
<Stack space={3} alignItems='start'>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Converts API statuses into our internal format.
|
||||
* @see {@link https://docs.joinmastodon.org/entities/status/}
|
||||
*/
|
||||
import { type Account as BaseAccount, type Status as BaseStatus, type MediaAttachment, mentionSchema, type Translation } from 'pl-api';
|
||||
import { type Account as BaseAccount, type Status as BaseStatus, type MediaAttachment, mentionSchema } from 'pl-api';
|
||||
import * as v from 'valibot';
|
||||
|
||||
import { unescapeHTML } from 'pl-fe/utils/html';
|
||||
|
@ -20,7 +20,6 @@ type CalculatedValues = {
|
|||
search_index: string;
|
||||
expanded?: boolean | null;
|
||||
hidden?: boolean | null;
|
||||
translation?: Translation | null | false;
|
||||
currentLanguage?: string;
|
||||
};
|
||||
|
||||
|
@ -57,11 +56,11 @@ const buildSearchContent = (status: Pick<BaseStatus, 'poll' | 'mentions' | 'spoi
|
|||
const calculateStatus = (status: BaseStatus, oldStatus?: OldStatus): CalculatedValues => {
|
||||
if (oldStatus && oldStatus.content === status.content && oldStatus.spoiler_text === status.spoiler_text) {
|
||||
const {
|
||||
search_index, hidden, expanded, translation, currentLanguage,
|
||||
search_index, hidden, expanded, currentLanguage,
|
||||
} = oldStatus;
|
||||
|
||||
return {
|
||||
search_index, hidden, expanded, translation, currentLanguage,
|
||||
search_index, hidden, expanded, currentLanguage,
|
||||
};
|
||||
} else {
|
||||
const searchContent = buildSearchContent(status);
|
||||
|
@ -129,7 +128,6 @@ const normalizeStatus = (status: BaseStatus & {
|
|||
reblog_id: status.reblog?.id || null,
|
||||
poll_id: status.poll?.id || null,
|
||||
group_id: status.group?.id || null,
|
||||
translating: false,
|
||||
expectsCard: false,
|
||||
showFiltered: null as null | boolean,
|
||||
...status,
|
||||
|
@ -144,7 +142,6 @@ const normalizeStatus = (status: BaseStatus & {
|
|||
group,
|
||||
media_attachments,
|
||||
...calculated,
|
||||
translation: (status.translation || calculated.translation || null) as Translation | null | false,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -39,10 +39,6 @@ import {
|
|||
STATUS_HIDE_MEDIA,
|
||||
STATUS_MUTE_SUCCESS,
|
||||
STATUS_REVEAL_MEDIA,
|
||||
STATUS_TRANSLATE_FAIL,
|
||||
STATUS_TRANSLATE_REQUEST,
|
||||
STATUS_TRANSLATE_SUCCESS,
|
||||
STATUS_TRANSLATE_UNDO,
|
||||
STATUS_UNFILTER,
|
||||
STATUS_UNMUTE_SUCCESS,
|
||||
STATUS_LANGUAGE_CHANGE,
|
||||
|
@ -52,7 +48,7 @@ import {
|
|||
} from '../actions/statuses';
|
||||
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
|
||||
|
||||
import type { Status as BaseStatus, CreateStatusParams, Translation } from 'pl-api';
|
||||
import type { Status as BaseStatus, CreateStatusParams } from 'pl-api';
|
||||
|
||||
type State = Record<string, MinifiedStatus>;
|
||||
|
||||
|
@ -162,18 +158,6 @@ const simulateDislike = (
|
|||
state[statusId] = updatedStatus;
|
||||
};
|
||||
|
||||
/** Import translation from translation service into the store. */
|
||||
const importTranslation = (state: State, statusId: string, translation: Translation) => {
|
||||
if (!state[statusId]) return;
|
||||
state[statusId].translation = translation;
|
||||
state[statusId].translating = false;
|
||||
};
|
||||
|
||||
/** Delete translation from the store. */
|
||||
const deleteTranslation = (state: State, statusId: string) => {
|
||||
state[statusId].translation = null;
|
||||
};
|
||||
|
||||
const initialState: State = {};
|
||||
|
||||
const statuses = (state = initialState, action: EmojiReactsAction | EventsAction | ImporterAction | InteractionsAction | StatusesAction | TimelineAction): State => {
|
||||
|
@ -300,7 +284,6 @@ const statuses = (state = initialState, action: EmojiReactsAction | EventsAction
|
|||
const status = draft[id];
|
||||
if (status) {
|
||||
status.expanded = false;
|
||||
status.translation = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -308,25 +291,6 @@ const statuses = (state = initialState, action: EmojiReactsAction | EventsAction
|
|||
return create(state, (draft) => decrementReplyCount(draft, action.params));
|
||||
case STATUS_DELETE_FAIL:
|
||||
return create(state, (draft) => incrementReplyCount(draft, action.params));
|
||||
case STATUS_TRANSLATE_REQUEST:
|
||||
return create(state, (draft) => {
|
||||
const status = draft[action.statusId];
|
||||
if (status) {
|
||||
status.translating = true;
|
||||
}
|
||||
});
|
||||
case STATUS_TRANSLATE_SUCCESS:
|
||||
return action.statusId !== null ? create(state, (draft) => importTranslation(draft, action.statusId!, action.translation)) : state;
|
||||
case STATUS_TRANSLATE_FAIL:
|
||||
return create(state, (draft) => {
|
||||
const status = draft[action.statusId];
|
||||
if (status) {
|
||||
status.translating = false;
|
||||
status.translation = false;
|
||||
}
|
||||
});
|
||||
case STATUS_TRANSLATE_UNDO:
|
||||
return create(state, (draft) => deleteTranslation(draft, action.statusId));
|
||||
case STATUS_UNFILTER:
|
||||
return create(state, (draft) => {
|
||||
const status = draft[action.statusId];
|
||||
|
|
36
packages/pl-fe/src/stores/status-meta.ts
Normal file
36
packages/pl-fe/src/stores/status-meta.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { create } from 'zustand';
|
||||
import { mutative } from 'zustand-mutative';
|
||||
|
||||
type State = {
|
||||
statuses: Record<string, { visible?: boolean; targetLanguage?: string }>;
|
||||
revealStatus: (statusId: string) => void;
|
||||
hideStatus: (statusId: string) => void;
|
||||
fetchTranslation: (statusId: string, targetLanguage: string) => void;
|
||||
hideTranslation: (statusId: string) => void;
|
||||
};
|
||||
|
||||
const useStatusMetaStore = create<State>()(mutative((set) => ({
|
||||
statuses: {},
|
||||
revealStatus: (statusId) => set((state: State) => {
|
||||
if (!state.statuses[statusId]) state.statuses[statusId] = {};
|
||||
|
||||
state.statuses[statusId].visible = true;
|
||||
}),
|
||||
hideStatus: (statusId) => set((state: State) => {
|
||||
if (!state.statuses[statusId]) state.statuses[statusId] = {};
|
||||
|
||||
state.statuses[statusId].visible = false;
|
||||
}),
|
||||
fetchTranslation: (statusId, targetLanguage) => set((state: State) => {
|
||||
if (!state.statuses[statusId]) state.statuses[statusId] = {};
|
||||
|
||||
state.statuses[statusId].targetLanguage = targetLanguage;
|
||||
}),
|
||||
hideTranslation: (statusId) => set((state: State) => {
|
||||
if (!state.statuses[statusId]) state.statuses[statusId] = {};
|
||||
|
||||
state.statuses[statusId].targetLanguage = undefined;
|
||||
}),
|
||||
})));
|
||||
|
||||
export { useStatusMetaStore };
|
Loading…
Reference in a new issue