148 lines
4.4 KiB
TypeScript
148 lines
4.4 KiB
TypeScript
import {useCallback} from 'react'
|
|
import {View} from 'react-native'
|
|
import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes'
|
|
import {type ScreenLayoutArgs, useIsFocused} from '@react-navigation/native'
|
|
import {type NativeStackNavigationProp} from '@react-navigation/native-stack'
|
|
|
|
import {type FlatNavigatorParams} from '#/lib/routes/types'
|
|
import {ScrollProvider} from '#/lib/ScrollContext'
|
|
import {useChatActorStatusQuery} from '#/state/queries/messages/get-status'
|
|
import {type NativeStackNavigationOptionsWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth'
|
|
import {LEFT_NAV_MINIMAL_WIDTH} from '#/view/shell/desktop/LeftNav'
|
|
import {atoms as a, useLayoutBreakpoints, useTheme, web} from '#/alf'
|
|
import {useDialogControl} from '#/components/Dialog'
|
|
import {NewChat} from '#/components/dms/dialogs/NewChatDialog'
|
|
import {CENTER_COLUMN_WIDTH, SCROLLBAR_OFFSET} from '#/components/Layout'
|
|
import {LockScroll} from '#/components/LockScroll'
|
|
import {useAgeAssurance} from '#/ageAssurance'
|
|
import {IS_WEB} from '#/env'
|
|
import {ChatList, Header as ChatListHeader} from '../../ChatList'
|
|
import {SplitViewProvider} from './context'
|
|
import {splitViewLeftScroll} from './leftColumnScroll'
|
|
|
|
type MessageScreens =
|
|
| 'Messages'
|
|
| 'MessagesConversation'
|
|
| 'MessagesConversationSettings'
|
|
| 'MessagesInbox'
|
|
| 'MessagesSettings'
|
|
|
|
type LayoutProps = ScreenLayoutArgs<
|
|
FlatNavigatorParams,
|
|
MessageScreens,
|
|
NativeStackNavigationOptionsWithAuth,
|
|
NativeStackNavigationProp<
|
|
FlatNavigatorParams,
|
|
MessageScreens,
|
|
string | undefined
|
|
>
|
|
>
|
|
export function renderMessagesSplitViewLayout(props: LayoutProps) {
|
|
return <MessagesSplitViewLayout {...props} />
|
|
}
|
|
|
|
function MessagesSplitViewLayout({children, ...props}: LayoutProps) {
|
|
const {rightNavVisible} = useLayoutBreakpoints()
|
|
const aa = useAgeAssurance()
|
|
|
|
if (!IS_WEB || !rightNavVisible || aa.state.access !== aa.Access.Full) {
|
|
return children
|
|
}
|
|
|
|
return (
|
|
<MessagesSplitViewLayoutInner {...props}>
|
|
{children}
|
|
</MessagesSplitViewLayoutInner>
|
|
)
|
|
}
|
|
|
|
function MessagesSplitViewLayoutInner({
|
|
children,
|
|
navigation,
|
|
route,
|
|
}: LayoutProps) {
|
|
const {centerColumnOffset} = useLayoutBreakpoints()
|
|
const newChatControl = useDialogControl()
|
|
const t = useTheme()
|
|
const isFocused = useIsFocused()
|
|
const {data: chatStatus} = useChatActorStatusQuery()
|
|
|
|
const onLeftColumnScroll = useCallback((e: ReanimatedScrollEvent) => {
|
|
'worklet'
|
|
splitViewLeftScroll.current = e.contentOffset.y
|
|
}, [])
|
|
|
|
const onNewChat = (conversation: string) =>
|
|
navigation.navigate('MessagesConversation', {conversation})
|
|
|
|
const selectedChat =
|
|
(route.name === 'MessagesConversation' ||
|
|
route.name === 'MessagesConversationSettings') &&
|
|
route.params &&
|
|
'conversation' in route.params
|
|
? route.params.conversation
|
|
: undefined
|
|
|
|
const halfLeftNavWidth = LEFT_NAV_MINIMAL_WIDTH / 2
|
|
|
|
const leftColumnWidth = 360
|
|
|
|
const rightColumnWidth =
|
|
CENTER_COLUMN_WIDTH - (centerColumnOffset ? halfLeftNavWidth + 30 : 0)
|
|
|
|
const containerWidth = leftColumnWidth + rightColumnWidth
|
|
|
|
return (
|
|
<View
|
|
style={[
|
|
a.flex_1,
|
|
a.flex_row,
|
|
a.mx_auto,
|
|
{maxWidth: containerWidth},
|
|
{
|
|
transform: [
|
|
{
|
|
translateX: centerColumnOffset
|
|
? halfLeftNavWidth
|
|
: halfLeftNavWidth / 2,
|
|
},
|
|
{translateX: web(SCROLLBAR_OFFSET) ?? 0},
|
|
],
|
|
},
|
|
]}>
|
|
{isFocused && <LockScroll />}
|
|
<SplitViewProvider side="left">
|
|
<View
|
|
style={[
|
|
a.border_l,
|
|
t.atoms.border_contrast_low,
|
|
{width: leftColumnWidth},
|
|
]}>
|
|
<ChatListHeader
|
|
newChatControl={newChatControl}
|
|
chatStatus={chatStatus}
|
|
/>
|
|
<ScrollProvider onScroll={onLeftColumnScroll}>
|
|
<ChatList
|
|
newChatControl={newChatControl}
|
|
selectedChat={selectedChat}
|
|
chatStatus={chatStatus}
|
|
/>
|
|
</ScrollProvider>
|
|
<NewChat onNewChat={onNewChat} control={newChatControl} />
|
|
</View>
|
|
</SplitViewProvider>
|
|
<SplitViewProvider side="right">
|
|
<View
|
|
style={[
|
|
a.border_x,
|
|
t.atoms.border_contrast_low,
|
|
{width: rightColumnWidth},
|
|
]}>
|
|
{children}
|
|
</View>
|
|
</SplitViewProvider>
|
|
</View>
|
|
)
|
|
}
|