Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -1315,3 +1315,156 @@ test('parent-child switching from unflattened-flattened to flattened-unflattened
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
]);
});

test('unflattening and creating a subtree that is partially culled', () => {
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});

// First render with a flattened view container that is visible.
Fantom.runTask(() => {
root.render(
<ScrollView
style={{height: 100, width: 100}}
contentOffset={{x: 0, y: 111}}>
<View style={{marginTop: 200}} />
</ScrollView>,
);
});

expect(root.takeMountingManagerLogs()).toEqual([
'Update {type: "RootView", nativeID: (root)}',
'Create {type: "ScrollView", nativeID: (N/A)}',
'Create {type: "View", nativeID: (N/A)}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);

let maybeNode = null;

// Now update opacity to unflattned the container and add a child that has a culled descendant.
Fantom.runTask(() => {
root.render(
<ScrollView
style={{height: 100, width: 100}}
ref={node => {
maybeNode = node;
}}
contentOffset={{x: 0, y: 111}}>
<View
style={{
marginTop: 200,
opacity: 0.5, // Force unflattening
}}>
<View
nativeID="child"
style={{
marginTop: 10,
height: 10,
width: 10,
}}>
<View
nativeID="grandchild"
style={{
marginTop: 5,
height: 5,
width: 5,
}}
/>
</View>
</View>
</ScrollView>,
);
});

expect(root.takeMountingManagerLogs()).toEqual([
'Update {type: "ScrollView", nativeID: (N/A)}',
'Update {type: "View", nativeID: (N/A)}',
'Create {type: "View", nativeID: (N/A)}',
'Create {type: "View", nativeID: "child"}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
]);

const element = ensureInstance(maybeNode, ReactNativeElement);

// Scroll down to see the grandchild.
Fantom.scrollTo(element, {
x: 0,
y: 115,
});

expect(root.takeMountingManagerLogs()).toEqual([
'Update {type: "ScrollView", nativeID: (N/A)}',
'Create {type: "View", nativeID: "grandchild"}',
'Insert {type: "View", parentNativeID: "child", index: 0, nativeID: "grandchild"}',
]);
});

test('flattening and deleting a subtree that is partially culled', () => {
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});

// First render with a unflattened view container that is visible and a subtree that is partially culled.
Fantom.runTask(() => {
root.render(
<ScrollView
style={{height: 100, width: 100}}
contentOffset={{x: 0, y: 111}}>
<View style={{marginTop: 200, opacity: 0.5}}>
<View
nativeID="child"
style={{
marginTop: 10,
height: 10,
width: 10,
}}>
<View
nativeID="grandchild"
style={{
marginTop: 5,
height: 5,
width: 5,
}}
/>
</View>
</View>
</ScrollView>,
);
});

// All views are mounted, except for the grandchild.
expect(root.takeMountingManagerLogs()).toEqual([
'Update {type: "RootView", nativeID: (root)}',
'Create {type: "ScrollView", nativeID: (N/A)}',
'Create {type: "View", nativeID: (N/A)}',
'Create {type: "View", nativeID: (N/A)}',
'Create {type: "View", nativeID: "child"}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
]);

// Now change opacity to the default to flatten the container and delete container's subtree.
Fantom.runTask(() => {
root.render(
<ScrollView
style={{height: 100, width: 100}}
contentOffset={{x: 0, y: 111}}>
<View
style={{
marginTop: 200,
}}
/>
</ScrollView>,
);
});

// Note that the grandchild is not deleted because it was not previously mounted.
expect(root.takeMountingManagerLogs()).toEqual([
'Update {type: "ScrollView", nativeID: (N/A)}',
'Update {type: "View", nativeID: (N/A)}',
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
'Delete {type: "View", nativeID: (N/A)}',
'Delete {type: "View", nativeID: "child"}',
]);
});
Original file line number Diff line number Diff line change
Expand Up @@ -854,8 +854,6 @@ static void calculateShadowViewMutationsFlattener(

if (!treeChildPair.flattened) {
ViewNodePairScope innerScope{};
// TODO(T217775046): Find a test case for this branch of view
// flattening + culling.
calculateShadowViewMutations(
innerScope,
mutationContainer.destructiveDownwardMutations,
Expand All @@ -872,8 +870,6 @@ static void calculateShadowViewMutationsFlattener(

if (!treeChildPair.flattened) {
ViewNodePairScope innerScope{};
// TODO(T217775046): Find a test case for this branch of view
// flattening + culling.
calculateShadowViewMutations(
innerScope,
mutationContainer.downwardMutations,
Expand Down
Loading