Skip to content

Commit 9613892

Browse files
Yajur-Groveracoates-msTatianaKapos
authored
[0.77] Backport fixes for Modal (#14490)
* Rework modal to be implemented entirely using public APIs (#14256) * Rework modal implementation to use public APIs * shutdown fix * Change files * format * remove dead code * format * fixes * fix * UIA tree for root component should be kept distinct from main UIA tree * input offset fix for sub rootviews * Split modal into two componentview's so that we dont have multiple roots in our componentview tree * format * Ensure rootview removes itself from the island, before a new one adds itself on instance reload * defork some modal test pages * remove override * Allow portals to have independent layout constraints and scale factor (#14315) * Allow portals to have independent layout constraints and scale factor * format * change files * fix * Change files * fix bad merge * [Fabric] Fix modal height (#14343) * fix modal height * Change files * reverse change * add override * remove old change file * fix linting --------- Co-authored-by: Andrew Coates <[email protected]> Co-authored-by: Tatiana Kapos <[email protected]>
1 parent 8bc6e4c commit 9613892

File tree

59 files changed

+4391
-874
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4391
-874
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Fix UpdateState on generated base class",
4+
"packageName": "@react-native-windows/codegen",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Allow portals to have independent layout constraints and scale factor (#14315)",
4+
"packageName": "react-native-windows",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/@react-native-windows/codegen/src/generators/GenerateComponentWindows.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ void Register::_COMPONENT_NAME_::NativeComponent(
200200
builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
201201
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
202202
auto userData = view.UserData().as<TUserData>();
203-
userData->member(view, newState);
203+
userData->UpdateState(view, newState);
204204
});
205205
}
206206

packages/@react-native-windows/tester/src/js/examples/Modal/ModalOnShow.windows.js

+9-19
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
1212

1313
import RNTesterText from '../../components/RNTesterText';
1414
import * as React from 'react';
15+
import {useState} from 'react';
1516
import {Modal, Pressable, StyleSheet, Text, View} from 'react-native';
1617

1718
function ModalOnShowOnDismiss(): React.Node {
18-
const [modalShowComponent, setModalShowComponent] = React.useState(true);
19-
const [modalVisible, setModalVisible] = React.useState(false);
20-
const [onShowCount, setOnShowCount] = React.useState(0);
21-
const [onDismissCount, setOnDismissCount] = React.useState(0);
19+
const [modalShowComponent, setModalShowComponent] = useState(true);
20+
const [modalVisible, setModalVisible] = useState(false);
21+
const [onShowCount, setOnShowCount] = useState(0);
22+
const [onDismissCount, setOnDismissCount] = useState(0);
2223

2324
return (
2425
<View style={styles.container}>
@@ -28,20 +29,15 @@ function ModalOnShowOnDismiss(): React.Node {
2829
transparent={true}
2930
visible={modalVisible}
3031
onShow={() => {
31-
setOnShowCount(onShowCount + 1);
32+
setOnShowCount(showCount => showCount + 1);
3233
}}
3334
onDismiss={() => {
34-
setOnDismissCount(onDismissCount + 1);
35+
setOnDismissCount(dismissCount => dismissCount + 1);
3536
}}
3637
onRequestClose={() => {
3738
setModalVisible(false);
3839
}}>
39-
<View
40-
style={[
41-
styles.centeredView,
42-
styles.modalBackdrop,
43-
styles.widthHeight,
44-
]}>
40+
<View style={[styles.centeredView, styles.modalBackdrop]}>
4541
<View style={styles.modalView}>
4642
<Text testID="modal-on-show-count">
4743
onShow is called {onShowCount} times
@@ -96,7 +92,7 @@ const styles = StyleSheet.create({
9692
paddingVertical: 30,
9793
},
9894
centeredView: {
99-
// flex: 1, [Windows]
95+
// flex: 1, // [Windows] - This will cause the modal to stretch to be as tall as the availiable space given to it.
10096
justifyContent: 'center',
10197
alignItems: 'center',
10298
},
@@ -134,12 +130,6 @@ const styles = StyleSheet.create({
134130
fontWeight: 'bold',
135131
textAlign: 'center',
136132
},
137-
// [Windows
138-
widthHeight: {
139-
width: 300,
140-
height: 400,
141-
},
142-
// Windows]
143133
});
144134

145135
export default ({

packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,9 @@ const styles = StyleSheet.create({
348348
marginTop: 6,
349349
},
350350
modalContainer: {
351-
// [Windows
352-
width: 500,
353-
height: 500,
354-
// flex: 1,
355-
// justifyContent: 'center',
356-
// padding: 20,
357-
// Windows ]
351+
//flex: 1, // [Windows] - This will cause the modal to stretch to be as tall as the availiable space given to it.
352+
justifyContent: 'center',
353+
padding: 20,
358354
},
359355
modalInnerContainer: {
360356
borderRadius: 10,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
2+
/*
3+
* This file is auto-generated from CalendarViewNativeComponent spec file in flow / TypeScript.
4+
*/
5+
// clang-format off
6+
#pragma once
7+
8+
#include <NativeModules.h>
9+
10+
#ifdef RNW_NEW_ARCH
11+
#include <JSValueComposition.h>
12+
13+
#include <winrt/Microsoft.ReactNative.Composition.h>
14+
#include <winrt/Microsoft.UI.Composition.h>
15+
#endif // #ifdef RNW_NEW_ARCH
16+
17+
#ifdef RNW_NEW_ARCH
18+
19+
namespace winrt::SampleCustomComponent::Codegen {
20+
21+
REACT_STRUCT(CalendarViewProps)
22+
struct CalendarViewProps : winrt::implements<CalendarViewProps, winrt::Microsoft::ReactNative::IComponentProps> {
23+
CalendarViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
24+
: ViewProps(props)
25+
{
26+
if (cloneFrom) {
27+
auto cloneFromProps = cloneFrom.as<CalendarViewProps>();
28+
label = cloneFromProps->label;
29+
}
30+
}
31+
32+
void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
33+
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
34+
}
35+
36+
REACT_FIELD(label)
37+
std::string label;
38+
39+
const winrt::Microsoft::ReactNative::ViewProps ViewProps;
40+
};
41+
42+
REACT_STRUCT(CalendarView_OnSelectedDatesChanged)
43+
struct CalendarView_OnSelectedDatesChanged {
44+
REACT_FIELD(value)
45+
bool value{};
46+
47+
REACT_FIELD(startDate)
48+
std::string startDate;
49+
};
50+
51+
struct CalendarViewEventEmitter {
52+
CalendarViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter)
53+
: m_eventEmitter(eventEmitter) {}
54+
55+
using OnSelectedDatesChanged = CalendarView_OnSelectedDatesChanged;
56+
57+
void onSelectedDatesChanged(OnSelectedDatesChanged &value) const {
58+
m_eventEmitter.DispatchEvent(L"selectedDatesChanged", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) {
59+
winrt::Microsoft::ReactNative::WriteValue(writer, value);
60+
});
61+
}
62+
63+
private:
64+
winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr};
65+
};
66+
67+
template<typename TUserData>
68+
struct BaseCalendarView {
69+
70+
virtual void UpdateProps(
71+
const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
72+
const winrt::com_ptr<CalendarViewProps> &newProps,
73+
const winrt::com_ptr<CalendarViewProps> &/*oldProps*/) noexcept {
74+
m_props = newProps;
75+
}
76+
77+
// UpdateLayoutMetrics will only be called if this method is overridden
78+
virtual void UpdateLayoutMetrics(
79+
const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
80+
const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/,
81+
const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept {
82+
}
83+
84+
// UpdateState will only be called if this method is overridden
85+
virtual void UpdateState(
86+
const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
87+
const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept {
88+
}
89+
90+
virtual void UpdateEventEmitter(const std::shared_ptr<CalendarViewEventEmitter> &eventEmitter) noexcept {
91+
m_eventEmitter = eventEmitter;
92+
}
93+
94+
// MountChildComponentView will only be called if this method is overridden
95+
virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
96+
const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept {
97+
}
98+
99+
// UnmountChildComponentView will only be called if this method is overridden
100+
virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
101+
const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept {
102+
}
103+
104+
// Initialize will only be called if this method is overridden
105+
virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept {
106+
}
107+
108+
// CreateVisual will only be called if this method is overridden
109+
virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
110+
return view.as<winrt::Microsoft::ReactNative::Composition::ComponentView>().Compositor().CreateSpriteVisual();
111+
}
112+
113+
// FinalizeUpdate will only be called if this method is overridden
114+
virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/,
115+
winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept {
116+
}
117+
118+
119+
120+
const std::shared_ptr<CalendarViewEventEmitter>& EventEmitter() const { return m_eventEmitter; }
121+
const winrt::com_ptr<CalendarViewProps>& Props() const { return m_props; }
122+
123+
private:
124+
winrt::com_ptr<CalendarViewProps> m_props;
125+
std::shared_ptr<CalendarViewEventEmitter> m_eventEmitter;
126+
};
127+
128+
template <typename TUserData>
129+
void RegisterCalendarViewNativeComponent(
130+
winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder,
131+
std::function<void(const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder&)> builderCallback) noexcept {
132+
packageBuilder.as<winrt::Microsoft::ReactNative::IReactPackageBuilderFabric>().AddViewComponent(
133+
L"CalendarView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
134+
auto compBuilder = builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();
135+
136+
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
137+
const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
138+
return winrt::make<CalendarViewProps>(props, cloneFrom);
139+
});
140+
141+
builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
142+
const winrt::Microsoft::ReactNative::IComponentProps &newProps,
143+
const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept {
144+
auto userData = view.UserData().as<TUserData>();
145+
userData->UpdateProps(view, newProps ? newProps.as<CalendarViewProps>() : nullptr, oldProps ? oldProps.as<CalendarViewProps>() : nullptr);
146+
});
147+
148+
compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
149+
const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics,
150+
const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept {
151+
auto userData = view.UserData().as<TUserData>();
152+
userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics);
153+
});
154+
155+
builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
156+
const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept {
157+
auto userData = view.UserData().as<TUserData>();
158+
userData->UpdateEventEmitter(std::make_shared<CalendarViewEventEmitter>(eventEmitter));
159+
});
160+
161+
if constexpr (&TUserData::FinalizeUpdate != &BaseCalendarView<TUserData>::FinalizeUpdate) {
162+
builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
163+
winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept {
164+
auto userData = view.UserData().as<TUserData>();
165+
userData->FinalizeUpdate(view, mask);
166+
});
167+
}
168+
169+
if constexpr (&TUserData::UpdateState != &BaseCalendarView<TUserData>::UpdateState) {
170+
builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
171+
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
172+
auto userData = view.UserData().as<TUserData>();
173+
userData->UpdateState(view, newState);
174+
});
175+
}
176+
177+
if constexpr (&TUserData::MountChildComponentView != &BaseCalendarView<TUserData>::MountChildComponentView) {
178+
builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
179+
const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept {
180+
auto userData = view.UserData().as<TUserData>();
181+
return userData->MountChildComponentView(view, args);
182+
});
183+
}
184+
185+
if constexpr (&TUserData::UnmountChildComponentView != &BaseCalendarView<TUserData>::UnmountChildComponentView) {
186+
builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
187+
const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept {
188+
auto userData = view.UserData().as<TUserData>();
189+
return userData->UnmountChildComponentView(view, args);
190+
});
191+
}
192+
193+
compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
194+
auto userData = winrt::make_self<TUserData>();
195+
if constexpr (&TUserData::Initialize != &BaseCalendarView<TUserData>::Initialize) {
196+
userData->Initialize(view);
197+
}
198+
view.UserData(*userData);
199+
});
200+
201+
if constexpr (&TUserData::CreateVisual != &BaseCalendarView<TUserData>::CreateVisual) {
202+
compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
203+
auto userData = view.UserData().as<TUserData>();
204+
return userData->CreateVisual(view);
205+
});
206+
}
207+
208+
// Allow app to further customize the builder
209+
if (builderCallback) {
210+
builderCallback(compBuilder);
211+
}
212+
});
213+
}
214+
215+
} // namespace winrt::SampleCustomComponent::Codegen
216+
217+
#endif // #ifdef RNW_NEW_ARCH

packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/DrawingIsland.g.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ void RegisterDrawingIslandNativeComponent(
150150
builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
151151
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
152152
auto userData = view.UserData().as<TUserData>();
153-
userData->member(view, newState);
153+
userData->UpdateState(view, newState);
154154
});
155155
}
156156

packages/sample-custom-component/windows/SampleCustomComponent/codegen/react/components/SampleCustomComponent/MovingLight.g.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void RegisterMovingLightNativeComponent(
203203
builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
204204
const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept {
205205
auto userData = view.UserData().as<TUserData>();
206-
userData->member(view, newState);
206+
userData->UpdateState(view, newState);
207207
});
208208
}
209209

vnext/Microsoft.ReactNative/CompositionComponentView.idl

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "ViewProps.idl";
77
import "Composition.Input.idl";
88
import "CompositionSwitcher.idl";
99
import "IReactContext.idl";
10+
import "ReactNativeIsland.idl";
1011

1112
#include "DocString.h"
1213

@@ -110,8 +111,19 @@ namespace Microsoft.ReactNative.Composition
110111
[default_interface]
111112
runtimeclass RootComponentView : ViewComponentView {
112113
Microsoft.ReactNative.ComponentView GetFocusedComponent();
114+
Microsoft.ReactNative.ReactNativeIsland ReactNativeIsland { get; };
115+
DOC_STRING("Is non-null if this RootComponentView is the content of a portal")
116+
PortalComponentView Portal { get; };
113117
};
114-
118+
119+
[experimental]
120+
[webhosthidden]
121+
[default_interface]
122+
DOC_STRING("Used to implement UI that is hosted outside the main UI tree, such as modal.")
123+
runtimeclass PortalComponentView : Microsoft.ReactNative.ComponentView {
124+
RootComponentView ContentRoot { get; };
125+
};
126+
115127
[experimental]
116128
[webhosthidden]
117129
[default_interface]

0 commit comments

Comments
 (0)