Skip to content
Open
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
100 changes: 0 additions & 100 deletions apps/src/tests/issue-tests/Test3115.tsx

This file was deleted.

42 changes: 30 additions & 12 deletions apps/src/tests/issue-tests/Test3212/BottomTabsScenario.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
import React, { useState } from "react";
import { SCROLL_EDGE_EFFECT_DEFAULTS, ScrollEdgeEffects, ScrollEdgeEffectsConfigContext } from "./context";
import { NavigationContainer, NavigationIndependentTree } from "@react-navigation/native";
import { BottomTabsContainer } from "../../../shared/gamma/containers/bottom-tabs/BottomTabsContainer"
import { Config } from "./Config";
import { ScrollViewTemplate } from "./ScrollViewTemplate";
import { ScrollView } from "react-native";
import React, { useState } from 'react';
import {
SCROLL_EDGE_EFFECT_DEFAULTS,
ScrollEdgeEffects,
ScrollEdgeEffectsConfigContext,
} from './context';
import {
NavigationContainer,
NavigationIndependentTree,
} from '@react-navigation/native';
import { BottomTabsContainer } from '../../../shared/gamma/containers/bottom-tabs/BottomTabsContainer';
import { Config } from './Config';
import { ScrollViewTemplate } from './ScrollViewTemplate';
import { ScrollView } from 'react-native';

function ConfigComponent() {
// Add ScrollView for automatic insets which are missing in BottomTabsScreen
return (
<ScrollView>
<Config title='Stack / scrollEdgeEffects:'/>
<Config title="Stack / scrollEdgeEffects:" />
</ScrollView>
);
}

