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
21 changes: 20 additions & 1 deletion react-native-harmony-screens/src/components/Screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
isNativePlatformSupported,
screensEnabled,
} from "../core";
import { ScreenOrderContext } from "./ScreenContainer";

// Native components
import ScreenNativeComponent, {
Expand Down Expand Up @@ -162,6 +163,15 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
const innerRef = React.useRef<ViewConfig | null>(null);
React.useImperativeHandle(ref, () => innerRef.current!, []);
const prevActivityState = usePrevious(props.activityState);

// RNOH patch: Get declaration order for HarmonyOS only
const isHarmony = (Platform.OS as string) === "harmony";
const screenOrderContext = isHarmony ? React.useContext(ScreenOrderContext) : null;
const declarationIndexRef = React.useRef<number | null>(null);
// Initialize synchronously to ensure zIndex is set before first render
if (isHarmony && screenOrderContext && declarationIndexRef.current === null) {
declarationIndexRef.current = screenOrderContext.getNextIndex();
}

const setRef = (ref: ViewConfig) => {
innerRef.current = ref;
Expand Down Expand Up @@ -289,6 +299,15 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
freezeOnBlur &&
(shouldFreeze !== undefined ? shouldFreeze : activityState === 0);

// RNOH patch: HarmonyOS-specific styles
const harmonyStyle = isHarmony && activityState !== undefined ? {
position: "absolute" as const,
top: 0, left: 0, right: 0, bottom: 0,
opacity: activityState === 0 ? 0 : 1,
pointerEvents: activityState === 0 ? ("none" as const) : activityState === 1 ? ("none" as const) : ("auto" as const),
zIndex: activityState === 0 ? 0 : (declarationIndexRef.current !== null ? declarationIndexRef.current : 1),
} : undefined;

return (
<DelayedFreeze freeze={freeze}>
<AnimatedScreen
Expand All @@ -313,7 +332,7 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
// https://github.com/software-mansion/react-native-screens/issues/2345
// With below change of zIndex, we force RN diffing mechanism to NOT include detaching and attaching mutation in one transaction.
// Detailed information can be found here https://github.com/software-mansion/react-native-screens/pull/2351
style={[style, { zIndex: undefined, paddingTop: headerHeight, }]}
style={harmonyStyle ? [style, { paddingTop: headerHeight }, harmonyStyle] : [style, { zIndex: undefined, paddingTop: headerHeight }]}
activityState={activityState}
sheetAllowedDetents={resolvedSheetAllowedDetents}
sheetLargestUndimmedDetent={resolvedSheetLargestUndimmedDetent}
Expand Down
23 changes: 19 additions & 4 deletions react-native-harmony-screens/src/components/ScreenContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,35 @@ import { isNativePlatformSupported, screensEnabled } from "../core";
import ScreenContainerNativeComponent from "../specs/ScreenContainerNativeComponent";
import ScreenNavigationContainerNativeComponent from "../specs/ScreenNavigationContainerNativeComponent";

// RNOH patch: Context for HarmonyOS only
const ScreenOrderContext = React.createContext<{ getNextIndex: () => number } | null>(null);

function ScreenContainer(props: ScreenContainerProps) {
const { enabled = screensEnabled(), hasTwoStates, ...rest } = props;
const { enabled = screensEnabled(), hasTwoStates, style, children, ...rest } = props;
const isHarmony = (Platform.OS as string) === "harmony";

// RNOH patch: Track declaration order for HarmonyOS only
const screenIndexRef = React.useRef(1);
const getNextIndex = React.useCallback(() => screenIndexRef.current++, []);
React.useEffect(() => { screenIndexRef.current = 1; }, [children]);
const contextValue = React.useMemo(() => ({ getNextIndex }), [getNextIndex]);

if (enabled && isNativePlatformSupported) {
if (hasTwoStates) {
const ScreenNavigationContainer =
Platform.OS === "ios"
? ScreenNavigationContainerNativeComponent
: ScreenContainerNativeComponent;
return <ScreenNavigationContainer {...rest} />;
const container = <ScreenNavigationContainer {...rest} style={isHarmony ? [{ position: "relative" as const }, style] : style}>{children}</ScreenNavigationContainer>;
return isHarmony ? <ScreenOrderContext.Provider value={contextValue}>{container}</ScreenOrderContext.Provider> : container;
}
return <ScreenContainerNativeComponent {...rest} />;
const container = <ScreenContainerNativeComponent {...rest} style={isHarmony ? [{ position: "relative" as const }, style] : style}>{children}</ScreenContainerNativeComponent>;
return isHarmony ? <ScreenOrderContext.Provider value={contextValue}>{container}</ScreenOrderContext.Provider> : container;
}
return <View {...rest} />;
const view = <View {...rest} style={isHarmony ? [{ position: "relative" as const }, style] : style}>{children}</View>;
return isHarmony ? <ScreenOrderContext.Provider value={contextValue}>{view}</ScreenOrderContext.Provider> : view;
}

export { ScreenOrderContext };

export default ScreenContainer;
2 changes: 1 addition & 1 deletion react-native-harmony-screens/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export {
} from "react-native-screens/src/components/ScreenStackHeaderConfig";

export { default as SearchBar } from 'react-native-screens/src/components/SearchBar';
export { default as ScreenContainer } from 'react-native-screens/src/components/ScreenContainer';
export { default as ScreenContainer } from './components/ScreenContainer';
export { default as ScreenStack } from './components/ScreenStack';
export { default as ScreenStackItem } from './components/ScreenStackItem';
export { default as FullWindowOverlay } from "react-native-screens/src/components/FullWindowOverlay";
Expand Down