Fix draft button behaviour when publishing, tweak buttons

This commit is contained in:
Samuel Newman
2026-01-16 13:36:22 +02:00
parent e5b700a3d2
commit ad848c0000
+23 -34
View File
@@ -50,7 +50,6 @@ import {
type BskyAgent, type BskyAgent,
type RichText, type RichText,
} from '@atproto/api' } from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, plural, Trans} from '@lingui/macro' import {msg, plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native' import {useNavigation} from '@react-navigation/native'
@@ -68,7 +67,6 @@ import {
} from '#/lib/constants' } from '#/lib/constants'
import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible' import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {mimeToExt} from '#/lib/media/video/util' import {mimeToExt} from '#/lib/media/video/util'
import {type NavigationProp} from '#/lib/routes/types' import {type NavigationProp} from '#/lib/routes/types'
@@ -117,9 +115,9 @@ import {ThreadgateBtn} from '#/view/com/composer/threadgate/ThreadgateBtn'
import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog' import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog'
import {VideoPreview} from '#/view/com/composer/videos/VideoPreview' import {VideoPreview} from '#/view/com/composer/videos/VideoPreview'
import {VideoTranscodeProgress} from '#/view/com/composer/videos/VideoTranscodeProgress' import {VideoTranscodeProgress} from '#/view/com/composer/videos/VideoTranscodeProgress'
import {Text} from '#/view/com/util/text/Text'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, native, useTheme, web} from '#/alf' import {atoms as a, native, useTheme, web} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo'
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmileIcon} from '#/components/icons/Emoji' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmileIcon} from '#/components/icons/Emoji'
@@ -128,7 +126,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Ti
import {LazyQuoteEmbed} from '#/components/Post/Embed/LazyQuoteEmbed' import {LazyQuoteEmbed} from '#/components/Post/Embed/LazyQuoteEmbed'
import * as Prompt from '#/components/Prompt' import * as Prompt from '#/components/Prompt'
import * as Toast from '#/components/Toast' import * as Toast from '#/components/Toast'
import {Text as NewText} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import {IS_ANDROID, IS_IOS, IS_NATIVE, IS_WEB} from '#/env' import {IS_ANDROID, IS_IOS, IS_NATIVE, IS_WEB} from '#/env'
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
@@ -1174,7 +1172,7 @@ function ComposerTopBar({
topBarAnimatedStyle: StyleProp<ViewStyle> topBarAnimatedStyle: StyleProp<ViewStyle>
children?: React.ReactNode children?: React.ReactNode
}) { }) {
const pal = usePalette('default') const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
return ( return (
<Animated.View <Animated.View
@@ -1187,7 +1185,8 @@ function ComposerTopBar({
color="primary" color="primary"
shape="default" shape="default"
size="small" size="small"
style={[a.rounded_full, a.py_sm, {paddingLeft: 7, paddingRight: 7}]} style={[{paddingLeft: 7, paddingRight: 7}]}
hoverStyle={[a.bg_transparent, {opacity: 0.5}]}
onPress={onCancel} onPress={onCancel}
accessibilityHint={_( accessibilityHint={_(
msg`Closes post composer and discards post draft`, msg`Closes post composer and discards post draft`,
@@ -1197,7 +1196,15 @@ function ComposerTopBar({
</ButtonText> </ButtonText>
</Button> </Button>
<View style={a.flex_1} /> <View style={a.flex_1} />
{/* Drafts not supported for replies */} {isPublishing ? (
<>
<Text style={[t.atoms.text_contrast_low]}>{publishingStage}</Text>
<View style={styles.postBtn}>
<ActivityIndicator />
</View>
</>
) : (
<>
{!isReply && ( {!isReply && (
<DraftsButton <DraftsButton
onSelectDraft={onSelectDraft} onSelectDraft={onSelectDraft}
@@ -1208,14 +1215,6 @@ function ComposerTopBar({
isEditingDraft={isEditingDraft} isEditingDraft={isEditingDraft}
/> />
)} )}
{isPublishing ? (
<>
<Text style={pal.textLight}>{publishingStage}</Text>
<View style={styles.postBtn}>
<ActivityIndicator />
</View>
</>
) : (
<Button <Button
testID="composerPublishBtn" testID="composerPublishBtn"
label={ label={
@@ -1251,11 +1250,8 @@ function ComposerTopBar({
}), }),
) )
} }
variant="solid"
color="primary" color="primary"
shape="default"
size="small" size="small"
style={[a.rounded_full, a.py_sm]}
onPress={onPublish} onPress={onPublish}
disabled={!canPost || isPublishQueued}> disabled={!canPost || isPublishQueued}>
<ButtonText style={[a.text_md]}> <ButtonText style={[a.text_md]}>
@@ -1268,6 +1264,7 @@ function ComposerTopBar({
)} )}
</ButtonText> </ButtonText>
</Button> </Button>
</>
)} )}
</View> </View>
{children} {children}
@@ -1276,18 +1273,10 @@ function ComposerTopBar({
} }
function AltTextReminder({error}: {error: string}) { function AltTextReminder({error}: {error: string}) {
const pal = usePalette('default')
return ( return (
<View style={[styles.reminderLine, pal.viewLight]}> <Admonition type="error" style={[a.mt_2xs, a.mb_sm, a.mx_lg]}>
<View style={styles.errorIcon}> {error}
<FontAwesomeIcon </Admonition>
icon="exclamation"
style={{color: colors.red4}}
size={10}
/>
</View>
<Text style={[pal.text, a.flex_1]}>{error}</Text>
</View>
) )
} }
@@ -1954,9 +1943,9 @@ function ErrorBanner({
]}> ]}>
<View style={[a.relative, a.flex_row, a.gap_sm, {paddingRight: 48}]}> <View style={[a.relative, a.flex_row, a.gap_sm, {paddingRight: 48}]}>
<CircleInfoIcon fill={t.palette.negative_400} /> <CircleInfoIcon fill={t.palette.negative_400} />
<NewText style={[a.flex_1, a.leading_snug, {paddingTop: 1}]}> <Text style={[a.flex_1, a.leading_snug, {paddingTop: 1}]}>
{error} {error}
</NewText> </Text>
<Button <Button
label={_(msg`Dismiss error`)} label={_(msg`Dismiss error`)}
size="tiny" size="tiny"
@@ -1969,7 +1958,7 @@ function ErrorBanner({
</Button> </Button>
</View> </View>
{videoError && videoState.jobId && ( {videoError && videoState.jobId && (
<NewText <Text
style={[ style={[
{paddingLeft: 28}, {paddingLeft: 28},
a.text_xs, a.text_xs,
@@ -1978,7 +1967,7 @@ function ErrorBanner({
t.atoms.text_contrast_low, t.atoms.text_contrast_low,
]}> ]}>
<Trans>Job ID: {videoState.jobId}</Trans> <Trans>Job ID: {videoState.jobId}</Trans>
</NewText> </Text>
)} )}
</View> </View>
</Animated.View> </Animated.View>
@@ -2066,7 +2055,7 @@ function VideoUploadToolbar({state}: {state: VideoState}) {
progress={wheelProgress} progress={wheelProgress}
/> />
</Animated.View> </Animated.View>
<NewText style={[a.font_semi_bold, a.ml_sm]}>{text}</NewText> <Text style={[a.font_semi_bold, a.ml_sm]}>{text}</Text>
</ToolbarWrapper> </ToolbarWrapper>
) )
} }