export function BottomTabsScenario() {
const [config, setConfig] = useState<ScrollEdgeEffects>({ ...SCROLL_EDGE_EFFECT_DEFAULTS });
const [config, setConfig] = useState<ScrollEdgeEffects>({
...SCROLL_EDGE_EFFECT_DEFAULTS,
});

return (
<NavigationIndependentTree>
<ScrollEdgeEffectsConfigContext.Provider value={{ config, setConfig }}>
<NavigationContainer>
<BottomTabsContainer
tabConfigs={[
{ component: ConfigComponent, tabScreenProps: { tabKey: 'config', title: 'Config' } },
// Using `freezeContents` for testing purposes, to make the ScrollView searching algorithm's success verifiable
{ component: ScrollViewTemplate, tabScreenProps: { tabKey: 'stack', title: 'Scroll', freezeContents: false, scrollEdgeEffects: config } },
{
component: ConfigComponent,
tabScreenProps: { tabKey: 'config', title: 'Config' },
},
{
component: ScrollViewTemplate,
tabScreenProps: {
tabKey: 'stack',
title: 'Scroll',
scrollEdgeEffects: config,
},
},
]}
/>
</NavigationContainer>
Expand Down
46 changes: 34 additions & 12 deletions apps/src/tests/issue-tests/Test3212/StackInBottomTabsScenario.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,47 @@
import React, { useCallback, useState } from "react";
import { SCROLL_EDGE_EFFECT_DEFAULTS, ScrollEdgeEffects, ScrollEdgeEffectsConfigContext } from "./context";
import { NavigationContainer } from "@react-navigation/native";
import { BottomTabsContainer } from "../../../shared/gamma/containers/bottom-tabs/BottomTabsContainer";
import { Config } from "./Config";
import { StackScenario } from "./StackScenario";
import { ScrollView } from "react-native";
import React, { useCallback, useState } from 'react';
import {
SCROLL_EDGE_EFFECT_DEFAULTS,
ScrollEdgeEffects,
ScrollEdgeEffectsConfigContext,
} from './context';
import { NavigationContainer } from '@react-navigation/native';
import { BottomTabsContainer } from '../../../shared/gamma/containers/bottom-tabs/BottomTabsContainer';
import { Config } from './Config';
import { StackScenario } from './StackScenario';
import { ScrollView } from 'react-native';

export function StackInBottomTabsScenario() {
const [config, setConfig] = useState<ScrollEdgeEffects>({ ...SCROLL_EDGE_EFFECT_DEFAULTS });
const [config, setConfig] = useState<ScrollEdgeEffects>({
...SCROLL_EDGE_EFFECT_DEFAULTS,
});

// Add ScrollView for automatic insets which are missing in BottomTabsScreen
const ConfigComponent = useCallback(() => <ScrollView><Config title='Outer BottomTabs / scrollEdgeEffects:' /></ScrollView>, []);
const ConfigComponent = useCallback(
() => (
<ScrollView>
<Config title="Outer BottomTabs / scrollEdgeEffects:" />
</ScrollView>
),
[],
);

return (
<ScrollEdgeEffectsConfigContext.Provider value={{ config, setConfig }}>
<NavigationContainer>
<BottomTabsContainer
tabConfigs={[
{ component: ConfigComponent, tabScreenProps: { tabKey: 'config', title: 'Config' } },
// Using `freezeContents` for testing purposes, to make the ScrollView searching algorithm's success verifiable
{ component: StackScenario, tabScreenProps: { tabKey: 'stack', title: 'Stack', freezeContents: false, scrollEdgeEffects: config } },
{
component: ConfigComponent,
tabScreenProps: { tabKey: 'config', title: 'Config' },
},
{
component: StackScenario,
tabScreenProps: {
tabKey: 'stack',
title: 'Stack',
scrollEdgeEffects: config,
},
},
]}
/>
</NavigationContainer>
Expand Down
11 changes: 8 additions & 3 deletions apps/src/tests/issue-tests/Test3236.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ function App() {
tabScreenProps: {
tabKey: 'Tab1',
title: 'Tab 1',
freezeContents: false,
icon: {
ios: {
type: 'sfSymbol',
name: 'sun.max',
},
android: {
type: 'drawableResource',
name: 'sunny',
},
},
iconResourceName: 'sunny',
},
component: makeTab('Tab 1', controllerMode, setControllerMode),
},
Expand All @@ -76,8 +78,11 @@ function App() {
type: 'sfSymbol',
name: 'snow',
},
android: {
type: 'drawableResource',
name: 'mode_cool',
},
},
iconResourceName: 'mode_cool',
},
component: makeTab('Tab 2', controllerMode, setControllerMode),
},
Expand Down
1 change: 0 additions & 1 deletion apps/src/tests/issue-tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ export { default as Test3045 } from './Test3045';
export { default as Test3074 } from './Test3074';
export { default as Test3093 } from './Test3093';
export { default as Test3111 } from './Test3111';
export { default as Test3115 } from './Test3115';
export { default as Test3168 } from './Test3168';
export { default as Test3173 } from './Test3173';
export { default as Test3212 } from './Test3212';
Expand Down
41 changes: 2 additions & 39 deletions src/components/tabs/TabsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import React from 'react';
import { Freeze } from 'react-freeze';
import {
Image,
ImageResolvedAssetSource,
Expand All @@ -12,15 +11,13 @@ import {
type ImageSourcePropType,
type NativeSyntheticEvent,
} from 'react-native';
import { freezeEnabled } from '../../core';
import BottomTabsScreenNativeComponent, {
type IconType,
type NativeProps,
type Appearance,
type ItemAppearance,
type ItemStateAppearance,
} from '../../fabric/bottom-tabs/BottomTabsScreenNativeComponent';
import { featureFlags } from '../../flags';
import type {
TabsScreenAppearance,
TabsScreenItemAppearance,
Expand Down Expand Up @@ -51,15 +48,12 @@ function TabsScreen(props: TabsScreenProps) {
}
}, []);

const [nativeViewIsVisible, setNativeViewIsVisible] = React.useState(false);

const {
onWillAppear,
onDidAppear,
onWillDisappear,
onDidDisappear,
isFocused = false,
freezeContents,
icon,
selectedIcon,
standardAppearance,
Expand All @@ -71,18 +65,11 @@ function TabsScreen(props: TabsScreenProps) {
...rest
} = props;

const shouldFreeze = shouldFreezeScreen(
nativeViewIsVisible,
isFocused,
freezeContents,
);

const onWillAppearCallback = React.useCallback(
(event: NativeSyntheticEvent<EmptyObject>) => {
bottomTabsDebugLog(
`TabsScreen [${componentNodeHandle.current}] onWillAppear received`,
);
setNativeViewIsVisible(true);
onWillAppear?.(event);
},
[onWillAppear],
Expand Down Expand Up @@ -113,7 +100,6 @@ function TabsScreen(props: TabsScreenProps) {
bottomTabsDebugLog(
`TabsScreen [${componentNodeHandle.current}] onDidDisappear received`,
);
setNativeViewIsVisible(false);
onDidDisappear?.(event);
},
[onDidDisappear],
Expand All @@ -122,7 +108,7 @@ function TabsScreen(props: TabsScreenProps) {
bottomTabsDebugLog(
`TabsScreen [${componentNodeHandle.current ?? -1}] render; tabKey: ${
rest.tabKey
} shouldFreeze: ${shouldFreeze}, isFocused: ${isFocused} nativeViewIsVisible: ${nativeViewIsVisible}`,
} isFocused: ${isFocused}`,
);

const iconProps = parseIconsToNativeProps(icon, selectedIcon);
Expand All @@ -149,9 +135,7 @@ function TabsScreen(props: TabsScreenProps) {
// eslint-disable-next-line camelcase -- we use sneak case experimental prefix
userInterfaceStyle={experimental_userInterfaceStyle}
{...rest}>
<Freeze freeze={shouldFreeze} placeholder={rest.placeholder}>
{rest.children}
</Freeze>
{rest.children}
</BottomTabsScreenNativeComponent>
);
}
Expand Down Expand Up @@ -221,27 +205,6 @@ function mapItemStateAppearanceToNativeProp(
};
}

function shouldFreezeScreen(
nativeViewVisible: boolean,
screenFocused: boolean,
freezeOverride: boolean | undefined,
) {
if (!freezeEnabled()) {
return false;
}

if (freezeOverride !== undefined) {
return freezeOverride;
}

if (featureFlags.experiment.controlledBottomTabs) {
// If the tabs are JS controlled, we want to freeze only when given view is not focused && it is not currently visible
return !nativeViewVisible && !screenFocused;
}

return !nativeViewVisible;
}

function parseAndroidIconToNativeProps(icon: PlatformIconAndroid | undefined): {
imageIconResource?: ImageResolvedAssetSource;
drawableIconResourceName?: string;
Expand Down
Loading
Loading