make scrollview automatically adapt to footer height
This commit is contained in:
+34
-35
@@ -232,42 +232,41 @@ function App() {
|
||||
* that is set up in the InnerApp component above.
|
||||
*/
|
||||
return (
|
||||
<Geo.Provider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider preload={false}>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<BottomSheetProvider>
|
||||
<StarterPackProvider>
|
||||
<SafeAreaProvider
|
||||
initialMetrics={initialWindowMetrics}>
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
||||
<Geo.Provider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider preload={false}>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<BottomSheetProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
</SafeAreaProvider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
</SafeAreaProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+53
-50
@@ -4,7 +4,10 @@ import './style.css'
|
||||
|
||||
import {Fragment, useEffect, useState} from 'react'
|
||||
import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller'
|
||||
import {SafeAreaProvider} from 'react-native-safe-area-context'
|
||||
import {
|
||||
initialWindowMetrics,
|
||||
SafeAreaProvider,
|
||||
} from 'react-native-safe-area-context'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import * as Sentry from '@sentry/react-native'
|
||||
|
||||
@@ -149,24 +152,22 @@ function InnerApp() {
|
||||
<UnreadNotifsProvider>
|
||||
<BackgroundNotificationPreferencesProvider>
|
||||
<MutedThreadsProvider>
|
||||
<SafeAreaProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceConfigProvider>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<IntentDialogProvider>
|
||||
<TranslateOnDeviceProvider>
|
||||
<HotkeysProvider>
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</HotkeysProvider>
|
||||
</TranslateOnDeviceProvider>
|
||||
</IntentDialogProvider>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceConfigProvider>
|
||||
</ProgressGuideProvider>
|
||||
</SafeAreaProvider>
|
||||
<ProgressGuideProvider>
|
||||
<ServiceConfigProvider>
|
||||
<EmailVerificationProvider>
|
||||
<HideBottomBarBorderProvider>
|
||||
<IntentDialogProvider>
|
||||
<TranslateOnDeviceProvider>
|
||||
<HotkeysProvider>
|
||||
<Shell />
|
||||
<ToastOutlet />
|
||||
</HotkeysProvider>
|
||||
</TranslateOnDeviceProvider>
|
||||
</IntentDialogProvider>
|
||||
</HideBottomBarBorderProvider>
|
||||
</EmailVerificationProvider>
|
||||
</ServiceConfigProvider>
|
||||
</ProgressGuideProvider>
|
||||
</MutedThreadsProvider>
|
||||
</BackgroundNotificationPreferencesProvider>
|
||||
</UnreadNotifsProvider>
|
||||
@@ -211,37 +212,39 @@ function App() {
|
||||
* that is set up in the InnerApp component above.
|
||||
*/
|
||||
return (
|
||||
<Geo.Provider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
||||
<Geo.Provider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
</SafeAreaProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import {forwardRef, memo, useContext, useMemo} from 'react'
|
||||
import {
|
||||
ScrollView,
|
||||
type ScrollViewProps,
|
||||
type StyleProp,
|
||||
StyleSheet,
|
||||
View,
|
||||
@@ -10,16 +12,14 @@ import {
|
||||
KeyboardAwareScrollView,
|
||||
type KeyboardAwareScrollViewProps,
|
||||
} from 'react-native-keyboard-controller'
|
||||
import Animated, {
|
||||
type AnimatedScrollViewProps,
|
||||
useAnimatedProps,
|
||||
} from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
|
||||
import {useEnableMinimalShellModeForScreen} from '#/state/shell'
|
||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||
import {
|
||||
android,
|
||||
atoms as a,
|
||||
ios,
|
||||
useBreakpoints,
|
||||
useLayoutBreakpoints,
|
||||
useTheme,
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import {useDialogContext} from '#/components/Dialog'
|
||||
import {CENTER_COLUMN_OFFSET, SCROLLBAR_OFFSET} from '#/components/Layout/const'
|
||||
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {IS_IOS, IS_WEB} from '#/env'
|
||||
|
||||
export * from '#/components/Layout/const'
|
||||
export * as Header from '#/components/Layout/Header'
|
||||
@@ -63,9 +63,7 @@ export const Screen = memo(function Screen({
|
||||
)
|
||||
})
|
||||
|
||||
export type ContentProps = AnimatedScrollViewProps & {
|
||||
style?: StyleProp<ViewStyle>
|
||||
contentContainerStyle?: StyleProp<ViewStyle>
|
||||
export type ContentProps = ScrollViewProps & {
|
||||
ignoreTabletLayoutOffset?: boolean
|
||||
}
|
||||
|
||||
@@ -73,7 +71,7 @@ export type ContentProps = AnimatedScrollViewProps & {
|
||||
* Default scroll view for simple pages
|
||||
*/
|
||||
export const Content = memo(
|
||||
forwardRef<Animated.ScrollView, ContentProps>(function Content(
|
||||
forwardRef<ScrollView, ContentProps>(function Content(
|
||||
{
|
||||
children,
|
||||
style,
|
||||
@@ -85,39 +83,33 @@ export const Content = memo(
|
||||
) {
|
||||
const t = useTheme()
|
||||
const {footerHeight} = useShellLayout()
|
||||
const animatedProps = useAnimatedProps(() => {
|
||||
return {
|
||||
scrollIndicatorInsets: {
|
||||
bottom: footerHeight.get(),
|
||||
top: 0,
|
||||
right: 1,
|
||||
},
|
||||
} satisfies AnimatedScrollViewProps
|
||||
})
|
||||
|
||||
return (
|
||||
<Animated.ScrollView
|
||||
<ScrollView
|
||||
ref={ref}
|
||||
id="content"
|
||||
automaticallyAdjustsScrollIndicatorInsets={false}
|
||||
scrollIndicatorInsets={{
|
||||
bottom: footerHeight,
|
||||
top: 0,
|
||||
right: 1,
|
||||
}}
|
||||
indicatorStyle={t.scheme === 'dark' ? 'white' : 'black'}
|
||||
// sets the scroll inset to the height of the footer
|
||||
animatedProps={animatedProps}
|
||||
style={[scrollViewStyles.common, style]}
|
||||
contentInset={ios({top: 0, left: 0, bottom: footerHeight, right: 0})}
|
||||
contentContainerStyle={[
|
||||
scrollViewStyles.contentContainer,
|
||||
!IS_IOS && {paddingBottom: footerHeight},
|
||||
contentContainerStyle,
|
||||
]}
|
||||
{...props}>
|
||||
{IS_WEB ? (
|
||||
<Center ignoreTabletLayoutOffset={ignoreTabletLayoutOffset}>
|
||||
{/* @ts-expect-error web only -esb */}
|
||||
{children}
|
||||
</Center>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Animated.ScrollView>
|
||||
</ScrollView>
|
||||
)
|
||||
}),
|
||||
)
|
||||
@@ -126,9 +118,6 @@ const scrollViewStyles = StyleSheet.create({
|
||||
common: {
|
||||
width: '100%',
|
||||
},
|
||||
contentContainer: {
|
||||
paddingBottom: 100,
|
||||
},
|
||||
})
|
||||
|
||||
export type KeyboardAwareContentProps = KeyboardAwareScrollViewProps & {
|
||||
@@ -147,11 +136,14 @@ export const KeyboardAwareContent = memo(function LayoutKeyboardAwareContent({
|
||||
contentContainerStyle,
|
||||
...props
|
||||
}: KeyboardAwareContentProps) {
|
||||
const {footerHeight} = useShellLayout()
|
||||
return (
|
||||
<KeyboardAwareScrollView
|
||||
style={[scrollViewStyles.common, style]}
|
||||
contentInset={ios({top: 0, left: 0, bottom: footerHeight, right: 0})}
|
||||
contentContainerStyle={[
|
||||
scrollViewStyles.contentContainer,
|
||||
android({paddingBottom: footerHeight}),
|
||||
web({paddingBottom: footerHeight}),
|
||||
contentContainerStyle,
|
||||
]}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
|
||||
@@ -68,11 +68,7 @@ export function useMinimalShellFooterTransform() {
|
||||
opacity: Math.pow(1 - footerModeValue, 2),
|
||||
transform: [
|
||||
{
|
||||
translateY: interpolate(
|
||||
footerModeValue,
|
||||
[0, 1],
|
||||
[0, footerHeight.get()],
|
||||
),
|
||||
translateY: interpolate(footerModeValue, [0, 1], [0, footerHeight]),
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import {useWindowDimensions, View} from 'react-native'
|
||||
import Animated, {useAnimatedStyle} from 'react-native-reanimated'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||
@@ -69,6 +68,8 @@ export function PostThread({uri}: {uri: string}) {
|
||||
hasSession,
|
||||
)
|
||||
|
||||
const [promptHeight, setPromptHeight] = useState(43)
|
||||
|
||||
/*
|
||||
* One query to rule them all
|
||||
*/
|
||||
@@ -543,6 +544,7 @@ export function PostThread({uri}: {uri: string}) {
|
||||
)
|
||||
|
||||
const defaultListFooterHeight = hasParents ? windowHeight - 200 : undefined
|
||||
const hasPrompt = !gtMobile && canReply && hasSession
|
||||
|
||||
return (
|
||||
<PostThreadContextProvider context={thread.context}>
|
||||
@@ -630,29 +632,37 @@ export function PostThread({uri}: {uri: string}) {
|
||||
* Default: 50
|
||||
*/
|
||||
updateCellsBatchingPeriod={100}
|
||||
footerExtensionHeight={hasPrompt ? promptHeight : 0}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!gtMobile && canReply && hasSession && (
|
||||
<MobileComposePrompt onPressReply={onReplyToAnchor} />
|
||||
{hasPrompt && (
|
||||
<MobileComposePrompt
|
||||
onPressReply={onReplyToAnchor}
|
||||
onLayout={evt =>
|
||||
setPromptHeight(Math.round(evt.nativeEvent.layout.height))
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</PostThreadContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function MobileComposePrompt({onPressReply}: {onPressReply: () => unknown}) {
|
||||
function MobileComposePrompt({
|
||||
onPressReply,
|
||||
onLayout,
|
||||
}: {
|
||||
onPressReply: () => unknown
|
||||
onLayout?: (event: LayoutChangeEvent) => void
|
||||
}) {
|
||||
const {footerHeight} = useShellLayout()
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
bottom: footerHeight.get(),
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<Animated.View style={[a.fixed, a.left_0, a.right_0, animatedStyle]}>
|
||||
<View
|
||||
style={[a.fixed, a.left_0, a.right_0, {bottom: footerHeight}]}
|
||||
onLayout={onLayout}>
|
||||
<ThreadComposePrompt onPressCompose={onPressReply} />
|
||||
</Animated.View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import {createContext, useContext, useMemo} from 'react'
|
||||
import {createContext, useContext, useMemo, useState} from 'react'
|
||||
import {type SharedValue, useSharedValue} from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
|
||||
type StateContext = {
|
||||
import {clamp} from '#/lib/numbers'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {atoms as a, platform, useBreakpoints} from '#/alf'
|
||||
|
||||
type LayoutContextValue = {
|
||||
headerHeight: SharedValue<number>
|
||||
footerHeight: SharedValue<number>
|
||||
footerHeight: number
|
||||
setFooterHeight: (height: number) => void
|
||||
}
|
||||
|
||||
const stateContext = createContext<StateContext>({
|
||||
const LayoutContext = createContext<LayoutContextValue>({
|
||||
headerHeight: {
|
||||
value: 0,
|
||||
addListener() {},
|
||||
@@ -17,34 +23,46 @@ const stateContext = createContext<StateContext>({
|
||||
},
|
||||
set() {},
|
||||
},
|
||||
footerHeight: {
|
||||
value: 0,
|
||||
addListener() {},
|
||||
removeListener() {},
|
||||
modify() {},
|
||||
get() {
|
||||
return 0
|
||||
},
|
||||
set() {},
|
||||
},
|
||||
footerHeight: 0,
|
||||
setFooterHeight: () => {},
|
||||
})
|
||||
stateContext.displayName = 'ShellLayoutContext'
|
||||
LayoutContext.displayName = 'ShellLayoutContext'
|
||||
|
||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
const headerHeight = useSharedValue(0)
|
||||
const footerHeight = useSharedValue(0)
|
||||
const insets = useSafeAreaInsets()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const [footerHeight, setFooterHeight] = useState(() =>
|
||||
platform({
|
||||
// try and precisely guess the footer height, then round it to 4 decimal places
|
||||
// to remove floating point imprecision. if we can guess it exactly,
|
||||
// we get to skip a rerender
|
||||
native: round4dp(
|
||||
47 + a.border.borderWidth + clamp(insets.bottom, 15, 60),
|
||||
),
|
||||
web: 58,
|
||||
default: 0,
|
||||
}),
|
||||
)
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
headerHeight,
|
||||
footerHeight,
|
||||
footerHeight: isWeb && gtMobile ? 0 : footerHeight,
|
||||
setFooterHeight: (height: number) => setFooterHeight(round4dp(height)),
|
||||
}),
|
||||
[headerHeight, footerHeight],
|
||||
[headerHeight, footerHeight, setFooterHeight, gtMobile],
|
||||
)
|
||||
|
||||
return <stateContext.Provider value={value}>{children}</stateContext.Provider>
|
||||
return (
|
||||
<LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useShellLayout() {
|
||||
return useContext(stateContext)
|
||||
return useContext(LayoutContext)
|
||||
}
|
||||
|
||||
function round4dp(value: number) {
|
||||
return Math.round(value * 10000) / 10000
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@ import {useDedupe} from '#/lib/hooks/useDedupe'
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {useScrollHandlers} from '#/lib/ScrollContext'
|
||||
import {addStyle} from '#/lib/styles'
|
||||
import {useTheme} from '#/alf'
|
||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||
import {ios, useTheme} from '#/alf'
|
||||
import {useLightbox} from '#/components/Lightbox/state'
|
||||
import {IS_IOS} from '#/env'
|
||||
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||
import {FlatList_INTERNAL} from './Views'
|
||||
|
||||
export type ListMethods = FlatList_INTERNAL
|
||||
@@ -39,6 +40,7 @@ export type ListProps<ItemT = any> = Omit<
|
||||
disableFullWindowScroll?: boolean
|
||||
sideBorders?: boolean
|
||||
progressViewOffset?: number
|
||||
footerExtensionHeight?: number
|
||||
}
|
||||
export type ListRef = React.RefObject<FlatList_INTERNAL | null>
|
||||
|
||||
@@ -55,6 +57,8 @@ let List = forwardRef<ListMethods, ListProps>(
|
||||
style,
|
||||
progressViewOffset,
|
||||
automaticallyAdjustsScrollIndicatorInsets = false,
|
||||
contentContainerStyle,
|
||||
footerExtensionHeight = 0,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
@@ -63,6 +67,7 @@ let List = forwardRef<ListMethods, ListProps>(
|
||||
const t = useTheme()
|
||||
const dedupe = useDedupe(400)
|
||||
const scrollsToTop = useAllowScrollToTop()
|
||||
const {footerHeight} = useShellLayout()
|
||||
|
||||
const handleScrolledDownChange = useNonReactiveCallback(
|
||||
(didScrollDown: boolean) => {
|
||||
@@ -159,14 +164,26 @@ let List = forwardRef<ListMethods, ListProps>(
|
||||
onViewableItemsChanged={onViewableItemsChanged}
|
||||
viewabilityConfig={viewabilityConfig}
|
||||
{...props}
|
||||
contentContainerStyle={[
|
||||
IS_ANDROID && {paddingBottom: footerHeight + footerExtensionHeight},
|
||||
contentContainerStyle,
|
||||
]}
|
||||
automaticallyAdjustsScrollIndicatorInsets={
|
||||
automaticallyAdjustsScrollIndicatorInsets
|
||||
}
|
||||
scrollIndicatorInsets={{
|
||||
top: headerOffset,
|
||||
right: 1,
|
||||
bottom: footerHeight + footerExtensionHeight,
|
||||
...props.scrollIndicatorInsets,
|
||||
}}
|
||||
contentInset={ios({
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: footerHeight + footerExtensionHeight,
|
||||
...props.contentInset,
|
||||
})}
|
||||
indicatorStyle={t.scheme === 'dark' ? 'white' : 'black'}
|
||||
contentOffset={contentOffset}
|
||||
refreshControl={refreshControl}
|
||||
|
||||
@@ -61,7 +61,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const safeAreaInsets = useSafeAreaInsets()
|
||||
const {footerHeight} = useShellLayout()
|
||||
const {setFooterHeight} = useShellLayout()
|
||||
const {isAtHome, isAtSearch, isAtNotifications, isAtMyProfile, isAtMessages} =
|
||||
useNavigationTabState()
|
||||
const numUnreadNotifications = useUnreadNotifications()
|
||||
@@ -154,9 +154,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
{paddingBottom: clamp(safeAreaInsets.bottom, 15, 60)},
|
||||
footerMinimalShellTransform,
|
||||
]}
|
||||
onLayout={e => {
|
||||
footerHeight.set(e.nativeEvent.layout.height)
|
||||
}}>
|
||||
onLayout={evt => setFooterHeight(evt.nativeEvent.layout.height)}>
|
||||
{hasSession ? (
|
||||
<>
|
||||
<Btn
|
||||
|
||||
@@ -53,7 +53,7 @@ export function BottomBarWeb() {
|
||||
const footerMinimalShellTransform = useMinimalShellFooterTransform()
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
const {footerHeight} = useShellLayout()
|
||||
const {setFooterHeight} = useShellLayout()
|
||||
const hideBorder = useHideBottomBarBorder()
|
||||
const accountSwitchControl = useDialogControl()
|
||||
const {data: profile} = useProfileQuery({did: currentAccount?.did})
|
||||
@@ -93,7 +93,7 @@ export function BottomBarWeb() {
|
||||
: t.atoms.border_contrast_low,
|
||||
footerMinimalShellTransform,
|
||||
]}
|
||||
onLayout={event => footerHeight.set(event.nativeEvent.layout.height)}>
|
||||
onLayout={event => setFooterHeight(event.nativeEvent.layout.height)}>
|
||||
{hasSession ? (
|
||||
<>
|
||||
<NavItem routeName="Home" href="/">
|
||||
|
||||
Reference in New Issue
Block a user