nicolium: add a toggle for auto-updating post preview

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2026-03-17 21:36:09 +01:00
parent 1865c40747
commit 51ce74d7fd
4 changed files with 30 additions and 3 deletions

View File

@ -12,6 +12,7 @@ import StatusReplyMentions from '@/components/statuses/status-reply-mentions';
import Icon from '@/components/ui/icon';
import IconButton from '@/components/ui/icon-button';
import Text from '@/components/ui/text';
import Toggle from '@/components/ui/toggle';
import { useCompose, useComposeActions } from '@/stores/compose';
import type { NormalizedStatus as Status } from '@/normalizers/status';
@ -32,7 +33,9 @@ const PreviewComposeContainer: React.FC<IQuotedStatusContainer> = ({ composeId }
const { updateCompose } = useComposeActions();
const intl = useIntl();
const previewedStatus = useCompose(composeId).preview as unknown as Status;
const compose = useCompose(composeId);
const autoUpdate = compose.previewAutoUpdate;
const previewedStatus = compose.preview as unknown as Status;
const handleClose = () => {
updateCompose(composeId, (draft) => {
@ -40,6 +43,12 @@ const PreviewComposeContainer: React.FC<IQuotedStatusContainer> = ({ composeId }
});
};
const handleSwitchAutoUpdate: React.ChangeEventHandler<HTMLInputElement> = (event) => {
updateCompose(composeId, (draft) => {
draft.previewAutoUpdate = event.target.checked;
});
};
const status = previewedStatus ?? null;
if (!status) {
@ -58,6 +67,10 @@ const PreviewComposeContainer: React.FC<IQuotedStatusContainer> = ({ composeId }
<FormattedMessage id='compose_form.preview_label' defaultMessage='Preview' />
</Text>
<Text theme='muted' size='sm' className='inline-flex items-center gap-1' tag='label'>
<FormattedMessage id='compose_form.preview.auto_update' defaultMessage='Auto-update' />
<Toggle size='sm' checked={autoUpdate} onChange={handleSwitchAutoUpdate} />
</Text>
<IconButton
src={require('@phosphor-icons/core/regular/x.svg')}
title={intl.formatMessage(messages.close)}

View File

@ -12,7 +12,7 @@ import { useClient } from '@/hooks/use-client';
import { useFeatures } from '@/hooks/use-features';
import { queryClient } from '@/queries/client';
import { queryKeys } from '@/queries/keys';
import { useComposeStore } from '@/stores/compose';
import { useComposeActions, useSubmitCompose } from '@/stores/compose';
import { useSettings } from '@/stores/settings';
import { getStatusIdsFromLinksInContent } from '@/utils/status';
import Purify from '@/utils/url-purify';
@ -34,7 +34,8 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
const [editor] = useLexicalComposerContext();
const features = useFeatures();
const { urlPrivacy, ignoreHashtagCasingSuggestions } = useSettings();
const { actions } = useComposeStore.getState();
const actions = useComposeActions();
const submitCompose = useSubmitCompose(composeId);
const checkUrls = useCallback(
debounce((editorState: EditorState) => {
@ -88,6 +89,13 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
[urlPrivacy.clearLinksInCompose],
);
const updatePreview = useCallback(
debounce(() => {
submitCompose({ preview: true });
}, 2000),
[],
);
const checkHashtagCasingSuggestions = useCallback(
debounce((editorState: EditorState) => {
if (ignoreHashtagCasingSuggestions) return;
@ -201,6 +209,9 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
draft.editorStateMap[draft.modifiedLanguage] = data as string;
draft.textMap[draft.modifiedLanguage] = text;
}
if (draft.preview && draft.previewAutoUpdate) {
updatePreview();
}
});
checkUrls(editorState);
checkHashtagCasingSuggestions(editorState);

View File

@ -683,6 +683,7 @@
"compose_form.poll.remove_option": "Remove this answer",
"compose_form.poll_placeholder": "Add a poll topic…",
"compose_form.preview": "Preview post",
"compose_form.preview.auto_update": "Auto-update",
"compose_form.preview.close": "Hide preview",
"compose_form.preview_label": "Preview",
"compose_form.publish": "Post",

View File

@ -136,6 +136,7 @@ interface Compose {
hashtagCasingSuggestion: string | null;
hashtagCasingSuggestionIgnored: boolean | null;
preview: Partial<BaseStatus> | null;
previewAutoUpdate: boolean;
suggestedLanguage: string | null;
showLocationPicker: boolean;
@ -191,6 +192,7 @@ const newCompose = (params: Partial<Compose> = {}): Compose => ({
hashtagCasingSuggestion: null,
hashtagCasingSuggestionIgnored: null,
preview: null,
previewAutoUpdate: false,
suggestedLanguage: null,
showLocationPicker: false,