Bump sentry
(cherry picked from commit 34fc98e752e1f08aca2d15cbb1c6c702583b6e59)
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,134 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {Image} from 'expo-image'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
|
import * as Dialog from '#/components/Dialog'
|
||||||
|
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
// midnight PDT on April 1st, 2025
|
||||||
|
export const EXPIRY = new Date('2025-04-02T07:00:00Z')
|
||||||
|
|
||||||
|
export function isEnabled() {
|
||||||
|
return new Date() < EXPIRY
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NeueChar() {
|
||||||
|
const t = useTheme()
|
||||||
|
const {_} = useLingui()
|
||||||
|
const nuxDialogs = useNuxDialogContext()
|
||||||
|
const control = Dialog.useDialogControl()
|
||||||
|
const {gtMobile} = useBreakpoints()
|
||||||
|
const [height, setHeight] = React.useState(0)
|
||||||
|
|
||||||
|
Dialog.useAutoOpen(control, 3e3)
|
||||||
|
|
||||||
|
const onClose = React.useCallback(() => {
|
||||||
|
nuxDialogs.dismissActiveNux()
|
||||||
|
}, [nuxDialogs])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.Outer control={control} onClose={onClose}>
|
||||||
|
<Dialog.Inner label={_(msg`Special announcement dialog for April Fools`)}>
|
||||||
|
<View
|
||||||
|
onLayout={e => {
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<Image
|
||||||
|
source={require('../../../../assets/misc/neue-char.jpg')}
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
{
|
||||||
|
top: -2,
|
||||||
|
left: -2,
|
||||||
|
right: -2,
|
||||||
|
bottom: -2,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
contentFit="cover"
|
||||||
|
alt={_(
|
||||||
|
msg`Fake conversation with the Bluesky app. Bluesky says: "i ain't reading all that", then "I'm happy for you though", and finally "or sorry that happened". This is in reference to a popular internet meme.`,
|
||||||
|
)}
|
||||||
|
accessibilityIgnoresInvertColors={false}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
paddingTop: height - a.pt_2xl.paddingTop, // dialog padding
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
gtMobile ? [a.py_3xl, a.pb_md] : [a.pt_xl, a.pb_sm],
|
||||||
|
a.mx_auto,
|
||||||
|
{maxWidth: 360},
|
||||||
|
]}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_3xl,
|
||||||
|
a.text_center,
|
||||||
|
a.font_heavy,
|
||||||
|
a.leading_tight,
|
||||||
|
a.mx_auto,
|
||||||
|
{maxWidth: 330},
|
||||||
|
]}>
|
||||||
|
<Trans>New character limit 🎉</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[a.text_lg, a.text_center, a.pt_md, a.leading_snug]}>
|
||||||
|
<Trans>
|
||||||
|
We’re listening to your feedback and updating the character count.
|
||||||
|
Posts are now limited to 299 characters!
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_md,
|
||||||
|
a.text_center,
|
||||||
|
a.pt_md,
|
||||||
|
a.leading_snug,
|
||||||
|
a.italic,
|
||||||
|
t.atoms.text_contrast_medium,
|
||||||
|
]}>
|
||||||
|
<Trans>For a limited time — just today ;)</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{!gtMobile && (
|
||||||
|
<View style={[a.pt_2xl]}>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Got it!`)}
|
||||||
|
onPress={onClose}
|
||||||
|
size="large"
|
||||||
|
variant="solid"
|
||||||
|
color="primary">
|
||||||
|
<ButtonText>{_(msg`Got it!`)}</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Dialog.Close />
|
||||||
|
</Dialog.Inner>
|
||||||
|
</Dialog.Outer>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {AppBskyActorDefs} from '@atproto/api'
|
import {type AppBskyActorDefs} from '@atproto/api'
|
||||||
|
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
import {useGate} from '#/lib/statsig/statsig'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs'
|
import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs'
|
||||||
import {
|
import {
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
UsePreferencesQueryResponse,
|
type UsePreferencesQueryResponse,
|
||||||
} from '#/state/queries/preferences'
|
} from '#/state/queries/preferences'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
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 {useOnboardingState} from '#/state/shell'
|
||||||
|
import {isEnabled, NeueChar} from '#/components/dialogs/nuxs/NeueChar'
|
||||||
/*
|
/*
|
||||||
* NUXs
|
* NUXs
|
||||||
*/
|
*/
|
||||||
@@ -29,7 +30,12 @@ const queuedNuxs: {
|
|||||||
currentProfile: AppBskyActorDefs.ProfileViewDetailed
|
currentProfile: AppBskyActorDefs.ProfileViewDetailed
|
||||||
preferences: UsePreferencesQueryResponse
|
preferences: UsePreferencesQueryResponse
|
||||||
}) => boolean
|
}) => boolean
|
||||||
}[] = []
|
}[] = [
|
||||||
|
{
|
||||||
|
id: Nux.NeueChar,
|
||||||
|
enabled: isEnabled,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
const Context = React.createContext<Context>({
|
const Context = React.createContext<Context>({
|
||||||
activeNux: undefined,
|
activeNux: undefined,
|
||||||
@@ -102,7 +108,7 @@ function Inner({
|
|||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (snoozed) return
|
// if (snoozed) return
|
||||||
if (!nuxs) return
|
if (!nuxs) return
|
||||||
|
|
||||||
for (const {id, enabled} of queuedNuxs) {
|
for (const {id, enabled} of queuedNuxs) {
|
||||||
@@ -110,7 +116,7 @@ function Inner({
|
|||||||
|
|
||||||
// check if completed first
|
// check if completed first
|
||||||
if (nux && nux.completed) {
|
if (nux && nux.completed) {
|
||||||
continue
|
// continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// then check gate (track exposure)
|
// then check gate (track exposure)
|
||||||
@@ -163,6 +169,7 @@ function Inner({
|
|||||||
return (
|
return (
|
||||||
<Context.Provider value={ctx}>
|
<Context.Provider value={ctx}>
|
||||||
{/*For example, activeNux === Nux.NeueTypography && <NeueTypography />*/}
|
{/*For example, activeNux === Nux.NeueTypography && <NeueTypography />*/}
|
||||||
|
{activeNux === Nux.NeueChar && <NeueChar />}
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
export enum Nux {
|
||||||
NeueTypography = 'NeueTypography',
|
NeueTypography = 'NeueTypography',
|
||||||
|
NeueChar = 'NeueChar',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nuxNames = new Set(Object.values(Nux))
|
export const nuxNames = new Set(Object.values(Nux))
|
||||||
|
|
||||||
export type AppNux = BaseNux<{
|
export type AppNux = BaseNux<
|
||||||
id: Nux.NeueTypography
|
| {
|
||||||
data: undefined
|
id: Nux.NeueTypography
|
||||||
}>
|
data: undefined
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
id: Nux.NeueChar
|
||||||
|
data: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
||||||
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||||
[Nux.NeueTypography]: undefined,
|
[Nux.NeueTypography]: undefined,
|
||||||
|
[Nux.NeueChar]: undefined,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,17 @@ import {
|
|||||||
BackHandler,
|
BackHandler,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
LayoutChangeEvent,
|
type LayoutChangeEvent,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
StyleProp,
|
type StyleProp,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
// @ts-expect-error no type definition
|
// @ts-expect-error no type definition
|
||||||
import ProgressCircle from 'react-native-progress/Circle'
|
import ProgressCircle from 'react-native-progress/Circle'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
AnimatedRef,
|
type AnimatedRef,
|
||||||
Easing,
|
Easing,
|
||||||
FadeIn,
|
FadeIn,
|
||||||
FadeOut,
|
FadeOut,
|
||||||
@@ -41,12 +41,12 @@ import Animated, {
|
|||||||
ZoomOut,
|
ZoomOut,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {ImagePickerAsset} from 'expo-image-picker'
|
import {type ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {
|
import {
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedGetPostThread,
|
type AppBskyFeedGetPostThread,
|
||||||
BskyAgent,
|
type BskyAgent,
|
||||||
RichText,
|
type RichText,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
@@ -59,7 +59,7 @@ import {until} from '#/lib/async/until'
|
|||||||
import {
|
import {
|
||||||
MAX_GRAPHEME_LENGTH,
|
MAX_GRAPHEME_LENGTH,
|
||||||
SUPPORTED_MIME_TYPES,
|
SUPPORTED_MIME_TYPES,
|
||||||
SupportedMimeTypes,
|
type SupportedMimeTypes,
|
||||||
} from '#/lib/constants'
|
} from '#/lib/constants'
|
||||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||||
import {useEmail} from '#/lib/hooks/useEmail'
|
import {useEmail} from '#/lib/hooks/useEmail'
|
||||||
@@ -75,7 +75,7 @@ import {logger} from '#/logger'
|
|||||||
import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection'
|
import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection'
|
||||||
import {useDialogStateControlContext} from '#/state/dialogs'
|
import {useDialogStateControlContext} from '#/state/dialogs'
|
||||||
import {emitPostCreated} from '#/state/events'
|
import {emitPostCreated} from '#/state/events'
|
||||||
import {ComposerImage, pasteImage} from '#/state/gallery'
|
import {type ComposerImage, pasteImage} from '#/state/gallery'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {useRequireAltTextEnabled} from '#/state/preferences'
|
import {useRequireAltTextEnabled} from '#/state/preferences'
|
||||||
import {
|
import {
|
||||||
@@ -85,10 +85,10 @@ import {
|
|||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
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 {useAgent, useSession} from '#/state/session'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
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 {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
|
||||||
import {ComposerReplyTo} from '#/view/com/composer/ComposerReplyTo'
|
import {ComposerReplyTo} from '#/view/com/composer/ComposerReplyTo'
|
||||||
import {
|
import {
|
||||||
@@ -105,7 +105,10 @@ import {SelectLangBtn} from '#/view/com/composer/select-language/SelectLangBtn'
|
|||||||
import {SuggestedLanguage} from '#/view/com/composer/select-language/SuggestedLanguage'
|
import {SuggestedLanguage} from '#/view/com/composer/select-language/SuggestedLanguage'
|
||||||
// TODO: Prevent naming components that coincide with RN primitives
|
// TODO: Prevent naming components that coincide with RN primitives
|
||||||
// due to linting false positives
|
// 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 {ThreadgateBtn} from '#/view/com/composer/threadgate/ThreadgateBtn'
|
||||||
import {SelectVideoBtn} from '#/view/com/composer/videos/SelectVideoBtn'
|
import {SelectVideoBtn} from '#/view/com/composer/videos/SelectVideoBtn'
|
||||||
import {SubtitleDialogBtn} from '#/view/com/composer/videos/SubtitleDialog'
|
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 {atoms as a, native, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {useDialogControl} from '#/components/Dialog'
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
|
import {isEnabled} from '#/components/dialogs/nuxs/NeueChar'
|
||||||
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
|
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
|
||||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
||||||
import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji'
|
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 {Text as NewText} from '#/components/Typography'
|
||||||
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
|
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
|
||||||
import {
|
import {
|
||||||
ComposerAction,
|
type ComposerAction,
|
||||||
composerReducer,
|
composerReducer,
|
||||||
createComposerState,
|
createComposerState,
|
||||||
EmbedDraft,
|
type EmbedDraft,
|
||||||
MAX_IMAGES,
|
MAX_IMAGES,
|
||||||
PostAction,
|
type PostAction,
|
||||||
PostDraft,
|
type PostDraft,
|
||||||
ThreadDraft,
|
type ThreadDraft,
|
||||||
} from './state/composer'
|
} 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 {getVideoMetadata} from './videos/pickVideo'
|
||||||
import {clearThumbnailCache} from './videos/VideoTranscodeBackdrop'
|
import {clearThumbnailCache} from './videos/VideoTranscodeBackdrop'
|
||||||
|
|
||||||
@@ -171,6 +180,7 @@ export const ComposePost = ({
|
|||||||
const {closeAllDialogs} = useDialogStateControlContext()
|
const {closeAllDialogs} = useDialogStateControlContext()
|
||||||
const {closeAllModals} = useModalControls()
|
const {closeAllModals} = useModalControls()
|
||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
|
const MAX_GRAPHEMES = isEnabled() ? 299 : MAX_GRAPHEME_LENGTH
|
||||||
|
|
||||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
||||||
const [isPublishing, setIsPublishing] = useState(false)
|
const [isPublishing, setIsPublishing] = useState(false)
|
||||||
@@ -360,7 +370,7 @@ export const ComposePost = ({
|
|||||||
!missingAltError &&
|
!missingAltError &&
|
||||||
thread.posts.every(
|
thread.posts.every(
|
||||||
post =>
|
post =>
|
||||||
post.shortenedGraphemeLength <= MAX_GRAPHEME_LENGTH &&
|
post.shortenedGraphemeLength <= MAX_GRAPHEMES &&
|
||||||
!isEmptyPost(post) &&
|
!isEmptyPost(post) &&
|
||||||
!(
|
!(
|
||||||
post.embed.media?.type === 'video' &&
|
post.embed.media?.type === 'video' &&
|
||||||
@@ -605,6 +615,7 @@ export const ComposePost = ({
|
|||||||
type: 'add_post',
|
type: 'add_post',
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
|
maxGraphemeLength={MAX_GRAPHEMES}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
@@ -678,6 +689,7 @@ export const ComposePost = ({
|
|||||||
onClearVideo={clearVideo}
|
onClearVideo={clearVideo}
|
||||||
onPublish={onComposerPostPublish}
|
onPublish={onComposerPostPublish}
|
||||||
onError={setError}
|
onError={setError}
|
||||||
|
maxGraphemeLength={MAX_GRAPHEMES}
|
||||||
/>
|
/>
|
||||||
{isWebFooterSticky && post.id === activePost.id && (
|
{isWebFooterSticky && post.id === activePost.id && (
|
||||||
<View style={styles.stickyFooterWeb}>{footer}</View>
|
<View style={styles.stickyFooterWeb}>{footer}</View>
|
||||||
@@ -715,6 +727,7 @@ let ComposerPost = React.memo(function ComposerPost({
|
|||||||
onSelectVideo,
|
onSelectVideo,
|
||||||
onError,
|
onError,
|
||||||
onPublish,
|
onPublish,
|
||||||
|
maxGraphemeLength,
|
||||||
}: {
|
}: {
|
||||||
post: PostDraft
|
post: PostDraft
|
||||||
dispatch: (action: ComposerAction) => void
|
dispatch: (action: ComposerAction) => void
|
||||||
@@ -729,6 +742,7 @@ let ComposerPost = React.memo(function ComposerPost({
|
|||||||
onSelectVideo: (postId: string, asset: ImagePickerAsset) => void
|
onSelectVideo: (postId: string, asset: ImagePickerAsset) => void
|
||||||
onError: (error: string) => void
|
onError: (error: string) => void
|
||||||
onPublish: (richtext: RichText) => void
|
onPublish: (richtext: RichText) => void
|
||||||
|
maxGraphemeLength: number
|
||||||
}) {
|
}) {
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const currentDid = currentAccount!.did
|
const currentDid = currentAccount!.did
|
||||||
@@ -831,7 +845,7 @@ let ComposerPost = React.memo(function ComposerPost({
|
|||||||
accessible={true}
|
accessible={true}
|
||||||
accessibilityLabel={_(msg`Write post`)}
|
accessibilityLabel={_(msg`Write post`)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Compose posts up to ${MAX_GRAPHEME_LENGTH} characters in length`,
|
msg`Compose posts up to ${maxGraphemeLength} characters in length`,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@@ -1170,6 +1184,7 @@ function ComposerFooter({
|
|||||||
onError,
|
onError,
|
||||||
onSelectVideo,
|
onSelectVideo,
|
||||||
onAddPost,
|
onAddPost,
|
||||||
|
maxGraphemeLength,
|
||||||
}: {
|
}: {
|
||||||
post: PostDraft
|
post: PostDraft
|
||||||
dispatch: (action: PostAction) => void
|
dispatch: (action: PostAction) => void
|
||||||
@@ -1178,6 +1193,7 @@ function ComposerFooter({
|
|||||||
onError: (error: string) => void
|
onError: (error: string) => void
|
||||||
onSelectVideo: (postId: string, asset: ImagePickerAsset) => void
|
onSelectVideo: (postId: string, asset: ImagePickerAsset) => void
|
||||||
onAddPost: () => void
|
onAddPost: () => void
|
||||||
|
maxGraphemeLength: number
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -1270,6 +1286,7 @@ function ComposerFooter({
|
|||||||
)}
|
)}
|
||||||
<SelectLangBtn />
|
<SelectLangBtn />
|
||||||
<CharProgress
|
<CharProgress
|
||||||
|
max={maxGraphemeLength}
|
||||||
count={post.shortenedGraphemeLength}
|
count={post.shortenedGraphemeLength}
|
||||||
style={{width: 65}}
|
style={{width: 65}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user