[Chat] Remove old bubble styles (#10239)
This commit is contained in:
@@ -1,82 +0,0 @@
|
|||||||
import {memo} from 'react'
|
|
||||||
import {View} from 'react-native'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {subDays} from 'date-fns'
|
|
||||||
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
|
||||||
import {Text} from '../Typography'
|
|
||||||
import {localDateString} from './util'
|
|
||||||
|
|
||||||
const timeFormatter = new Intl.DateTimeFormat(undefined, {
|
|
||||||
hour: 'numeric',
|
|
||||||
minute: 'numeric',
|
|
||||||
})
|
|
||||||
const weekdayFormatter = new Intl.DateTimeFormat(undefined, {
|
|
||||||
weekday: 'long',
|
|
||||||
})
|
|
||||||
const longDateFormatter = new Intl.DateTimeFormat(undefined, {
|
|
||||||
weekday: 'short',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
})
|
|
||||||
const longDateFormatterWithYear = new Intl.DateTimeFormat(undefined, {
|
|
||||||
weekday: 'short',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
year: 'numeric',
|
|
||||||
})
|
|
||||||
|
|
||||||
let DateDivider = ({date: dateStr}: {date: string}): React.ReactNode => {
|
|
||||||
const {_} = useLingui()
|
|
||||||
const t = useTheme()
|
|
||||||
|
|
||||||
let date: string
|
|
||||||
const time = timeFormatter.format(new Date(dateStr))
|
|
||||||
|
|
||||||
const timestamp = new Date(dateStr)
|
|
||||||
|
|
||||||
const today = new Date()
|
|
||||||
const yesterday = subDays(today, 1)
|
|
||||||
const oneWeekAgo = subDays(today, 7)
|
|
||||||
|
|
||||||
if (localDateString(today) === localDateString(timestamp)) {
|
|
||||||
date = _(msg`Today`)
|
|
||||||
} else if (localDateString(yesterday) === localDateString(timestamp)) {
|
|
||||||
date = _(msg`Yesterday`)
|
|
||||||
} else {
|
|
||||||
if (timestamp < oneWeekAgo) {
|
|
||||||
if (timestamp.getFullYear() === today.getFullYear()) {
|
|
||||||
date = longDateFormatter.format(timestamp)
|
|
||||||
} else {
|
|
||||||
date = longDateFormatterWithYear.format(timestamp)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
date = weekdayFormatter.format(timestamp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.w_full, a.my_lg]}>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
a.text_center,
|
|
||||||
t.atoms.bg,
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
a.px_md,
|
|
||||||
]}>
|
|
||||||
<Trans>
|
|
||||||
<Text
|
|
||||||
style={[a.text_xs, t.atoms.text_contrast_medium, a.font_semi_bold]}>
|
|
||||||
{date}
|
|
||||||
</Text>{' '}
|
|
||||||
at {time}
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DateDivider = memo(DateDivider)
|
|
||||||
export {DateDivider}
|
|
||||||
@@ -469,23 +469,9 @@ let MessageItemMetadata = ({
|
|||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'pending-message':
|
case 'pending-message':
|
||||||
return item.failed ? (
|
return item.failed ? (
|
||||||
<Text
|
<Text style={[a.text_xs, a.my_2xs, {color: errorColor}, style]}>
|
||||||
style={[
|
<Text style={[a.text_xs, {color: errorColor}]}>
|
||||||
a.text_xs,
|
<Trans>Message failed to send.</Trans>
|
||||||
a.my_2xs,
|
|
||||||
{
|
|
||||||
color: errorColor,
|
|
||||||
},
|
|
||||||
style,
|
|
||||||
]}>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
{
|
|
||||||
color: errorColor,
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
{l`Message failed to send.`}
|
|
||||||
</Text>
|
</Text>
|
||||||
{item.retry && (
|
{item.retry && (
|
||||||
<>
|
<>
|
||||||
@@ -494,27 +480,14 @@ let MessageItemMetadata = ({
|
|||||||
label={l`Click to retry failed message`}
|
label={l`Click to retry failed message`}
|
||||||
to="#"
|
to="#"
|
||||||
onPress={handleRetry}
|
onPress={handleRetry}
|
||||||
style={[
|
style={[a.text_xs, {color: errorColor}]}>
|
||||||
a.text_xs,
|
<Trans>Tap to retry</Trans>
|
||||||
{
|
|
||||||
color: errorColor,
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
{l`Tap to retry`}
|
|
||||||
</InlineLinkText>
|
</InlineLinkText>
|
||||||
.
|
.
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : null
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
a.my_2xs,
|
|
||||||
style,
|
|
||||||
t.atoms.text_contrast_high,
|
|
||||||
]}>{l`Sending…`}</Text>
|
|
||||||
)
|
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import {memo} from 'react'
|
|
||||||
import {useWindowDimensions, View} from 'react-native'
|
|
||||||
import {type $Typed, type AppBskyEmbedRecord} from '@atproto/api'
|
|
||||||
|
|
||||||
import {atoms as a, native, tokens, useTheme, web} from '#/alf'
|
|
||||||
import {Embed, PostEmbedViewContext} from '#/components/Post/Embed'
|
|
||||||
import {MessageContextProvider} from './MessageContext'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
let MessageItemEmbed = ({
|
|
||||||
embed,
|
|
||||||
}: {
|
|
||||||
embed: $Typed<AppBskyEmbedRecord.View>
|
|
||||||
}): React.ReactNode => {
|
|
||||||
const t = useTheme()
|
|
||||||
const screen = useWindowDimensions()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MessageContextProvider>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.my_xs,
|
|
||||||
t.atoms.bg,
|
|
||||||
a.rounded_md,
|
|
||||||
native({
|
|
||||||
flexBasis: 0,
|
|
||||||
width: Math.min(screen.width, 600) / 1.4,
|
|
||||||
}),
|
|
||||||
web({
|
|
||||||
width: '100%',
|
|
||||||
minWidth: 280,
|
|
||||||
maxWidth: 360,
|
|
||||||
}),
|
|
||||||
]}>
|
|
||||||
<View style={{marginTop: tokens.space.sm * -1}}>
|
|
||||||
<Embed
|
|
||||||
embed={embed}
|
|
||||||
allowNestedQuotes
|
|
||||||
viewContext={PostEmbedViewContext.Feed}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</MessageContextProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MessageItemEmbed = memo(MessageItemEmbed)
|
|
||||||
export {MessageItemEmbed}
|
|
||||||
@@ -1,335 +0,0 @@
|
|||||||
import {memo, useCallback, useMemo} from 'react'
|
|
||||||
import {
|
|
||||||
type GestureResponderEvent,
|
|
||||||
type StyleProp,
|
|
||||||
type TextStyle,
|
|
||||||
View,
|
|
||||||
} from 'react-native'
|
|
||||||
import Animated, {
|
|
||||||
LayoutAnimationConfig,
|
|
||||||
LinearTransition,
|
|
||||||
ZoomIn,
|
|
||||||
ZoomOut,
|
|
||||||
} from 'react-native-reanimated'
|
|
||||||
import {
|
|
||||||
AppBskyEmbedRecord,
|
|
||||||
ChatBskyConvoDefs,
|
|
||||||
RichText as RichTextAPI,
|
|
||||||
} from '@atproto/api'
|
|
||||||
import {type I18n} from '@lingui/core'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
|
||||||
import {useConvoActive} from '#/state/messages/convo'
|
|
||||||
import {type ConvoItem} from '#/state/messages/convo/types'
|
|
||||||
import {useSession} from '#/state/session'
|
|
||||||
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
|
|
||||||
import {atoms as a, native, useTheme} from '#/alf'
|
|
||||||
import {isOnlyEmoji} from '#/alf/typography'
|
|
||||||
import {ActionsWrapper} from '#/components/dms/ActionsWrapper'
|
|
||||||
import {InlineLinkText} from '#/components/Link'
|
|
||||||
import {RichText} from '#/components/RichText'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
import {IS_NATIVE} from '#/env'
|
|
||||||
import {DateDivider as DateDividerDeprecated} from './DateDivider_DEPRECATED'
|
|
||||||
import {MessageItemEmbed as MessageItemEmbedDeprecated} from './MessageItemEmbed_DEPRECATED'
|
|
||||||
import {localDateString} from './util'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
let MessageItem = ({
|
|
||||||
item,
|
|
||||||
}: {
|
|
||||||
item: ConvoItem & {type: 'message' | 'pending-message'}
|
|
||||||
}): React.ReactNode => {
|
|
||||||
const t = useTheme()
|
|
||||||
const {currentAccount} = useSession()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {convo} = useConvoActive()
|
|
||||||
|
|
||||||
const {message, nextMessage, prevMessage} = item
|
|
||||||
const isPending = item.type === 'pending-message'
|
|
||||||
|
|
||||||
const isFromSelf = message.sender?.did === currentAccount?.did
|
|
||||||
|
|
||||||
const nextIsMessage = ChatBskyConvoDefs.isMessageView(nextMessage)
|
|
||||||
|
|
||||||
const isNextFromSelf =
|
|
||||||
nextIsMessage && nextMessage.sender?.did === currentAccount?.did
|
|
||||||
|
|
||||||
const isNextFromSameSender = isNextFromSelf === isFromSelf
|
|
||||||
|
|
||||||
const isNewDay = useMemo(() => {
|
|
||||||
if (!prevMessage) return true
|
|
||||||
|
|
||||||
const thisDate = new Date(message.sentAt)
|
|
||||||
const prevDate = new Date(prevMessage.sentAt)
|
|
||||||
|
|
||||||
return localDateString(thisDate) !== localDateString(prevDate)
|
|
||||||
}, [message, prevMessage])
|
|
||||||
|
|
||||||
const isLastMessageOfDay = useMemo(() => {
|
|
||||||
if (!nextMessage || !nextIsMessage) return true
|
|
||||||
|
|
||||||
const thisDate = new Date(message.sentAt)
|
|
||||||
const prevDate = new Date(nextMessage.sentAt)
|
|
||||||
|
|
||||||
return localDateString(thisDate) !== localDateString(prevDate)
|
|
||||||
}, [message.sentAt, nextIsMessage, nextMessage])
|
|
||||||
|
|
||||||
const needsTail = isLastMessageOfDay || !isNextFromSameSender
|
|
||||||
|
|
||||||
const isLastInGroup = useMemo(() => {
|
|
||||||
// if this message is pending, it means the next message is pending too
|
|
||||||
if (isPending && nextMessage) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// or, if there's a 5 minute gap between this message and the next
|
|
||||||
if (ChatBskyConvoDefs.isMessageView(nextMessage)) {
|
|
||||||
const thisDate = new Date(message.sentAt)
|
|
||||||
const nextDate = new Date(nextMessage.sentAt)
|
|
||||||
|
|
||||||
const diff = nextDate.getTime() - thisDate.getTime()
|
|
||||||
|
|
||||||
// 5 minutes
|
|
||||||
return diff > 5 * 60 * 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}, [message, nextMessage, isPending])
|
|
||||||
|
|
||||||
const pendingColor = t.palette.primary_200
|
|
||||||
|
|
||||||
const rt = useMemo(() => {
|
|
||||||
return new RichTextAPI({text: message.text, facets: message.facets})
|
|
||||||
}, [message.text, message.facets])
|
|
||||||
|
|
||||||
const appliedReactions = (
|
|
||||||
<LayoutAnimationConfig skipEntering skipExiting>
|
|
||||||
{message.reactions && message.reactions.length > 0 && (
|
|
||||||
<View
|
|
||||||
style={[isFromSelf ? a.align_end : a.align_start, a.px_sm, a.pb_2xs]}>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.gap_2xs,
|
|
||||||
a.py_xs,
|
|
||||||
a.px_xs,
|
|
||||||
a.justify_center,
|
|
||||||
isFromSelf ? a.justify_end : a.justify_start,
|
|
||||||
a.flex_wrap,
|
|
||||||
a.pb_xs,
|
|
||||||
t.atoms.bg_contrast_25,
|
|
||||||
a.border,
|
|
||||||
t.atoms.border_contrast_low,
|
|
||||||
a.rounded_lg,
|
|
||||||
t.atoms.shadow_sm,
|
|
||||||
{
|
|
||||||
// vibe coded number
|
|
||||||
transform: [{translateY: -11}],
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
{message.reactions.map((reaction, _i, reactions) => {
|
|
||||||
let label
|
|
||||||
if (reaction.sender.did === currentAccount?.did) {
|
|
||||||
label = _(msg`You reacted ${reaction.value}`)
|
|
||||||
} else {
|
|
||||||
const senderDid = reaction.sender.did
|
|
||||||
const sender = convo.members.find(
|
|
||||||
member => member.did === senderDid,
|
|
||||||
)
|
|
||||||
if (sender) {
|
|
||||||
label = _(
|
|
||||||
msg`${sanitizeDisplayName(
|
|
||||||
sender.displayName || sender.handle,
|
|
||||||
)} reacted ${reaction.value}`,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
label = _(msg`Someone reacted ${reaction.value}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Animated.View
|
|
||||||
entering={native(ZoomIn.springify(200).delay(400))}
|
|
||||||
exiting={reactions.length > 1 && native(ZoomOut.delay(200))}
|
|
||||||
layout={native(LinearTransition.delay(300))}
|
|
||||||
key={reaction.sender.did + reaction.value}
|
|
||||||
style={[a.p_2xs]}
|
|
||||||
accessible={true}
|
|
||||||
accessibilityLabel={label}
|
|
||||||
accessibilityHint={_(
|
|
||||||
msg`Double tap or long press the message to add a reaction`,
|
|
||||||
)}>
|
|
||||||
<Text emoji style={[a.text_sm]}>
|
|
||||||
{reaction.value}
|
|
||||||
</Text>
|
|
||||||
</Animated.View>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</LayoutAnimationConfig>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isNewDay && <DateDividerDeprecated date={message.sentAt} />}
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
isFromSelf ? a.mr_md : a.ml_md,
|
|
||||||
nextIsMessage && !isNextFromSameSender && a.mb_md,
|
|
||||||
]}>
|
|
||||||
<ActionsWrapper isFromSelf={isFromSelf} message={message}>
|
|
||||||
{AppBskyEmbedRecord.isView(message.embed) && (
|
|
||||||
<MessageItemEmbedDeprecated embed={message.embed} />
|
|
||||||
)}
|
|
||||||
{rt.text.length > 0 && (
|
|
||||||
<View
|
|
||||||
style={
|
|
||||||
!isOnlyEmoji(message.text) && [
|
|
||||||
a.py_sm,
|
|
||||||
a.my_2xs,
|
|
||||||
a.rounded_md,
|
|
||||||
{
|
|
||||||
paddingLeft: 14,
|
|
||||||
paddingRight: 14,
|
|
||||||
backgroundColor: isFromSelf
|
|
||||||
? isPending
|
|
||||||
? pendingColor
|
|
||||||
: t.palette.primary_500
|
|
||||||
: t.palette.contrast_50,
|
|
||||||
borderRadius: 17,
|
|
||||||
},
|
|
||||||
isFromSelf ? a.self_end : a.self_start,
|
|
||||||
isFromSelf
|
|
||||||
? {borderBottomRightRadius: needsTail ? 2 : 17}
|
|
||||||
: {borderBottomLeftRadius: needsTail ? 2 : 17},
|
|
||||||
]
|
|
||||||
}>
|
|
||||||
<RichText
|
|
||||||
value={rt}
|
|
||||||
style={[a.text_md, isFromSelf && {color: t.palette.white}]}
|
|
||||||
interactiveStyle={a.underline}
|
|
||||||
enableTags
|
|
||||||
emojiMultiplier={3}
|
|
||||||
shouldProxyLinks={true}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{IS_NATIVE && appliedReactions}
|
|
||||||
</ActionsWrapper>
|
|
||||||
|
|
||||||
{!IS_NATIVE && appliedReactions}
|
|
||||||
|
|
||||||
{isLastInGroup && (
|
|
||||||
<MessageItemMetadata
|
|
||||||
item={item}
|
|
||||||
style={isFromSelf ? a.text_right : a.text_left}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MessageItem = memo(MessageItem)
|
|
||||||
export {MessageItem}
|
|
||||||
|
|
||||||
let MessageItemMetadata = ({
|
|
||||||
item,
|
|
||||||
style,
|
|
||||||
}: {
|
|
||||||
item: ConvoItem & {type: 'message' | 'pending-message'}
|
|
||||||
style: StyleProp<TextStyle>
|
|
||||||
}): React.ReactNode => {
|
|
||||||
const t = useTheme()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {message} = item
|
|
||||||
|
|
||||||
const handleRetry = useCallback(
|
|
||||||
(e: GestureResponderEvent) => {
|
|
||||||
if (item.type === 'pending-message' && item.retry) {
|
|
||||||
e.preventDefault()
|
|
||||||
item.retry()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[item],
|
|
||||||
)
|
|
||||||
|
|
||||||
const relativeTimestamp = useCallback(
|
|
||||||
(i18n: I18n, timestamp: string) => {
|
|
||||||
const date = new Date(timestamp)
|
|
||||||
const now = new Date()
|
|
||||||
|
|
||||||
const time = i18n.date(date, {
|
|
||||||
hour: 'numeric',
|
|
||||||
minute: 'numeric',
|
|
||||||
})
|
|
||||||
|
|
||||||
const diff = now.getTime() - date.getTime()
|
|
||||||
|
|
||||||
// if under 30 seconds
|
|
||||||
if (diff < 1000 * 30) {
|
|
||||||
return _(msg`Now`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return time
|
|
||||||
},
|
|
||||||
[_],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
a.mt_2xs,
|
|
||||||
a.mb_lg,
|
|
||||||
t.atoms.text_contrast_medium,
|
|
||||||
style,
|
|
||||||
]}>
|
|
||||||
<TimeElapsed timestamp={message.sentAt} timeToString={relativeTimestamp}>
|
|
||||||
{({timeElapsed}) => (
|
|
||||||
<Text style={[a.text_xs, t.atoms.text_contrast_medium]}>
|
|
||||||
{timeElapsed}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</TimeElapsed>
|
|
||||||
|
|
||||||
{item.type === 'pending-message' && item.failed && (
|
|
||||||
<>
|
|
||||||
{' '}
|
|
||||||
·{' '}
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
a.text_xs,
|
|
||||||
{
|
|
||||||
color: t.palette.negative_400,
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
{_(msg`Failed to send`)}
|
|
||||||
</Text>
|
|
||||||
{item.retry && (
|
|
||||||
<>
|
|
||||||
{' '}
|
|
||||||
·{' '}
|
|
||||||
<InlineLinkText
|
|
||||||
label={_(msg`Click to retry failed message`)}
|
|
||||||
to="#"
|
|
||||||
onPress={handleRetry}
|
|
||||||
style={[a.text_xs]}>
|
|
||||||
{_(msg`Retry`)}
|
|
||||||
</InlineLinkText>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
MessageItemMetadata = memo(MessageItemMetadata)
|
|
||||||
export {MessageItemMetadata}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
import {useMemo} from 'react'
|
|
||||||
import {View} from 'react-native'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
|
|
||||||
import {type ConvoItem, ConvoItemError} from '#/state/messages/convo/types'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
|
||||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
|
||||||
import {InlineLinkText} from '#/components/Link'
|
|
||||||
import {Text} from '#/components/Typography'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export function MessageListError({item}: {item: ConvoItem & {type: 'error'}}) {
|
|
||||||
const t = useTheme()
|
|
||||||
const {_} = useLingui()
|
|
||||||
const {description, help, cta} = useMemo(() => {
|
|
||||||
return {
|
|
||||||
[ConvoItemError.FirehoseFailed]: {
|
|
||||||
description: _(msg`This chat was disconnected`),
|
|
||||||
help: _(msg`Press to attempt reconnection`),
|
|
||||||
cta: _(msg`Reconnect`),
|
|
||||||
},
|
|
||||||
[ConvoItemError.HistoryFailed]: {
|
|
||||||
description: _(msg`Failed to load past messages`),
|
|
||||||
help: _(msg`Press to retry`),
|
|
||||||
cta: _(msg`Retry`),
|
|
||||||
},
|
|
||||||
}[item.code]
|
|
||||||
}, [_, item.code])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.py_md, a.w_full, a.flex_row, a.justify_center]}>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_1,
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_center,
|
|
||||||
a.gap_sm,
|
|
||||||
{maxWidth: 400},
|
|
||||||
]}>
|
|
||||||
<CircleInfo size="sm" fill={t.palette.negative_400} />
|
|
||||||
|
|
||||||
<Text style={[a.leading_snug, t.atoms.text_contrast_medium]}>
|
|
||||||
{description} ·{' '}
|
|
||||||
{item.retry && (
|
|
||||||
<InlineLinkText
|
|
||||||
to="#"
|
|
||||||
label={help}
|
|
||||||
onPress={e => {
|
|
||||||
e.preventDefault()
|
|
||||||
item.retry?.()
|
|
||||||
return false
|
|
||||||
}}>
|
|
||||||
{cta}
|
|
||||||
</InlineLinkText>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -51,11 +51,9 @@ import {ChatDisabled} from '#/screens/Messages/components/ChatDisabled'
|
|||||||
import {MessageComposer} from '#/screens/Messages/components/MessageComposer'
|
import {MessageComposer} from '#/screens/Messages/components/MessageComposer'
|
||||||
import {MessageInput} from '#/screens/Messages/components/MessageInput'
|
import {MessageInput} from '#/screens/Messages/components/MessageInput'
|
||||||
import {MessageListError} from '#/screens/Messages/components/MessageListError'
|
import {MessageListError} from '#/screens/Messages/components/MessageListError'
|
||||||
import {MessageListError as MessageListErrorDeprecated} from '#/screens/Messages/components/MessageListError_DEPRECATED'
|
|
||||||
import {atoms as a, platform, tokens, useTheme, web} from '#/alf'
|
import {atoms as a, platform, tokens, useTheme, web} from '#/alf'
|
||||||
import {ChatEmptyPill} from '#/components/dms/ChatEmptyPill'
|
import {ChatEmptyPill} from '#/components/dms/ChatEmptyPill'
|
||||||
import {MessageItem} from '#/components/dms/MessageItem'
|
import {MessageItem} from '#/components/dms/MessageItem'
|
||||||
import {MessageItem as MessageItemDeprecated} from '#/components/dms/MessageItem_DEPRECATED'
|
|
||||||
import {NewMessagesPill} from '#/components/dms/NewMessagesPill'
|
import {NewMessagesPill} from '#/components/dms/NewMessagesPill'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
@@ -107,8 +105,6 @@ export function MessagesList({
|
|||||||
const {embedUri, setEmbed} = useMessageEmbed()
|
const {embedUri, setEmbed} = useMessageEmbed()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
|
||||||
const isGroupChatEnabled = ax.features.enabled(ax.features.GroupChatsEnable)
|
|
||||||
|
|
||||||
const textInputId = 'chat-input-' + useId()
|
const textInputId = 'chat-input-' + useId()
|
||||||
const flatListRef = useAnimatedRef<ListMethods>()
|
const flatListRef = useAnimatedRef<ListMethods>()
|
||||||
|
|
||||||
@@ -363,7 +359,7 @@ export function MessagesList({
|
|||||||
|
|
||||||
const renderItem = ({item}: {item: ConvoItem}) => {
|
const renderItem = ({item}: {item: ConvoItem}) => {
|
||||||
if (item.type === 'message' || item.type === 'pending-message') {
|
if (item.type === 'message' || item.type === 'pending-message') {
|
||||||
return isGroupChatEnabled ? (
|
return (
|
||||||
<MessageItem
|
<MessageItem
|
||||||
item={item}
|
item={item}
|
||||||
profile={convoState.convo.members.find(
|
profile={convoState.convo.members.find(
|
||||||
@@ -371,17 +367,11 @@ export function MessagesList({
|
|||||||
)}
|
)}
|
||||||
isGroupChat={convoState.convo.kind === 'group'}
|
isGroupChat={convoState.convo.kind === 'group'}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<MessageItemDeprecated item={item} />
|
|
||||||
)
|
)
|
||||||
} else if (item.type === 'deleted-message') {
|
} else if (item.type === 'deleted-message') {
|
||||||
return <Text>Deleted message</Text>
|
return <Text>Deleted message</Text>
|
||||||
} else if (item.type === 'error') {
|
} else if (item.type === 'error') {
|
||||||
return isGroupChatEnabled ? (
|
return <MessageListError item={item} />
|
||||||
<MessageListError item={item} />
|
|
||||||
) : (
|
|
||||||
<MessageListErrorDeprecated item={item} />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
Reference in New Issue
Block a user