[Chat] Split view layout for web (#10258)
This commit is contained in:
@@ -7,6 +7,7 @@ import {useNavigation} from '@react-navigation/native'
|
||||
import {HITSLOP_30} from '#/lib/constants'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {useSetDrawerOpen} from '#/state/shell'
|
||||
import {useIsWithinSplitView} from '#/screens/Messages/components/splitView/context'
|
||||
import {
|
||||
atoms as a,
|
||||
platform,
|
||||
@@ -46,6 +47,7 @@ export function Outer({
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {isWithinOffsetView} = useContext(ScrollbarOffsetContext)
|
||||
const {centerColumnOffset} = useLayoutBreakpoints()
|
||||
const {isWithinSplitView} = useIsWithinSplitView()
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -64,12 +66,13 @@ export function Outer({
|
||||
}),
|
||||
t.atoms.border_contrast_low,
|
||||
gtMobile && [a.mx_auto, {maxWidth: 600}],
|
||||
!isWithinOffsetView && {
|
||||
transform: [
|
||||
{translateX: centerColumnOffset ? CENTER_COLUMN_OFFSET : 0},
|
||||
{translateX: web(SCROLLBAR_OFFSET) ?? 0},
|
||||
],
|
||||
},
|
||||
!isWithinOffsetView &&
|
||||
!isWithinSplitView && {
|
||||
transform: [
|
||||
{translateX: centerColumnOffset ? CENTER_COLUMN_OFFSET : 0},
|
||||
{translateX: web(SCROLLBAR_OFFSET) ?? 0},
|
||||
],
|
||||
},
|
||||
]}>
|
||||
{children}
|
||||
</View>
|
||||
@@ -108,6 +111,7 @@ export function Slot({children}: {children?: React.ReactNode}) {
|
||||
export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
||||
const {_} = useLingui()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {isWithinRightPanel} = useIsWithinSplitView()
|
||||
|
||||
const onPressBack = useCallback(
|
||||
(evt: GestureResponderEvent) => {
|
||||
@@ -122,6 +126,10 @@ export function BackButton({onPress, style, ...props}: Partial<ButtonProps>) {
|
||||
[onPress, navigation],
|
||||
)
|
||||
|
||||
if (isWithinRightPanel) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Slot>
|
||||
<Button
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import {forwardRef, memo, useContext, useMemo} from 'react'
|
||||
import {
|
||||
type StyleProp,
|
||||
StyleSheet,
|
||||
View,
|
||||
type ViewProps,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {
|
||||
KeyboardAwareScrollView,
|
||||
type KeyboardAwareScrollViewProps,
|
||||
} from 'react-native-keyboard-controller'
|
||||
import Animated, {
|
||||
type AnimatedScrollViewProps,
|
||||
useAnimatedProps,
|
||||
@@ -18,6 +13,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
|
||||
import {useEnableMinimalShellModeForScreen} from '#/state/shell'
|
||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||
import {useIsWithinSplitView} from '#/screens/Messages/components/splitView/context'
|
||||
import {
|
||||
atoms as a,
|
||||
useBreakpoints,
|
||||
@@ -49,14 +45,20 @@ export const Screen = memo(function Screen({
|
||||
...props
|
||||
}: ScreenProps) {
|
||||
const {top} = useSafeAreaInsets()
|
||||
const {isWithinSplitView} = useIsWithinSplitView()
|
||||
|
||||
useEnableMinimalShellModeForScreen({enabled: minimalShell})
|
||||
|
||||
return (
|
||||
<>
|
||||
{IS_WEB && <WebCenterBorders />}
|
||||
{IS_WEB && !isWithinSplitView && <WebCenterBorders />}
|
||||
<View
|
||||
style={[a.util_screen_outer, {paddingTop: noInsetTop ? 0 : top}, style]}
|
||||
style={[
|
||||
a.util_screen_outer,
|
||||
{paddingTop: noInsetTop ? 0 : top},
|
||||
isWithinSplitView && {maxHeight: '100%'},
|
||||
style,
|
||||
]}
|
||||
{...props}
|
||||
/>
|
||||
</>
|
||||
@@ -85,6 +87,7 @@ export const Content = memo(
|
||||
) {
|
||||
const t = useTheme()
|
||||
const {footerHeight} = useShellLayout()
|
||||
const {isWithinSplitView} = useIsWithinSplitView()
|
||||
const animatedProps = useAnimatedProps(() => {
|
||||
return {
|
||||
scrollIndicatorInsets: {
|
||||
@@ -103,11 +106,18 @@ export const Content = memo(
|
||||
indicatorStyle={t.scheme === 'dark' ? 'white' : 'black'}
|
||||
// sets the scroll inset to the height of the footer
|
||||
animatedProps={animatedProps}
|
||||
style={[scrollViewStyles.common, style]}
|
||||
contentContainerStyle={[
|
||||
scrollViewStyles.contentContainer,
|
||||
contentContainerStyle,
|
||||
style={[
|
||||
a.w_full,
|
||||
isWithinSplitView &&
|
||||
web({
|
||||
flex: 1,
|
||||
overflowY: 'scroll',
|
||||
scrollbarWidth: 'thin',
|
||||
scrollbarColor: `${t.palette.contrast_100} transparent`,
|
||||
}),
|
||||
style,
|
||||
]}
|
||||
contentContainerStyle={[contentContainerStyle]}
|
||||
{...props}>
|
||||
{IS_WEB ? (
|
||||
<Center ignoreTabletLayoutOffset={ignoreTabletLayoutOffset}>
|
||||
@@ -122,45 +132,6 @@ export const Content = memo(
|
||||
}),
|
||||
)
|
||||
|
||||
const scrollViewStyles = StyleSheet.create({
|
||||
common: {
|
||||
width: '100%',
|
||||
},
|
||||
contentContainer: {
|
||||
paddingBottom: 100,
|
||||
},
|
||||
})
|
||||
|
||||
export type KeyboardAwareContentProps = KeyboardAwareScrollViewProps & {
|
||||
children: React.ReactNode
|
||||
contentContainerStyle?: StyleProp<ViewStyle>
|
||||
}
|
||||
|
||||
/**
|
||||
* Default scroll view for simple pages.
|
||||
*
|
||||
* BE SURE TO TEST THIS WHEN USING, it's untested as of writing this comment.
|
||||
*/
|
||||
export const KeyboardAwareContent = memo(function LayoutKeyboardAwareContent({
|
||||
children,
|
||||
style,
|
||||
contentContainerStyle,
|
||||
...props
|
||||
}: KeyboardAwareContentProps) {
|
||||
return (
|
||||
<KeyboardAwareScrollView
|
||||
style={[scrollViewStyles.common, style]}
|
||||
contentContainerStyle={[
|
||||
scrollViewStyles.contentContainer,
|
||||
contentContainerStyle,
|
||||
]}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
{...props}>
|
||||
{IS_WEB ? <Center>{children}</Center> : children}
|
||||
</KeyboardAwareScrollView>
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* Utility component to center content within the screen
|
||||
*/
|
||||
@@ -174,28 +145,30 @@ export const Center = memo(function LayoutCenter({
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {centerColumnOffset} = useLayoutBreakpoints()
|
||||
const {isWithinDialog} = useDialogContext()
|
||||
const {isWithinSplitView} = useIsWithinSplitView()
|
||||
const ctx = useMemo(() => ({isWithinOffsetView: true}), [])
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.mx_auto,
|
||||
!isWithinSplitView && a.mx_auto,
|
||||
gtMobile && {
|
||||
maxWidth: 600,
|
||||
},
|
||||
!isWithinOffsetView && {
|
||||
transform: [
|
||||
{
|
||||
translateX:
|
||||
centerColumnOffset &&
|
||||
!ignoreTabletLayoutOffset &&
|
||||
!isWithinDialog
|
||||
? CENTER_COLUMN_OFFSET
|
||||
: 0,
|
||||
},
|
||||
{translateX: web(SCROLLBAR_OFFSET) ?? 0},
|
||||
],
|
||||
},
|
||||
!isWithinOffsetView &&
|
||||
!isWithinSplitView && {
|
||||
transform: [
|
||||
{
|
||||
translateX:
|
||||
centerColumnOffset &&
|
||||
!ignoreTabletLayoutOffset &&
|
||||
!isWithinDialog
|
||||
? CENTER_COLUMN_OFFSET
|
||||
: 0,
|
||||
},
|
||||
{translateX: web(SCROLLBAR_OFFSET) ?? 0},
|
||||
],
|
||||
},
|
||||
style,
|
||||
]}
|
||||
{...props}>
|
||||
|
||||
Reference in New Issue
Block a user