pl-fe: remove immutable usage from compose reducer

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-11-14 15:21:01 +01:00
parent e53be89a85
commit e8c89a4415
8 changed files with 43 additions and 46 deletions

View file

@ -318,7 +318,7 @@ const needsDescriptions = (state: RootState, composeId: string) => {
const media = state.compose[composeId]!.media_attachments;
const missingDescriptionModal = useSettingsStore.getState().settings.missingDescriptionModal;
const hasMissing = media.filter(item => !item.description).size > 0;
const hasMissing = media.filter(item => !item.description).length > 0;
return missingDescriptionModal && hasMissing;
};
@ -357,7 +357,7 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}) =>
return;
}
if ((!status || !status.length) && media.size === 0) {
if ((!status || !status.length) && media.length === 0) {
return;
}
@ -392,7 +392,7 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}) =>
status,
in_reply_to_id: compose.in_reply_to || undefined,
quote_id: compose.quote || undefined,
media_ids: media.map(item => item.id).toArray(),
media_ids: media.map(item => item.id),
sensitive: compose.sensitive,
spoiler_text: compose.spoiler_text,
visibility: compose.privacy,
@ -471,7 +471,7 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
const progress = new Array(files.length).fill(0);
let total = Array.from(files).reduce((a, v) => a + v.size, 0);
const mediaCount = media ? media.size : 0;
const mediaCount = media ? media.length : 0;
if (files.length + mediaCount > attachmentLimit) {
toast.error(messages.uploadErrorLimit);
@ -726,7 +726,7 @@ const insertIntoTagHistory = (composeId: string, recognizedTags: Array<Tag>, tex
.map(tag => tag.name);
const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1);
names.push(...intersectedOldHistory.toJS());
names.push(...intersectedOldHistory);
const newHistory = names.slice(0, 1000);

View file

@ -22,7 +22,7 @@ const checkComposeContent = (compose?: Compose) =>
!!compose && [
compose.editorState && compose.editorState.length > 0,
compose.spoiler_text.length > 0,
compose.media_attachments.size > 0,
compose.media_attachments.length > 0,
compose.poll !== null,
].some(check => check === true);

View file

@ -96,7 +96,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
const hasPoll = !!compose.poll;
const isEditing = compose.id !== null;
const anyMedia = compose.media_attachments.size > 0;
const anyMedia = compose.media_attachments.length > 0;
const [composeFocused, setComposeFocused] = useState(false);
@ -189,7 +189,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
</HStack>
), [features, id, anyMedia]);
const showModifiers = !condensed && (compose.media_attachments.size || compose.is_uploading || compose.poll?.options.length || compose.schedule);
const showModifiers = !condensed && (compose.media_attachments.length || compose.is_uploading || compose.poll?.options.length || compose.schedule);
const composeModifiers = showModifiers && (
<Stack space={4} className='font-[inherit] text-sm text-gray-900'>

View file

@ -90,7 +90,7 @@ const Option: React.FC<IOption> = ({
maxLength={maxChars}
value={title}
onChange={handleOptionTitleChange}
suggestions={suggestions.toArray()}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}

View file

@ -37,7 +37,7 @@ const SpoilerInput: React.FC<ISpoilerInput> = ({
placeholder={intl.formatMessage(messages.placeholder)}
value={value}
onChange={handleChangeSpoilerText}
suggestions={suggestions.toArray()}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}

View file

@ -38,13 +38,13 @@ const UploadForm: React.FC<IUploadForm> = ({ composeId, onSubmit }) => {
dragOverItem.current = null;
}, [dragItem, dragOverItem]);
if (!isUploading && mediaIds.isEmpty()) return null;
if (!isUploading && !mediaIds.length) return null;
return (
<div className='overflow-hidden'>
<UploadProgress composeId={composeId} />
<HStack wrap className={clsx('overflow-hidden', mediaIds.size !== 0 && 'm-[-5px]')}>
<HStack wrap className={clsx('overflow-hidden', mediaIds.length > 0 && 'm-[-5px]')}>
{mediaIds.map((id: string) => (
<Upload
id={id}

View file

@ -303,7 +303,7 @@ const AutosuggestPlugin = ({
};
const onSelectSuggestion = (index: number) => {
const suggestion = suggestions.get(index) as AutoSuggestion;
const suggestion = suggestions[index];
editor.update(() => {
dispatch((dispatch, getState) => {
@ -446,11 +446,11 @@ const AutosuggestPlugin = ({
]);
useEffect(() => {
if (suggestions && suggestions.size > 0) setSuggestionsHidden(false);
if (suggestions && suggestions.length > 0) setSuggestionsHidden(false);
}, [suggestions]);
useEffect(() => {
if (resolution !== null && !suggestionsHidden && !suggestions.isEmpty()) {
if (resolution !== null && !suggestionsHidden && suggestions.length) {
const handleClick = (event: MouseEvent) => {
const target = event.target as HTMLElement;
@ -462,7 +462,7 @@ const AutosuggestPlugin = ({
return () => document.removeEventListener('click', handleClick);
}
}, [resolution, suggestionsHidden, suggestions.isEmpty()]);
}, [resolution, suggestionsHidden, !suggestions.length]);
useEffect(() => {
if (resolution === null) return;
@ -472,8 +472,8 @@ const AutosuggestPlugin = ({
KEY_ARROW_UP_COMMAND,
(payload) => {
const event = payload;
if (suggestions !== null && suggestions.size && selectedSuggestion !== null) {
const newSelectedSuggestion = selectedSuggestion !== 0 ? selectedSuggestion - 1 : suggestions.size - 1;
if (suggestions !== null && suggestions.length && selectedSuggestion !== null) {
const newSelectedSuggestion = selectedSuggestion !== 0 ? selectedSuggestion - 1 : suggestions.length - 1;
setSelectedSuggestion(newSelectedSuggestion);
event.preventDefault();
event.stopImmediatePropagation();
@ -486,8 +486,8 @@ const AutosuggestPlugin = ({
KEY_ARROW_DOWN_COMMAND,
(payload) => {
const event = payload;
if (suggestions !== null && suggestions.size && selectedSuggestion !== null) {
const newSelectedSuggestion = selectedSuggestion !== suggestions.size - 1 ? selectedSuggestion + 1 : 0;
if (suggestions !== null && suggestions.length && selectedSuggestion !== null) {
const newSelectedSuggestion = selectedSuggestion !== suggestions.length - 1 ? selectedSuggestion + 1 : 0;
setSelectedSuggestion(newSelectedSuggestion);
event.preventDefault();
event.stopImmediatePropagation();
@ -543,8 +543,8 @@ const AutosuggestPlugin = ({
<div
className={clsx({
'scroll-smooth snap-y snap-always will-change-scroll mt-6 overflow-y-auto max-h-56 relative w-max z-[1000] shadow bg-white dark:bg-gray-900 rounded-lg py-1 space-y-0 dark:ring-2 dark:ring-primary-700 focus:outline-none': true,
hidden: suggestionsHidden || suggestions.isEmpty(),
block: !suggestionsHidden && !suggestions.isEmpty(),
hidden: suggestionsHidden || !suggestions.length,
block: !suggestionsHidden && suggestions.length,
})}
>
{suggestions.map(renderSuggestion)}

View file

@ -1,9 +1,8 @@
import { List as ImmutableList } from 'immutable';
import { create } from 'mutative';
import { Instance, PLEROMA, type CredentialAccount, type MediaAttachment, type Tag } from 'pl-api';
import { PLEROMA, type CredentialAccount, type Instance, type MediaAttachment, type Tag } from 'pl-api';
import { INSTANCE_FETCH_SUCCESS, InstanceAction } from 'pl-fe/actions/instance';
import { isNativeEmoji } from 'pl-fe/features/emoji';
import { isNativeEmoji, type Emoji } from 'pl-fe/features/emoji';
import { tagHistory } from 'pl-fe/settings';
import { hasIntegerMediaIds } from 'pl-fe/utils/status';
@ -69,11 +68,9 @@ import { FE_NAME } from '../actions/settings';
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
import { unescapeHTML } from '../utils/html';
import type { Emoji } from 'pl-fe/features/emoji';
import type { Language } from 'pl-fe/features/preferences';
import type { Account } from 'pl-fe/normalizers/account';
import type { Status } from 'pl-fe/normalizers/status';
import type { APIEntity } from 'pl-fe/types/entities';
const getResetFileKey = () => Math.floor((Math.random() * 0x10000));
@ -109,7 +106,7 @@ interface Compose {
is_composing: boolean;
is_submitting: boolean;
is_uploading: boolean;
media_attachments: ImmutableList<MediaAttachment>;
media_attachments: Array<MediaAttachment>;
poll: ComposePoll | null;
privacy: string;
progress: number;
@ -119,9 +116,9 @@ interface Compose {
sensitive: boolean;
spoiler_text: string;
spoilerTextMap: Partial<Record<Language, string>>;
suggestions: ImmutableList<string>;
suggestions: Array<string> | Array<Emoji>;
suggestion_token: string | null;
tagHistory: ImmutableList<string>;
tagHistory: Array<string>;
text: string;
textMap: Partial<Record<Language, string>>;
to: Array<string>;
@ -149,7 +146,7 @@ const newCompose = (params: Partial<Compose> = {}): Compose => ({
is_composing: false,
is_submitting: false,
is_uploading: false,
media_attachments: ImmutableList<MediaAttachment>(),
media_attachments: [],
poll: null,
privacy: 'public',
progress: 0,
@ -159,9 +156,9 @@ const newCompose = (params: Partial<Compose> = {}): Compose => ({
sensitive: false,
spoiler_text: '',
spoilerTextMap: {},
suggestions: ImmutableList<string>(),
suggestions: [],
suggestion_token: null,
tagHistory: ImmutableList<string>(),
tagHistory: [],
text: '',
textMap: {},
to: [],
@ -204,7 +201,7 @@ const statusToMentionsAccountIdsArray = (status: Pick<Status, 'mentions' | 'acco
};
const appendMedia = (compose: Compose, media: MediaAttachment, defaultSensitive?: boolean) => {
const prevSize = compose.media_attachments.size;
const prevSize = compose.media_attachments.length;
compose.media_attachments.push(media);
compose.is_uploading = false;
@ -217,7 +214,7 @@ const appendMedia = (compose: Compose, media: MediaAttachment, defaultSensitive?
};
const removeMedia = (compose: Compose, mediaId: string) => {
const prevSize = compose.media_attachments.size;
const prevSize = compose.media_attachments.length;
compose.media_attachments = compose.media_attachments.filter(item => item.id !== mediaId);
compose.idempotencyKey = crypto.randomUUID();
@ -235,17 +232,17 @@ const insertSuggestion = (compose: Compose, position: number, token: string | nu
compose.poll.options[path[2]] = updateText(compose.poll.options[path[2]]);
}
compose.suggestion_token = null;
compose.suggestions = ImmutableList();
compose.suggestions = [];
compose.idempotencyKey = crypto.randomUUID();
};
const updateSuggestionTags = (compose: Compose, token: string, tags: Tag[]) => {
const prefix = token.slice(1);
compose.suggestions = ImmutableList(tags
compose.suggestions = tags
.filter((tag) => tag.name.toLowerCase().startsWith(prefix.toLowerCase()))
.slice(0, 4)
.map((tag) => '#' + tag.name));
.map((tag) => '#' + tag.name);
compose.suggestion_token = token;
};
@ -299,7 +296,7 @@ const importAccount = (compose: Compose, account: CredentialAccount) => {
if (settings.defaultPrivacy) compose.privacy = settings.defaultPrivacy;
if (settings.defaultContentType) compose.content_type = settings.defaultContentType;
compose.tagHistory = ImmutableList(tagHistory.get(account.id));
compose.tagHistory = tagHistory.get(account.id);
};
// const updateSetting = (compose: Compose, path: string[], value: string) => {
@ -493,12 +490,12 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_SUGGESTIONS_CLEAR:
return updateCompose(state, action.composeId, compose => {
compose.suggestions = compose.suggestions.clear();
compose.suggestions = [];
compose.suggestion_token = null;
});
case COMPOSE_SUGGESTIONS_READY:
return updateCompose(state, action.composeId, compose => {
compose.suggestions = ImmutableList(action.accounts ? action.accounts.map((item: APIEntity) => item.id) : action.emojis);
compose.suggestions = action.accounts ? action.accounts.map((item) => item.id) : action.emojis || [];
compose.suggestion_token = action.token;
});
case COMPOSE_SUGGESTION_SELECT:
@ -507,7 +504,7 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
return updateCompose(state, action.composeId, compose => updateSuggestionTags(compose, action.token, action.tags));
case COMPOSE_TAG_HISTORY_UPDATE:
return updateCompose(state, action.composeId, compose => {
compose.tagHistory = ImmutableList(action.tags) as ImmutableList<string>;
compose.tagHistory = action.tags;
});
case TIMELINE_DELETE:
return updateCompose(state, 'compose-modal', compose => {
@ -550,9 +547,9 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
compose.group_id = action.status.group_id;
if (action.v?.software === PLEROMA && action.withRedraft && hasIntegerMediaIds(action.status)) {
compose.media_attachments = ImmutableList();
compose.media_attachments = [];
} else {
compose.media_attachments = ImmutableList(action.status.media_attachments);
compose.media_attachments = action.status.media_attachments;
}
if (action.status.spoiler_text.length > 0) {
@ -661,10 +658,10 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
case COMPOSE_CHANGE_MEDIA_ORDER:
return updateCompose(state, action.composeId, compose => {
const indexA = compose.media_attachments.findIndex(x => x.id === action.a);
const moveItem = compose.media_attachments.get(indexA)!;
const moveItem = compose.media_attachments[indexA];
const indexB = compose.media_attachments.findIndex(x => x.id === action.b);
return compose.media_attachments.splice(indexA, 1).splice(indexB, 0, moveItem);
compose.media_attachments = compose.media_attachments.splice(indexA, 1).splice(indexB, 0, moveItem);
});
case COMPOSE_ADD_SUGGESTED_QUOTE:
return updateCompose(state, action.composeId, compose => {