Bluesky app fork with some witchin' additions 💫

[Drafts] NUX (#9825)

* drafts NUX

* use "Drafts" string

* change button copy

authored by samuel.fm and committed by

GitHub bb6ce831 3abc3618

+166 -6
assets/images/drafts_announcement_nux.webp

This is a binary file and will not be displayed.

+154
src/components/dialogs/nuxs/DraftsAnnouncement.tsx
··· 1 + import {useCallback} from 'react' 2 + import {View} from 'react-native' 3 + import {Image} from 'expo-image' 4 + import {LinearGradient} from 'expo-linear-gradient' 5 + import {msg, Trans} from '@lingui/macro' 6 + import {useLingui} from '@lingui/react' 7 + 8 + import {atoms as a, useTheme, web} from '#/alf' 9 + import {Button, ButtonText} from '#/components/Button' 10 + import * as Dialog from '#/components/Dialog' 11 + import {useNuxDialogContext} from '#/components/dialogs/nuxs' 12 + import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle' 13 + import {Text} from '#/components/Typography' 14 + import {IS_E2E, IS_NATIVE, IS_WEB} from '#/env' 15 + import {createIsEnabledCheck, isExistingUserAsOf} from './utils' 16 + 17 + export const enabled = createIsEnabledCheck(props => { 18 + return ( 19 + !IS_E2E && 20 + IS_NATIVE && 21 + isExistingUserAsOf( 22 + '2026-02-05T00:00:00.000Z', 23 + props.currentProfile.createdAt, 24 + ) 25 + ) 26 + }) 27 + 28 + export function DraftsAnnouncement() { 29 + const t = useTheme() 30 + const {_} = useLingui() 31 + const nuxDialogs = useNuxDialogContext() 32 + const control = Dialog.useDialogControl() 33 + 34 + Dialog.useAutoOpen(control) 35 + 36 + const onClose = useCallback(() => { 37 + nuxDialogs.dismissActiveNux() 38 + }, [nuxDialogs]) 39 + 40 + return ( 41 + <Dialog.Outer 42 + control={control} 43 + onClose={onClose} 44 + nativeOptions={{preventExpansion: true}}> 45 + <Dialog.Handle fill={t.palette.primary_400} /> 46 + 47 + <Dialog.ScrollableInner 48 + label={_(msg`Introducing drafts`)} 49 + style={[web({maxWidth: 440})]} 50 + contentContainerStyle={[ 51 + { 52 + paddingTop: 0, 53 + paddingLeft: 0, 54 + paddingRight: 0, 55 + }, 56 + ]}> 57 + <View 58 + style={[ 59 + a.align_center, 60 + a.overflow_hidden, 61 + { 62 + paddingTop: IS_WEB ? 24 : 40, 63 + borderTopLeftRadius: a.rounded_md.borderRadius, 64 + borderTopRightRadius: a.rounded_md.borderRadius, 65 + }, 66 + ]}> 67 + <LinearGradient 68 + colors={[t.palette.primary_100, t.palette.primary_200]} 69 + locations={[0, 1]} 70 + start={{x: 0, y: 0}} 71 + end={{x: 0, y: 1}} 72 + style={[a.absolute, a.inset_0]} 73 + /> 74 + <View 75 + style={[a.flex_row, a.align_center, a.gap_xs, {marginBottom: -12}]}> 76 + <SparkleIcon fill={t.palette.primary_800} size="sm" /> 77 + <Text 78 + style={[ 79 + a.font_semi_bold, 80 + { 81 + color: t.palette.primary_800, 82 + }, 83 + ]}> 84 + <Trans>New Feature</Trans> 85 + </Text> 86 + </View> 87 + <Image 88 + accessibilityIgnoresInvertColors 89 + source={require('../../../../assets/images/drafts_announcement_nux.webp')} 90 + style={[ 91 + a.w_full, 92 + { 93 + aspectRatio: 393 / 226, 94 + }, 95 + ]} 96 + alt={_( 97 + msg({ 98 + message: `A screenshot of a the post composer with a new button next to the post button that says "Drafts", with a rainbow firework effect. Below, the text in the composer reads "Hey, did you hear the news? Bluesky has drafts now???".`, 99 + comment: 100 + 'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.', 101 + }), 102 + )} 103 + /> 104 + </View> 105 + <View style={[a.align_center, a.px_xl, a.pt_xl, a.gap_2xl, a.pb_sm]}> 106 + <View style={[a.gap_sm, a.align_center]}> 107 + <Text 108 + style={[ 109 + a.text_3xl, 110 + a.leading_tight, 111 + a.font_bold, 112 + a.text_center, 113 + { 114 + fontSize: IS_WEB ? 28 : 32, 115 + maxWidth: 300, 116 + }, 117 + ]}> 118 + <Trans>Drafts</Trans> 119 + </Text> 120 + <Text 121 + style={[ 122 + a.text_md, 123 + a.leading_snug, 124 + a.text_center, 125 + { 126 + maxWidth: 340, 127 + }, 128 + ]}> 129 + <Trans> 130 + Not ready to hit post? Keep your best ideas in Drafts until the 131 + timing is just right. 132 + </Trans> 133 + </Text> 134 + </View> 135 + 136 + {!IS_WEB && ( 137 + <Button 138 + label={_(msg`Close`)} 139 + size="large" 140 + color="primary" 141 + onPress={() => control.close()} 142 + style={[a.w_full]}> 143 + <ButtonText> 144 + <Trans>Finally!</Trans> 145 + </ButtonText> 146 + </Button> 147 + )} 148 + </View> 149 + 150 + <Dialog.Close /> 151 + </Dialog.ScrollableInner> 152 + </Dialog.Outer> 153 + ) 154 + }
+6 -6
src/components/dialogs/nuxs/index.tsx
··· 19 19 import {type SessionAccount, useSession} from '#/state/session' 20 20 import {useOnboardingState} from '#/state/shell' 21 21 import { 22 - enabled as isLiveNowBetaDialogEnabled, 23 - LiveNowBetaDialog, 24 - } from '#/components/dialogs/nuxs/LiveNowBetaDialog' 22 + DraftsAnnouncement, 23 + enabled as isDraftsAnnouncementEnabled, 24 + } from '#/components/dialogs/nuxs/DraftsAnnouncement' 25 25 import {isSnoozed, snooze, unsnooze} from '#/components/dialogs/nuxs/snoozing' 26 26 import {type EnabledCheckProps} from '#/components/dialogs/nuxs/utils' 27 27 import {useAnalytics} from '#/analytics' ··· 37 37 enabled?: (props: EnabledCheckProps) => boolean 38 38 }[] = [ 39 39 { 40 - id: Nux.LiveNowBetaDialog, 41 - enabled: isLiveNowBetaDialogEnabled, 40 + id: Nux.DraftsAnnouncement, 41 + enabled: isDraftsAnnouncementEnabled, 42 42 }, 43 43 ] 44 44 ··· 186 186 return ( 187 187 <Context.Provider value={ctx}> 188 188 {/*For example, activeNux === Nux.NeueTypography && <NeueTypography />*/} 189 - {activeNux === Nux.LiveNowBetaDialog && <LiveNowBetaDialog />} 189 + {activeNux === Nux.DraftsAnnouncement && <DraftsAnnouncement />} 190 190 </Context.Provider> 191 191 ) 192 192 }
+6
src/state/queries/nuxs/definitions.ts
··· 14 14 FindContactsDismissibleBanner = 'FindContactsDismissibleBanner', 15 15 LiveNowBetaDialog = 'LiveNowBetaDialog', 16 16 LiveNowBetaNudge = 'LiveNowBetaNudge', 17 + DraftsAnnouncement = 'DraftsAnnouncement', 17 18 18 19 /* 19 20 * Blocking announcements. New IDs are required for each new announcement. ··· 72 73 id: Nux.LiveNowBetaNudge 73 74 data: undefined 74 75 } 76 + | { 77 + id: Nux.DraftsAnnouncement 78 + data: undefined 79 + } 75 80 > 76 81 77 82 export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = { ··· 87 92 [Nux.FindContactsDismissibleBanner]: undefined, 88 93 [Nux.LiveNowBetaDialog]: undefined, 89 94 [Nux.LiveNowBetaNudge]: undefined, 95 + [Nux.DraftsAnnouncement]: undefined, 90 96 }