From 42fc4a99e68e7ce6834bd1548e494108e8e39c90 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Mon, 31 Mar 2025 19:36:28 -0500 Subject: [PATCH] Bump sentry (cherry picked from commit 34fc98e752e1f08aca2d15cbb1c6c702583b6e59) --- assets/misc/neue-char.jpg | Bin 0 -> 21664 bytes src/components/dialogs/nuxs/NeueChar.tsx | 134 +++++++++++++++++++++++ src/components/dialogs/nuxs/index.tsx | 19 +++- src/state/queries/nuxs/definitions.ts | 20 +++- src/view/com/composer/Composer.tsx | 59 ++++++---- 5 files changed, 199 insertions(+), 33 deletions(-) create mode 100644 assets/misc/neue-char.jpg create mode 100644 src/components/dialogs/nuxs/NeueChar.tsx diff --git a/assets/misc/neue-char.jpg b/assets/misc/neue-char.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf15ee1d8f31e7804c2f0782cc9744a6904dc2cd GIT binary patch literal 21664 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 { + nuxDialogs.dismissActiveNux() + }, [nuxDialogs]) + + return ( + + + { + setHeight(e.nativeEvent.layout.height) + }} + style={[ + a.absolute, + a.inset_0, + a.overflow_hidden, + { + backgroundColor: 'black', + bottom: 'auto', + paddingTop: gtMobile ? '42%' : '60%', + borderTopLeftRadius: a.rounded_md.borderRadius, + borderTopRightRadius: a.rounded_md.borderRadius, + }, + ]}> + {_( + + + + + + + New character limit ๐ŸŽ‰ + + + + Weโ€™re listening to your feedback and updating the character count. + Posts are now limited to 299 characters! + + + + + For a limited time โ€” just today ;) + + + {!gtMobile && ( + + + + )} + + + + + + ) +} diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx index 10cae887ba..08600634ab 100644 --- a/src/components/dialogs/nuxs/index.tsx +++ b/src/components/dialogs/nuxs/index.tsx @@ -1,16 +1,17 @@ import React from 'react' -import {AppBskyActorDefs} from '@atproto/api' +import {type AppBskyActorDefs} from '@atproto/api' import {useGate} from '#/lib/statsig/statsig' import {logger} from '#/logger' import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs' import { usePreferencesQuery, - UsePreferencesQueryResponse, + type UsePreferencesQueryResponse, } from '#/state/queries/preferences' import {useProfileQuery} from '#/state/queries/profile' -import {SessionAccount, useSession} from '#/state/session' +import {type SessionAccount, useSession} from '#/state/session' import {useOnboardingState} from '#/state/shell' +import {isEnabled, NeueChar} from '#/components/dialogs/nuxs/NeueChar' /* * NUXs */ @@ -29,7 +30,12 @@ const queuedNuxs: { currentProfile: AppBskyActorDefs.ProfileViewDetailed preferences: UsePreferencesQueryResponse }) => boolean -}[] = [] +}[] = [ + { + id: Nux.NeueChar, + enabled: isEnabled, + }, +] const Context = React.createContext({ activeNux: undefined, @@ -102,7 +108,7 @@ function Inner({ } React.useEffect(() => { - if (snoozed) return + // if (snoozed) return if (!nuxs) return for (const {id, enabled} of queuedNuxs) { @@ -110,7 +116,7 @@ function Inner({ // check if completed first if (nux && nux.completed) { - continue + // continue } // then check gate (track exposure) @@ -163,6 +169,7 @@ function Inner({ return ( {/*For example, activeNux === Nux.NeueTypography && */} + {activeNux === Nux.NeueChar && } ) } diff --git a/src/state/queries/nuxs/definitions.ts b/src/state/queries/nuxs/definitions.ts index 8166602c8a..c9f4cdbe3c 100644 --- a/src/state/queries/nuxs/definitions.ts +++ b/src/state/queries/nuxs/definitions.ts @@ -1,18 +1,26 @@ -import zod from 'zod' +import type zod from 'zod' -import {BaseNux} from '#/state/queries/nuxs/types' +import {type BaseNux} from '#/state/queries/nuxs/types' export enum Nux { NeueTypography = 'NeueTypography', + NeueChar = 'NeueChar', } export const nuxNames = new Set(Object.values(Nux)) -export type AppNux = BaseNux<{ - id: Nux.NeueTypography - data: undefined -}> +export type AppNux = BaseNux< + | { + id: Nux.NeueTypography + data: undefined + } + | { + id: Nux.NeueChar + data: undefined + } +> export const NuxSchemas: Record | undefined> = { [Nux.NeueTypography]: undefined, + [Nux.NeueChar]: undefined, } diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index e8fe1a7ce7..36a37a5317 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -12,17 +12,17 @@ import { BackHandler, Keyboard, KeyboardAvoidingView, - LayoutChangeEvent, + type LayoutChangeEvent, ScrollView, - StyleProp, + type StyleProp, StyleSheet, View, - ViewStyle, + type ViewStyle, } from 'react-native' // @ts-expect-error no type definition import ProgressCircle from 'react-native-progress/Circle' import Animated, { - AnimatedRef, + type AnimatedRef, Easing, FadeIn, FadeOut, @@ -41,12 +41,12 @@ import Animated, { ZoomOut, } from 'react-native-reanimated' import {useSafeAreaInsets} from 'react-native-safe-area-context' -import {ImagePickerAsset} from 'expo-image-picker' +import {type ImagePickerAsset} from 'expo-image-picker' import { AppBskyFeedDefs, - AppBskyFeedGetPostThread, - BskyAgent, - RichText, + type AppBskyFeedGetPostThread, + type BskyAgent, + type RichText, } from '@atproto/api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg, Trans} from '@lingui/macro' @@ -59,7 +59,7 @@ import {until} from '#/lib/async/until' import { MAX_GRAPHEME_LENGTH, SUPPORTED_MIME_TYPES, - SupportedMimeTypes, + type SupportedMimeTypes, } from '#/lib/constants' import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' import {useEmail} from '#/lib/hooks/useEmail' @@ -75,7 +75,7 @@ import {logger} from '#/logger' import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection' import {useDialogStateControlContext} from '#/state/dialogs' import {emitPostCreated} from '#/state/events' -import {ComposerImage, pasteImage} from '#/state/gallery' +import {type ComposerImage, pasteImage} from '#/state/gallery' import {useModalControls} from '#/state/modals' import {useRequireAltTextEnabled} from '#/state/preferences' import { @@ -85,10 +85,10 @@ import { } from '#/state/preferences/languages' import {usePreferencesQuery} from '#/state/queries/preferences' import {useProfileQuery} from '#/state/queries/profile' -import {Gif} from '#/state/queries/tenor' +import {type Gif} from '#/state/queries/tenor' import {useAgent, useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' -import {ComposerOpts} from '#/state/shell/composer' +import {type ComposerOpts} from '#/state/shell/composer' import {CharProgress} from '#/view/com/composer/char-progress/CharProgress' import {ComposerReplyTo} from '#/view/com/composer/ComposerReplyTo' import { @@ -105,7 +105,10 @@ import {SelectLangBtn} from '#/view/com/composer/select-language/SelectLangBtn' import {SuggestedLanguage} from '#/view/com/composer/select-language/SuggestedLanguage' // TODO: Prevent naming components that coincide with RN primitives // due to linting false positives -import {TextInput, TextInputRef} from '#/view/com/composer/text-input/TextInput' +import { + TextInput, + type TextInputRef, +} from '#/view/com/composer/text-input/TextInput' import {ThreadgateBtn} from '#/view/com/composer/threadgate/ThreadgateBtn' import {SelectVideoBtn} from '#/view/com/composer/videos/SelectVideoBtn' import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog' @@ -118,6 +121,7 @@ import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, native, useTheme} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' +import {isEnabled} from '#/components/dialogs/nuxs/NeueChar' import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' @@ -126,16 +130,21 @@ import * as Prompt from '#/components/Prompt' import {Text as NewText} from '#/components/Typography' import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' import { - ComposerAction, + type ComposerAction, composerReducer, createComposerState, - EmbedDraft, + type EmbedDraft, MAX_IMAGES, - PostAction, - PostDraft, - ThreadDraft, + type PostAction, + type PostDraft, + type ThreadDraft, } from './state/composer' -import {NO_VIDEO, NoVideoState, processVideo, VideoState} from './state/video' +import { + NO_VIDEO, + type NoVideoState, + processVideo, + type VideoState, +} from './state/video' import {getVideoMetadata} from './videos/pickVideo' import {clearThumbnailCache} from './videos/VideoTranscodeBackdrop' @@ -171,6 +180,7 @@ export const ComposePost = ({ const {closeAllDialogs} = useDialogStateControlContext() const {closeAllModals} = useModalControls() const {data: preferences} = usePreferencesQuery() + const MAX_GRAPHEMES = isEnabled() ? 299 : MAX_GRAPHEME_LENGTH const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true}) const [isPublishing, setIsPublishing] = useState(false) @@ -360,7 +370,7 @@ export const ComposePost = ({ !missingAltError && thread.posts.every( post => - post.shortenedGraphemeLength <= MAX_GRAPHEME_LENGTH && + post.shortenedGraphemeLength <= MAX_GRAPHEMES && !isEmptyPost(post) && !( post.embed.media?.type === 'video' && @@ -605,6 +615,7 @@ export const ComposePost = ({ type: 'add_post', }) }} + maxGraphemeLength={MAX_GRAPHEMES} /> ) @@ -678,6 +689,7 @@ export const ComposePost = ({ onClearVideo={clearVideo} onPublish={onComposerPostPublish} onError={setError} + maxGraphemeLength={MAX_GRAPHEMES} /> {isWebFooterSticky && post.id === activePost.id && ( {footer} @@ -715,6 +727,7 @@ let ComposerPost = React.memo(function ComposerPost({ onSelectVideo, onError, onPublish, + maxGraphemeLength, }: { post: PostDraft dispatch: (action: ComposerAction) => void @@ -729,6 +742,7 @@ let ComposerPost = React.memo(function ComposerPost({ onSelectVideo: (postId: string, asset: ImagePickerAsset) => void onError: (error: string) => void onPublish: (richtext: RichText) => void + maxGraphemeLength: number }) { const {currentAccount} = useSession() const currentDid = currentAccount!.did @@ -831,7 +845,7 @@ let ComposerPost = React.memo(function ComposerPost({ accessible={true} accessibilityLabel={_(msg`Write post`)} accessibilityHint={_( - msg`Compose posts up to ${MAX_GRAPHEME_LENGTH} characters in length`, + msg`Compose posts up to ${maxGraphemeLength} characters in length`, )} /> @@ -1170,6 +1184,7 @@ function ComposerFooter({ onError, onSelectVideo, onAddPost, + maxGraphemeLength, }: { post: PostDraft dispatch: (action: PostAction) => void @@ -1178,6 +1193,7 @@ function ComposerFooter({ onError: (error: string) => void onSelectVideo: (postId: string, asset: ImagePickerAsset) => void onAddPost: () => void + maxGraphemeLength: number }) { const t = useTheme() const {_} = useLingui() @@ -1270,6 +1286,7 @@ function ComposerFooter({ )}