pl-fe: zustand migrations

Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
mkljczk 2024-11-30 21:33:52 +01:00
parent 4722bccb5c
commit 9f0a4818f2
9 changed files with 34 additions and 64 deletions

View file

@ -44,8 +44,6 @@ const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL' as const;
const STATUS_UNFILTER = 'STATUS_UNFILTER' as const;
const STATUS_LANGUAGE_CHANGE = 'STATUS_LANGUAGE_CHANGE' as const;
const createStatus = (params: CreateStatusParams, idempotencyKey: string, statusId: string | null) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch<StatusesAction>({ type: STATUS_CREATE_REQUEST, params, idempotencyKey, editing: !!statusId });
@ -260,12 +258,6 @@ const unfilterStatus = (statusId: string) => ({
statusId,
});
const changeStatusLanguage = (statusId: string, language: string) => ({
type: STATUS_LANGUAGE_CHANGE,
statusId,
language,
});
type StatusesAction =
| { type: typeof STATUS_CREATE_REQUEST; params: CreateStatusParams; idempotencyKey: string; editing: boolean }
| { type: typeof STATUS_CREATE_SUCCESS; status: BaseStatus | ScheduledStatus; params: CreateStatusParams; idempotencyKey: string; editing: boolean }
@ -289,7 +281,6 @@ type StatusesAction =
| { type: typeof STATUS_UNMUTE_SUCCESS; statusId: string }
| { type: typeof STATUS_UNMUTE_FAIL; statusId: string; error: unknown }
| ReturnType<typeof unfilterStatus>
| ReturnType<typeof changeStatusLanguage>;
export {
STATUS_CREATE_REQUEST,
@ -314,7 +305,6 @@ export {
STATUS_UNMUTE_SUCCESS,
STATUS_UNMUTE_FAIL,
STATUS_UNFILTER,
STATUS_LANGUAGE_CHANGE,
createStatus,
editStatus,
fetchStatus,
@ -326,6 +316,5 @@ export {
unmuteStatus,
toggleMuteStatus,
unfilterStatus,
changeStatusLanguage,
type StatusesAction,
};

View file

@ -17,14 +17,15 @@ type Selected = Record<number, boolean>;
interface IPoll {
id: string;
status?: Pick<Status, 'url' | 'currentLanguage'>;
status?: Pick<Status, 'url'>;
language?: string;
}
const messages = defineMessages({
multiple: { id: 'poll.choose_multiple', defaultMessage: 'Choose as many as you\'d like.' },
});
const Poll: React.FC<IPoll> = ({ id, status }): JSX.Element | null => {
const Poll: React.FC<IPoll> = ({ id, status, language }): JSX.Element | null => {
const { openModal } = useModalsStore();
const dispatch = useAppDispatch();
const intl = useIntl();
@ -87,7 +88,7 @@ const Poll: React.FC<IPoll> = ({ id, status }): JSX.Element | null => {
showResults={showResults}
active={!!selected[i]}
onToggle={toggleOption}
language={status?.currentLanguage}
language={language}
/>
))}
</Stack>

View file

@ -130,10 +130,10 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
const content = useMemo(
(): string => translation
? translation.content
: (status.content_map && status.currentLanguage)
? (status.content_map[status.currentLanguage] || status.content)
: (status.content_map && statusMeta.currentLanguage)
? (status.content_map[statusMeta.currentLanguage] || status.content)
: status.content,
[status.content, translation, status.currentLanguage],
[status.content, translation, statusMeta.currentLanguage],
);
const { content: parsedContent, hashtags } = useMemo(() => parseContent({
@ -149,8 +149,8 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
const withSpoiler = status.spoiler_text.length > 0;
const spoilerText = status.spoiler_text_map && status.currentLanguage
? status.spoiler_text_map[status.currentLanguage] || status.spoiler_text
const spoilerText = status.spoiler_text_map && statusMeta.currentLanguage
? status.spoiler_text_map[statusMeta.currentLanguage] || status.spoiler_text
: status.spoiler_text;
const direction = getTextDirection(status.search_index);
@ -245,7 +245,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
}
if (status.poll_id) {
output.push(<Poll id={status.poll_id} key='poll' status={status} />);
output.push(<Poll id={status.poll_id} key='poll' status={status} language={statusMeta.currentLanguage} />);
}
if (translatable) {
@ -283,7 +283,7 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
}
if (status.poll_id) {
output.push(<Poll id={status.poll_id} key='poll' status={status} />);
output.push(<Poll id={status.poll_id} key='poll' status={status} language={statusMeta.currentLanguage} />);
}
if (translatable) {

View file

@ -1,12 +1,11 @@
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { changeStatusLanguage } from 'pl-fe/actions/statuses';
import HStack from 'pl-fe/components/ui/hstack';
import Icon from 'pl-fe/components/ui/icon';
import Text from 'pl-fe/components/ui/text';
import { type Language, languages } from 'pl-fe/features/preferences';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
import DropdownMenu from './dropdown-menu';
@ -17,13 +16,16 @@ const messages = defineMessages({
});
interface IStatusLanguagePicker {
status: Pick<Status, 'id' | 'content_map' | 'currentLanguage'>;
status: Pick<Status, 'id' | 'content_map'>;
showLabel?: boolean;
}
const StatusLanguagePicker: React.FC<IStatusLanguagePicker> = ({ status, showLabel }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { statuses, setStatusLanguage } = useStatusMetaStore();
const { currentLanguage } = statuses[status.id] || {};
if (!status.content_map || Object.keys(status.content_map).length < 2) return null;
@ -36,8 +38,8 @@ const StatusLanguagePicker: React.FC<IStatusLanguagePicker> = ({ status, showLab
<DropdownMenu
items={Object.keys(status.content_map).map((language) => ({
text: languages[language as Language] || language,
action: () => dispatch(changeStatusLanguage(status.id, language)),
active: language === status.currentLanguage,
action: () => setStatusLanguage(status.id, language),
active: language === currentLanguage,
}))}
>
<button title={intl.formatMessage(messages.languageVersions)} className='hover:underline'>
@ -45,7 +47,7 @@ const StatusLanguagePicker: React.FC<IStatusLanguagePicker> = ({ status, showLab
<HStack space={1} alignItems='center'>
{icon}
<Text tag='span' theme='muted' size='sm'>
{languages[status.currentLanguage as Language] || status.currentLanguage}
{languages[currentLanguage as Language] || currentLanguage}
</Text>
</HStack>
) : icon}

View file

@ -43,7 +43,7 @@ const messages = defineMessages({
});
interface ISensitiveContentOverlay {
status: Pick<Status, 'id' | 'sensitive' | 'spoiler_text' | 'media_attachments' | 'currentLanguage'>;
status: Pick<Status, 'id' | 'sensitive' | 'spoiler_text' | 'media_attachments'>;
}
const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveContentOverlay>((props, ref) => {

View file

@ -16,12 +16,7 @@ const domParser = new DOMParser();
type StatusApprovalStatus = Exclude<BaseStatus['approval_status'], null>;
type StatusVisibility = 'public' | 'unlisted' | 'private' | 'direct' | 'group' | 'mutuals_only' | 'local';
type CalculatedValues = {
search_index: string;
currentLanguage?: string;
};
type OldStatus = Pick<BaseStatus, 'content' | 'spoiler_text'> & CalculatedValues;
type OldStatus = Pick<BaseStatus, 'content' | 'spoiler_text'> & { search_index: string };
// Gets titles of poll options from status
const getPollOptionTitles = ({ poll }: Pick<BaseStatus, 'poll'>): readonly string[] => {
@ -51,28 +46,20 @@ const buildSearchContent = (status: Pick<BaseStatus, 'poll' | 'mentions' | 'spoi
return unescapeHTML(fields.join('\n\n')) || '';
};
const calculateStatus = (status: BaseStatus, oldStatus?: OldStatus): CalculatedValues => {
const getSearchIndex = (status: BaseStatus, oldStatus?: OldStatus) => {
if (oldStatus && oldStatus.content === status.content && oldStatus.spoiler_text === status.spoiler_text) {
const {
search_index, currentLanguage,
} = oldStatus;
return {
search_index, currentLanguage,
};
return oldStatus.search_index;
} else {
const searchContent = buildSearchContent(status);
return {
search_index: domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || '',
};
return domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || '';
}
};
const normalizeStatus = (status: BaseStatus & {
accounts?: Array<BaseAccount>;
}, oldStatus?: OldStatus) => {
const calculated = calculateStatus(status, oldStatus);
const searchIndex = getSearchIndex(status, oldStatus);
// Sort the replied-to mention to the top
let mentions = status.mentions.toSorted((a, _b) => {
@ -137,7 +124,7 @@ const normalizeStatus = (status: BaseStatus & {
event,
group,
media_attachments,
...calculated,
search_index: searchIndex,
};
};

View file

@ -39,7 +39,6 @@ import {
STATUS_MUTE_SUCCESS,
STATUS_UNFILTER,
STATUS_UNMUTE_SUCCESS,
STATUS_LANGUAGE_CHANGE,
type StatusesAction,
} from '../actions/statuses';
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
@ -258,13 +257,6 @@ const statuses = (state = initialState, action: EmojiReactsAction | EventsAction
status.showFiltered = false;
}
});
case STATUS_LANGUAGE_CHANGE:
return create(state, (draft) => {
const status = draft[action.statusId];
if (status) {
status.currentLanguage = action.language;
}
});
case TIMELINE_DELETE:
return create(state, (draft) => deleteStatus(draft, action.statusId, action.references));
case EVENT_JOIN_REQUEST:

View file

@ -162,13 +162,6 @@ const makeGetStatus = () => createSelector(
poll,
filtered,
};
// if (map.currentLanguage === null && map.content_map?.size) {
// let currentLanguage: string | null = null;
// if (map.content_map.has(locale)) currentLanguage = locale;
// else if (map.language && map.content_map.has(map.language)) currentLanguage = map.language;
// else currentLanguage = map.content_map.keySeq().first();
// map.set('currentLanguage', currentLanguage);
// }
},
);

View file

@ -2,7 +2,7 @@ import { create } from 'zustand';
import { mutative } from 'zustand-mutative';
type State = {
statuses: Record<string, { expanded?: boolean; mediaVisible?: boolean; targetLanguage?: string }>;
statuses: Record<string, { expanded?: boolean; mediaVisible?: boolean; currentLanguage?: string; targetLanguage?: string }>;
expandStatus: (statusId: string) => void;
collapseStatus: (statusId: string) => void;
revealStatusMedia: (statusId: string) => void;
@ -10,6 +10,7 @@ type State = {
toggleStatusMediaHidden: (statusId: string) => void;
fetchTranslation: (statusId: string, targetLanguage: string) => void;
hideTranslation: (statusId: string) => void;
setStatusLanguage: (statusId: string, language: string) => void;
};
const useStatusMetaStore = create<State>()(mutative((set) => ({
@ -45,6 +46,11 @@ const useStatusMetaStore = create<State>()(mutative((set) => ({
state.statuses[statusId].targetLanguage = undefined;
}),
setStatusLanguage: (statusId, language) => set((state: State) => {
if (!state.statuses[statusId]) state.statuses[statusId] = {};
state.statuses[statusId].currentLanguage = language;
}),
})));
export { useStatusMetaStore };