Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/components/Accordion/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import useThemeStyles from '@hooks/useThemeStyles';

import type {ReactNode} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import type {SharedValue} from 'react-native-reanimated';
Expand All @@ -26,7 +24,6 @@ type AccordionProps = {

function Accordion({isExpanded, children, duration = 300, isToggleTriggered, style}: AccordionProps) {
const height = useSharedValue(0);
const styles = useThemeStyles();

const derivedHeight = useDerivedValue(() => {
if (!isToggleTriggered.get()) {
Expand Down Expand Up @@ -69,9 +66,9 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty
};
}
return {
height: !isToggleTriggered.get() ? height.get() : derivedHeight.get(),
height: !isToggleTriggered.get() ? undefined : derivedHeight.get(),
opacity: derivedOpacity.get(),
overflow: isExpanded.get() ? 'visible' : 'hidden',
overflow: isToggleTriggered.get() ? 'hidden' : 'visible',
};
});

Expand All @@ -81,7 +78,6 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty
onLayout={(e) => {
height.set(e.nativeEvent.layout.height);
}}
style={[styles.pAbsolute, styles.l0, styles.r0, styles.t0]}
>
{children}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type ExternalScrollDriverProps = Omit<ScrollViewProps, 'ref'> & {
/** Where the table region starts within the parent page's scrollable content (px from the top). */
offsetTop?: number;

/** Native Views need an explicit cross-axis size inside the horizontal scroller. */
contentWidth?: number;

/** Imperative handle FlashList drives (scrollTo/scrollToEnd/getScrollableNode…). */
ref?: React.Ref<MinimalScrollRef>;
};
Expand All @@ -78,7 +81,7 @@ type ExternalScrollDriverProps = Omit<ScrollViewProps, 'ref'> & {
* corrections settle below the fold exactly like the parent-driven windowing. Must be a stable module-level component:
* FlashList memoizes its scroll component on identity.
*/
function ExternalScrollDriver({store, offsetTop = 0, onScroll, children, style, ref}: ExternalScrollDriverProps) {
function ExternalScrollDriver({store, offsetTop = 0, contentWidth, onScroll, children, style, ref}: ExternalScrollDriverProps) {
const nodeRef = useRef<View>(null);

useImperativeHandle(
Expand Down Expand Up @@ -123,7 +126,8 @@ function ExternalScrollDriver({store, offsetTop = 0, onScroll, children, style,
return (
<View
ref={nodeRef}
style={style}
testID="external-scroll-driver"
style={[style, {width: contentWidth}]}
>
{children}
</View>
Expand Down Expand Up @@ -231,7 +235,7 @@ function ExternalScrollFlashListTable<T>({
drawDistance={estimatedRowHeight * 12}
renderScrollComponent={ExternalScrollDriver}
// Consumed by ExternalScrollDriver (FlashList spreads overrideProps onto the scroll component).
overrideProps={{store, offsetTop}}
overrideProps={{store, offsetTop, contentWidth}}
// Treat the parent viewport as the list's window instead of measuring the (full-height) driver View.
overrideWindowSize={{width: contentWidth, height: viewportHeight}}
// Grow to content height and don't clip — the parent page owns vertical scroll, so the list's own
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ function WideInboxTabButton({selectedTab, statusIndicatorColor, accessibilityLab
role={CONST.ROLE.TAB}
accessibilityLabel={accessibilityLabel}
accessibilityState={{selected: selectedTab === NAVIGATION_TABS.INBOX}}
wrapperStyle={styles.leftNavigationTabBarItem}
style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function InsightsTabButton({selectedTab, isWideLayout}: InsightsTabButtonProps)
role={CONST.ROLE.TAB}
accessibilityLabel={translate('common.insights')}
accessibilityState={{selected: isSelected}}
wrapperStyle={styles.leftNavigationTabBarItem}
style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INSIGHTS}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function SearchTabButton({selectedTab, isWideLayout}: SearchTabButtonProps) {
role={CONST.ROLE.TAB}
accessibilityLabel={translate('common.spend')}
accessibilityState={searchAccessibilityState}
wrapperStyle={styles.leftNavigationTabBarItem}
style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.REPORTS}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function WorkspacesTabButton({selectedTab, isWideLayout}: WorkspacesTabButtonPro
role={CONST.ROLE.TAB}
accessibilityLabel={`${translate('common.workspacesTabTitle')}${workspacesTabIndicatorStatus ? `. ${translate('common.yourReviewIsRequired')}` : ''}`}
accessibilityState={workspacesAccessibilityState}
wrapperStyle={styles.leftNavigationTabBarItem}
style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.WORKSPACES}
>
Expand Down
7 changes: 5 additions & 2 deletions src/components/Navigation/NavigationTabBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';

Expand Down Expand Up @@ -50,6 +51,7 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home']);

const {shouldUseNarrowLayout} = useResponsiveLayout();
const {paddingTop, paddingBottom} = useSafeAreaPaddings(true);

const StyleUtils = useStyleUtils();

Expand Down Expand Up @@ -80,7 +82,7 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
<Hoverable shouldUseNativeHoverEvents>
{(isSidebarHovered) => (
<View
style={styles.leftNavigationTabBarContainer}
style={[styles.leftNavigationTabBarContainer, styles.navigationTabBarSafeAreaInsets(paddingTop, paddingBottom)]}
testID="NavigationTabBar"
>
<View style={styles.flex1}>
Expand All @@ -103,6 +105,7 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
onPress={navigateToNewDotHome}
role={CONST.ROLE.TAB}
accessibilityLabel={translate('common.home')}
wrapperStyle={styles.leftNavigationTabBarItem}
style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.HOME}
>
Expand Down Expand Up @@ -139,7 +142,7 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
onPress={navigateToSettings}
/>
</View>
<View style={styles.leftNavigationTabBarFAB}>
<View style={[styles.leftNavigationTabBarFAB, styles.leftNavigationTabBarFABPosition(paddingBottom)]}>
<SupportalSwitcherButton isSidebarHovered={isSidebarHovered} />
<NavigationTabBarFloatingActionButton />
</View>
Expand Down
8 changes: 6 additions & 2 deletions src/components/Navigation/SearchSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {ParamListBase} from '@react-navigation/native';
import React, {useEffect} from 'react';
import {View} from 'react-native';
import Animated from 'react-native-reanimated';
import {SafeAreaView} from 'react-native-safe-area-context';

import {
useSearchSidebarCollapse,
Expand Down Expand Up @@ -109,7 +110,10 @@ function SearchSidebar({state}: SearchSidebarProps) {
<Animated.View style={layoutSpacerStyle}>
<Hoverable onHoverOut={endPeek}>
<Animated.View style={[styles.searchSidebar, styles.stickToLeft, styles.zIndex1, visualSidebarWidthStyle]}>
<View style={styles.flex1}>
<SafeAreaView
style={styles.flex1}
edges={['top']}
>
<TopBar
shouldShowLoadingBar={shouldShowLoadingState || shouldShowLoadingBarForReports}
breadcrumbLabel={translate('common.spend')}
Expand All @@ -124,7 +128,7 @@ function SearchSidebar({state}: SearchSidebarProps) {
<SearchTypeMenuWide />
</View>
</Hoverable>
</View>
</SafeAreaView>
</Animated.View>
</Hoverable>
</Animated.View>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Navigation/SearchSidebarCollapseStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const TOGGLE_BUTTON_COLLAPSED_TRANSLATE_X = -10;

const layoutTransitionStyle: ViewStyle =
Platform.OS === 'web' ? {transition: `width ${SEARCH_SIDEBAR_COLLAPSE_ANIMATION_DURATION_MS}ms ease, margin-left ${SEARCH_SIDEBAR_COLLAPSE_ANIMATION_DURATION_MS}ms ease`} : {};
const layoutPositionStyle: ViewStyle = Platform.OS === 'web' ? {} : {position: 'absolute', top: 0, bottom: 0, left: 0};
const fadeTransitionStyle: ViewStyle =
Platform.OS === 'web' ? {transition: `opacity ${SEARCH_SIDEBAR_COLLAPSE_ANIMATION_DURATION_MS}ms ease, transform ${SEARCH_SIDEBAR_COLLAPSE_ANIMATION_DURATION_MS}ms ease`} : {};

Expand Down Expand Up @@ -89,7 +90,7 @@ function useSearchSidebarCollapse() {
function useSearchSidebarLayoutWidthStyle() {
const {isCollapsed: collapsed} = useSearchSidebarCollapse();

return useMemo<ViewStyle>(() => ({...layoutTransitionStyle, height: '100%', width: getSearchSidebarWidth(collapsed ? 1 : 0)}), [collapsed]);
return useMemo<ViewStyle>(() => ({...layoutTransitionStyle, ...layoutPositionStyle, height: '100%', width: getSearchSidebarWidth(collapsed ? 1 : 0)}), [collapsed]);
}

function useSearchSidebarVisualWidthStyle() {
Expand Down
4 changes: 3 additions & 1 deletion src/components/SidePanel/SidePanelContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import React, {createContext, useEffect, useRef, useState} from 'react';
// eslint-disable-next-line no-restricted-imports
import {Animated} from 'react-native';

import isSidePanelReportSupported from './isSidePanelReportSupported';

type SidePanelStateContextProps = {
isSidePanelTransitionEnded: boolean;
isSidePanelHiddenOrLargeScreen: boolean;
Expand Down Expand Up @@ -72,7 +74,7 @@ function SidePanelContextProvider({children}: PropsWithChildren) {
const {shouldHideSidePanel, shouldHideSidePanelBackdrop, shouldHideHelpButton, isSidePanelHiddenOrLargeScreen, sidePanelNVP} = useSidePanelDisplayStatus();
const shouldHideToolTip = isExtraLargeScreenWidth ? !isSidePanelTransitionEnded : !shouldHideSidePanel;

const shouldApplySidePanelOffset = isExtraLargeScreenWidth && !shouldHideSidePanel;
const shouldApplySidePanelOffset = isSidePanelReportSupported && isExtraLargeScreenWidth && !shouldHideSidePanel;
const sidePanelOffset = useRef(new Animated.Value(shouldApplySidePanelOffset ? variables.sidePanelWidth : 0));
const sidePanelTranslateX = useRef(new Animated.Value(shouldHideSidePanel ? sidePanelWidth : 0));
const sidePanelWidthRef = useRef(sidePanelWidth);
Expand Down
59 changes: 0 additions & 59 deletions src/components/WideRHPContextProvider/index.native.tsx

This file was deleted.

This file was deleted.

46 changes: 26 additions & 20 deletions src/components/WideRHPContextProvider/useShouldRenderOverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import {useEffect, useRef, useState} from 'react';
// We use Animated for all functionality related to wide RHP to make it easier
// to interact with react-navigation components (e.g., CardContainer, interpolator), which also use Animated.
// eslint-disable-next-line no-restricted-imports
import {Animated} from 'react-native';
import {Animated, Platform} from 'react-native';

const OVERLAY_TIMING_DURATION = 300;
// These values only drive opacity, so native can animate them while the incoming report renders on JS.
const USE_NATIVE_DRIVER = Platform.OS !== 'web';

function useShouldRenderOverlay(condition: boolean, overlayProgress: Animated.Value) {
const [shouldRenderOverlay, setShouldRenderOverlay] = useState(false);
Expand All @@ -15,26 +17,30 @@ function useShouldRenderOverlay(condition: boolean, overlayProgress: Animated.Va
useEffect(() => {
conditionRef.current = condition;

if (condition) {
setShouldRenderOverlay(true);
Animated.timing(overlayProgress, {
toValue: 1,
duration: OVERLAY_TIMING_DURATION,
useNativeDriver: false,
}).start();
} else {
Animated.timing(overlayProgress, {
toValue: 0,
duration: OVERLAY_TIMING_DURATION,
useNativeDriver: false,
}).start(() => {
if (conditionRef.current) {
return;
}
setShouldRenderOverlay(false);
});
// Commit the transparent overlay before starting its fade. Report rendering can otherwise
// consume the animation duration before the conditionally rendered overlay even mounts.
if (!shouldRenderOverlay) {
overlayProgress.setValue(0);
if (condition) {
setShouldRenderOverlay(true);
}
return;
}
}, [condition, overlayProgress]);

const animation = Animated.timing(overlayProgress, {
toValue: condition ? 1 : 0,
duration: OVERLAY_TIMING_DURATION,
useNativeDriver: USE_NATIVE_DRIVER,
});
animation.start(({finished}) => {
if (!finished || conditionRef.current) {
return;
}
setShouldRenderOverlay(false);
});

return () => animation.stop();
}, [condition, overlayProgress, shouldRenderOverlay]);

return shouldRenderOverlay;
}
Expand Down
8 changes: 0 additions & 8 deletions src/components/WideRHPOverlayWrapper/index.native.ts

This file was deleted.

Loading
Loading