Add long-press menu to Chat tab for marking all as read (#10890)
This commit is contained in:
@@ -2,9 +2,8 @@ import {type JSX, useCallback} from 'react'
|
|||||||
import {type GestureResponderEvent, View} from 'react-native'
|
import {type GestureResponderEvent, View} from 'react-native'
|
||||||
import Animated from 'react-native-reanimated'
|
import Animated from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {msg, plural} from '@lingui/core/macro'
|
import {plural} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {type BottomTabBarProps} from '@react-navigation/bottom-tabs'
|
import {type BottomTabBarProps} from '@react-navigation/bottom-tabs'
|
||||||
import {StackActions} from '@react-navigation/native'
|
import {StackActions} from '@react-navigation/native'
|
||||||
|
|
||||||
@@ -20,6 +19,7 @@ import {getTabState, TabState} from '#/lib/routes/helpers'
|
|||||||
import {type SharedNavTab, TAB_TO_NAV_ITEM} from '#/lib/routes/tab-to-nav-item'
|
import {type SharedNavTab, TAB_TO_NAV_ITEM} from '#/lib/routes/tab-to-nav-item'
|
||||||
import {emitSoftReset} from '#/state/events'
|
import {emitSoftReset} from '#/state/events'
|
||||||
import {useUnreadMessageCount} from '#/state/queries/messages/list-conversations'
|
import {useUnreadMessageCount} from '#/state/queries/messages/list-conversations'
|
||||||
|
import {useUpdateAllRead} from '#/state/queries/messages/update-all-read'
|
||||||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
@@ -37,10 +37,12 @@ import {
|
|||||||
Bell_Filled_Corner0_Rounded as BellFilled,
|
Bell_Filled_Corner0_Rounded as BellFilled,
|
||||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||||
} from '#/components/icons/Bell'
|
} from '#/components/icons/Bell'
|
||||||
|
import {CircleCheck_Stroke2_Corner0_Rounded as CircleCheckIcon} from '#/components/icons/CircleCheck'
|
||||||
import {
|
import {
|
||||||
HomeOpen_Filled_Corner0_Rounded as HomeFilled,
|
HomeOpen_Filled_Corner0_Rounded as HomeFilled,
|
||||||
HomeOpen_Stoke2_Corner0_Rounded as Home,
|
HomeOpen_Stoke2_Corner0_Rounded as Home,
|
||||||
} from '#/components/icons/HomeOpen'
|
} from '#/components/icons/HomeOpen'
|
||||||
|
import {Inbox_Stroke2_Corner2_Rounded as InboxIcon} from '#/components/icons/Inbox'
|
||||||
import {
|
import {
|
||||||
MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled,
|
MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled,
|
||||||
MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlass,
|
MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlass,
|
||||||
@@ -49,6 +51,8 @@ import {
|
|||||||
Message_Stroke2_Corner0_Rounded as Message,
|
Message_Stroke2_Corner0_Rounded as Message,
|
||||||
Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
|
Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
|
||||||
} from '#/components/icons/Message'
|
} from '#/components/icons/Message'
|
||||||
|
import * as Menu from '#/components/Menu'
|
||||||
|
import * as Toast from '#/components/Toast'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
@@ -59,7 +63,7 @@ import {styles} from './BottomBarStyles'
|
|||||||
export function BottomBar({navigation}: BottomTabBarProps) {
|
export function BottomBar({navigation}: BottomTabBarProps) {
|
||||||
const {hasSession, currentAccount} = useSession()
|
const {hasSession, currentAccount} = useSession()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const safeAreaInsets = useSafeAreaInsets()
|
const safeAreaInsets = useSafeAreaInsets()
|
||||||
const {footerHeight} = useShellLayout()
|
const {footerHeight} = useShellLayout()
|
||||||
@@ -74,6 +78,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
const dedupe = useDedupe()
|
const dedupe = useDedupe()
|
||||||
const accountSwitchControl = useDialogControl()
|
const accountSwitchControl = useDialogControl()
|
||||||
|
const messagesMenuControl = Menu.useMenuControl()
|
||||||
const playHaptic = useHaptics()
|
const playHaptic = useHaptics()
|
||||||
const hideBorder = useHideBottomBarBorder()
|
const hideBorder = useHideBottomBarBorder()
|
||||||
const iconWidth = 28
|
const iconWidth = 28
|
||||||
@@ -142,6 +147,12 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
accountSwitchControl.open()
|
accountSwitchControl.open()
|
||||||
}, [accountSwitchControl, playHaptic])
|
}, [accountSwitchControl, playHaptic])
|
||||||
|
|
||||||
|
const onLongPressMessages = useCallback(() => {
|
||||||
|
if (aa.flags.chatDisabled) return
|
||||||
|
playHaptic()
|
||||||
|
messagesMenuControl.open()
|
||||||
|
}, [aa.flags.chatDisabled, messagesMenuControl, playHaptic])
|
||||||
|
|
||||||
const [demoMode] = useDemoMode()
|
const [demoMode] = useDemoMode()
|
||||||
const {isActive: live} = useActorStatus(profile)
|
const {isActive: live} = useActorStatus(profile)
|
||||||
const isLabeler = profile?.associated?.labeler
|
const isLabeler = profile?.associated?.labeler
|
||||||
@@ -149,7 +160,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SwitchAccountDialog control={accountSwitchControl} />
|
<SwitchAccountDialog control={accountSwitchControl} />
|
||||||
|
<MessagesTabMenu control={messagesMenuControl} />
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styles.bottomBar,
|
styles.bottomBar,
|
||||||
@@ -182,7 +193,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
}
|
}
|
||||||
onPress={onPressHome}
|
onPress={onPressHome}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={_(msg`Home`)}
|
accessibilityLabel={l`Home`}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
@@ -202,7 +213,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
}
|
}
|
||||||
onPress={onPressSearch}
|
onPress={onPressSearch}
|
||||||
accessibilityRole="search"
|
accessibilityRole="search"
|
||||||
accessibilityLabel={_(msg`Search`)}
|
accessibilityLabel={l`Search`}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
@@ -221,21 +232,22 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
onPress={onPressMessages}
|
onPress={onPressMessages}
|
||||||
|
onLongPress={onLongPressMessages}
|
||||||
notificationCount={
|
notificationCount={
|
||||||
aa.flags.chatDisabled ? undefined : numUnreadMessages.numUnread
|
aa.flags.chatDisabled ? undefined : numUnreadMessages.numUnread
|
||||||
}
|
}
|
||||||
hasNew={aa.flags.chatDisabled ? false : numUnreadMessages.hasNew}
|
hasNew={aa.flags.chatDisabled ? false : numUnreadMessages.hasNew}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={_(msg`Chat`)}
|
accessibilityLabel={l`Chat`}
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
!aa.flags.chatDisabled && numUnreadMessages.count > 0
|
!aa.flags.chatDisabled && numUnreadMessages.count > 0
|
||||||
? _(
|
? l({
|
||||||
plural(numUnreadMessages.numUnread ?? 0, {
|
message: plural(numUnreadMessages.numUnread ?? 0, {
|
||||||
one: '# unread item',
|
one: '# unread item',
|
||||||
other: '# unread items',
|
other: '# unread items',
|
||||||
}),
|
}),
|
||||||
)
|
})
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -258,16 +270,16 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
notificationCount={numUnreadNotifications}
|
notificationCount={numUnreadNotifications}
|
||||||
accessible={true}
|
accessible={true}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={_(msg`Notifications`)}
|
accessibilityLabel={l`Notifications`}
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
numUnreadNotifications === ''
|
numUnreadNotifications === ''
|
||||||
? ''
|
? ''
|
||||||
: _(
|
: l({
|
||||||
plural(numUnreadNotifications ?? 0, {
|
message: plural(numUnreadNotifications ?? 0, {
|
||||||
one: '# unread item',
|
one: '# unread item',
|
||||||
other: '# unread items',
|
other: '# unread items',
|
||||||
}),
|
}),
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Btn
|
<Btn
|
||||||
@@ -301,7 +313,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
onPress={onPressProfile}
|
onPress={onPressProfile}
|
||||||
onLongPress={onLongPressProfile}
|
onLongPress={onLongPressProfile}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={_(msg`Profile`)}
|
accessibilityLabel={l`Profile`}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@@ -330,9 +342,8 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
<View style={[a.flex_row, a.flex_wrap, a.gap_sm]}>
|
<View style={[a.flex_row, a.flex_wrap, a.gap_sm]}>
|
||||||
<Button
|
<Button
|
||||||
onPress={showCreateAccount}
|
onPress={showCreateAccount}
|
||||||
label={_(msg`Create account`)}
|
label={l`Create account`}
|
||||||
size="small"
|
size="small"
|
||||||
variant="solid"
|
|
||||||
color="primary">
|
color="primary">
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Create account</Trans>
|
<Trans>Create account</Trans>
|
||||||
@@ -340,9 +351,8 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onPress={showSignIn}
|
onPress={showSignIn}
|
||||||
label={_(msg`Sign in`)}
|
label={l`Sign in`}
|
||||||
size="small"
|
size="small"
|
||||||
variant="solid"
|
|
||||||
color="secondary">
|
color="secondary">
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Sign in</Trans>
|
<Trans>Sign in</Trans>
|
||||||
@@ -419,3 +429,50 @@ function Btn({
|
|||||||
</PressableScale>
|
</PressableScale>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function MessagesTabMenu({control}: {control: Menu.MenuControlProps}) {
|
||||||
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
|
const {mutate: markAllChatsRead} = useUpdateAllRead('accepted', {
|
||||||
|
onMutate: () => {
|
||||||
|
Toast.show(l`Marked all chats as read`, {type: 'success'})
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
Toast.show(l`Failed to mark all chats as read`, {type: 'error'})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const {mutate: markAllRequestsRead} = useUpdateAllRead('request', {
|
||||||
|
onMutate: () => {
|
||||||
|
Toast.show(l`Marked all requests as read`, {type: 'success'})
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
Toast.show(l`Failed to mark all requests as read`, {type: 'error'})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu.Root control={control}>
|
||||||
|
<Menu.Outer showCancel>
|
||||||
|
<Menu.Group>
|
||||||
|
<Menu.Item
|
||||||
|
label={l`Mark all chats as read`}
|
||||||
|
onPress={() => markAllChatsRead()}>
|
||||||
|
<Menu.ItemIcon icon={CircleCheckIcon} />
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Mark all chats as read</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
label={l`Mark all requests as read`}
|
||||||
|
onPress={() => markAllRequestsRead()}>
|
||||||
|
<Menu.ItemIcon icon={InboxIcon} />
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Mark all requests as read</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.Group>
|
||||||
|
</Menu.Outer>
|
||||||
|
</Menu.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user