Add clear action to discard composer content
When pressing the Drafts button with content in the composer, the user can choose to discard. This now properly clears the composer by dispatching a 'clear' action that resets to an empty state. - Add 'clear' action type to ComposerAction - Implement clear case in composerReducer (resets to single empty post) - Add handleClearComposer callback in Composer.tsx - Pass onDiscard prop through ComposerTopBar to DraftsButton - Call onDiscard before opening drafts dialog on discard Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -388,6 +388,11 @@ export const ComposePost = ({
|
||||
return true
|
||||
}, [thread.posts])
|
||||
|
||||
// Clear the composer (discard current content)
|
||||
const handleClearComposer = React.useCallback(() => {
|
||||
composerDispatch({type: 'clear'})
|
||||
}, [composerDispatch])
|
||||
|
||||
const insets = useSafeAreaInsets()
|
||||
const viewStyles = useMemo(
|
||||
() => ({
|
||||
@@ -814,6 +819,7 @@ export const ComposePost = ({
|
||||
onPublish={onPressPublish}
|
||||
onSelectDraft={handleSelectDraft}
|
||||
onSaveDraft={saveCurrentDraft}
|
||||
onDiscard={handleClearComposer}
|
||||
isEmpty={isComposerEmpty}>
|
||||
{missingAltError && <AltTextReminder error={missingAltError} />}
|
||||
<ErrorBanner
|
||||
@@ -998,7 +1004,7 @@ let ComposerPost = React.memo(function ComposerPost({
|
||||
a.mb_sm,
|
||||
!isActive && isLastPost && a.mb_lg,
|
||||
!isActive && styles.inactivePost,
|
||||
isTextOnly && IS_NATIVE && a.flex_grow,
|
||||
isTextOnly && isLastPost && IS_NATIVE && a.flex_grow,
|
||||
]}>
|
||||
<View style={[a.flex_row, IS_NATIVE && a.flex_1]}>
|
||||
<UserAvatar
|
||||
@@ -1104,6 +1110,7 @@ function ComposerTopBar({
|
||||
onPublish,
|
||||
onSelectDraft,
|
||||
onSaveDraft,
|
||||
onDiscard,
|
||||
isEmpty,
|
||||
topBarAnimatedStyle,
|
||||
children,
|
||||
@@ -1118,6 +1125,7 @@ function ComposerTopBar({
|
||||
onPublish: () => void
|
||||
onSelectDraft: (draft: StoredDraft) => void
|
||||
onSaveDraft: () => Promise<void>
|
||||
onDiscard: () => void
|
||||
isEmpty: boolean
|
||||
topBarAnimatedStyle: StyleProp<ViewStyle>
|
||||
children?: React.ReactNode
|
||||
@@ -1148,6 +1156,7 @@ function ComposerTopBar({
|
||||
<DraftsButton
|
||||
onSelectDraft={onSelectDraft}
|
||||
onSaveDraft={onSaveDraft}
|
||||
onDiscard={onDiscard}
|
||||
isEmpty={isEmpty}
|
||||
/>
|
||||
{isPublishing ? (
|
||||
|
||||
@@ -11,10 +11,12 @@ import {DraftsListDialog} from './DraftsListDialog'
|
||||
export function DraftsButton({
|
||||
onSelectDraft,
|
||||
onSaveDraft,
|
||||
onDiscard,
|
||||
isEmpty,
|
||||
}: {
|
||||
onSelectDraft: (draft: StoredDraft) => void
|
||||
onSaveDraft: () => Promise<void>
|
||||
onDiscard: () => void
|
||||
isEmpty: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
@@ -38,6 +40,7 @@ export function DraftsButton({
|
||||
}
|
||||
|
||||
const handleDiscardAndOpen = () => {
|
||||
onDiscard()
|
||||
draftsDialogControl.open()
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,9 @@ export type ComposerAction =
|
||||
/** Map of localId -> loaded media path/URL */
|
||||
loadedMedia: Map<string, string>
|
||||
}
|
||||
| {
|
||||
type: 'clear'
|
||||
}
|
||||
|
||||
export const MAX_IMAGES = 4
|
||||
|
||||
@@ -309,6 +312,31 @@ export function composerReducer(
|
||||
},
|
||||
}
|
||||
}
|
||||
case 'clear': {
|
||||
return {
|
||||
activePostIndex: 0,
|
||||
mutableNeedsFocusActive: true,
|
||||
draftId: undefined,
|
||||
thread: {
|
||||
posts: [
|
||||
{
|
||||
id: nanoid(),
|
||||
richtext: new RichText({text: ''}),
|
||||
shortenedGraphemeLength: 0,
|
||||
labels: [],
|
||||
embed: {
|
||||
quote: undefined,
|
||||
media: undefined,
|
||||
link: undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
// Keep the user's default interaction settings
|
||||
postgate: state.thread.postgate,
|
||||
threadgate: state.thread.threadgate,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user