diff --git a/change/react-native-windows-f295c471-5165-440a-a5d5-4d9b2d9c84d9.json b/change/react-native-windows-f295c471-5165-440a-a5d5-4d9b2d9c84d9.json new file mode 100644 index 00000000000..724dde632cb --- /dev/null +++ b/change/react-native-windows-f295c471-5165-440a-a5d5-4d9b2d9c84d9.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Rework modal implementation to use public APIs", + "packageName": "react-native-windows", + "email": "30809111+acoates-ms@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/tester/overrides.json b/packages/@react-native-windows/tester/overrides.json index a17f62b8ec8..2ea7f8fd427 100644 --- a/packages/@react-native-windows/tester/overrides.json +++ b/packages/@react-native-windows/tester/overrides.json @@ -41,12 +41,6 @@ "baseHash": "8583dee020400ce4d2754c3e04fd08dfde341c49", "issue": 12869 }, - { - "type": "patch", - "file": "src/js/examples/Modal/ModalOnShow.windows.js", - "baseFile": "packages/rn-tester/js/examples/Modal/ModalOnShow.js", - "baseHash": "911507abcf9172b5fdd1bb68faaf02562df704d4" - }, { "type": "patch", "file": "src/js/examples/Modal/ModalPresentation.windows.js", diff --git a/packages/@react-native-windows/tester/src/js/examples/Modal/ModalOnShow.windows.js b/packages/@react-native-windows/tester/src/js/examples/Modal/ModalOnShow.windows.js deleted file mode 100644 index 97afc692b3a..00000000000 --- a/packages/@react-native-windows/tester/src/js/examples/Modal/ModalOnShow.windows.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; - -import RNTesterText from '../../components/RNTesterText'; -import * as React from 'react'; -import {Modal, Pressable, StyleSheet, Text, View} from 'react-native'; - -function ModalOnShowOnDismiss(): React.Node { - const [modalShowComponent, setModalShowComponent] = React.useState(true); - const [modalVisible, setModalVisible] = React.useState(false); - const [onShowCount, setOnShowCount] = React.useState(0); - const [onDismissCount, setOnDismissCount] = React.useState(0); - - return ( - - {modalShowComponent && ( - { - setOnShowCount(onShowCount + 1); - }} - onDismiss={() => { - setOnDismissCount(onDismissCount + 1); - }} - onRequestClose={() => { - setModalVisible(false); - }}> - - - - onShow is called {onShowCount} times - - - onDismiss is called {onDismissCount} times - - setModalVisible(false)}> - - Hide modal by setting visible to false - - - setModalShowComponent(false)}> - - Hide modal by removing component - - - - - - )} - - onShow is called {onShowCount} times - - - onDismiss is called {onDismissCount} times - - { - setModalShowComponent(true); - setModalVisible(true); - }}> - - Show Modal - - - - ); -} - -const styles = StyleSheet.create({ - container: { - display: 'flex', - alignItems: 'center', - paddingVertical: 30, - }, - centeredView: { - // flex: 1, [Windows] - justifyContent: 'center', - alignItems: 'center', - }, - modalBackdrop: { - backgroundColor: 'rgba(0, 0, 0, 0.5)', - }, - modalView: { - margin: 20, - borderRadius: 20, - padding: 35, - alignItems: 'center', - shadowColor: '#000', - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.25, - shadowRadius: 4, - elevation: 5, - }, - button: { - borderRadius: 20, - padding: 10, - marginVertical: 20, - elevation: 2, - }, - buttonOpen: { - backgroundColor: '#F194FF', - }, - buttonClose: { - backgroundColor: '#2196F3', - }, - textStyle: { - color: 'white', - fontWeight: 'bold', - textAlign: 'center', - }, - // [Windows - widthHeight: { - width: 300, - height: 400, - }, - // Windows] -}); - -export default ({ - title: "Modal's onShow/onDismiss", - name: 'onShow', - description: - 'onShow and onDismiss (iOS only) callbacks are called when a modal is shown/dismissed', - render: (): React.Node => , -}: RNTesterModuleExample); diff --git a/packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js b/packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js index f766fa58bc0..9a5f35172a5 100644 --- a/packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js +++ b/packages/@react-native-windows/tester/src/js/examples/Modal/ModalPresentation.windows.js @@ -348,13 +348,9 @@ const styles = StyleSheet.create({ marginTop: 6, }, modalContainer: { - // [Windows - width: 500, - height: 500, - // flex: 1, - // justifyContent: 'center', - // padding: 20, - // Windows ] + flex: 1, + justifyContent: 'center', + padding: 20, }, modalInnerContainer: { borderRadius: 10, diff --git a/vnext/Microsoft.ReactNative/CompositionComponentView.idl b/vnext/Microsoft.ReactNative/CompositionComponentView.idl index 7cfa2740d2a..5c72cbd5067 100644 --- a/vnext/Microsoft.ReactNative/CompositionComponentView.idl +++ b/vnext/Microsoft.ReactNative/CompositionComponentView.idl @@ -7,6 +7,7 @@ import "ViewProps.idl"; import "Composition.Input.idl"; import "CompositionSwitcher.idl"; import "IReactContext.idl"; +import "ReactNativeIsland.idl"; #include "DocString.h" @@ -110,8 +111,19 @@ namespace Microsoft.ReactNative.Composition [default_interface] runtimeclass RootComponentView : ViewComponentView { Microsoft.ReactNative.ComponentView GetFocusedComponent(); + Microsoft.ReactNative.ReactNativeIsland ReactNativeIsland { get; }; + DOC_STRING("Is non-null if this RootComponentView is the content of a portal") + PortalComponentView Portal { get; }; }; - + + [experimental] + [webhosthidden] + [default_interface] + DOC_STRING("Used to implement UI that is hosted outside the main UI tree, such as modal.") + runtimeclass PortalComponentView : Microsoft.ReactNative.ComponentView { + RootComponentView ContentRoot { get; }; + }; + [experimental] [webhosthidden] [default_interface] diff --git a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp index c7cad679f72..3161fa2cb7a 100644 --- a/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp @@ -639,7 +639,6 @@ facebook::react::Tag ComponentView::hitTest( } winrt::IInspectable ComponentView::EnsureUiaProvider() noexcept { - assert(false); return nullptr; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp index 360a3161c14..4989b3fc0e9 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp @@ -15,8 +15,6 @@ #include #include #include -#include -#include #include #include #include @@ -59,9 +57,6 @@ ComponentViewDescriptor const &ComponentViewRegistry::dequeueComponentViewWithCo } else if (componentHandle == facebook::react::ImageShadowNode::Handle()) { view = winrt::Microsoft::ReactNative::Composition::implementation::ImageComponentView::Create( compContext, tag, m_context); - } else if (componentHandle == facebook::react::WindowsModalHostViewShadowNode::Handle()) { - view = winrt::Microsoft::ReactNative::Composition::implementation::WindowsModalHostComponentView::Create( - compContext, tag, m_context); } else if (componentHandle == facebook::react::WindowsTextInputShadowNode::Handle()) { view = winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView::Create( compContext, tag, m_context); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index dcd29eaddf5..ca254789899 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -192,8 +192,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE winrt::get_self(strongView)->props()); if (props == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - auto accessibilityRole = - props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole; // Invoke control pattern is used to support controls that do not maintain state // when activated but rather initiate or perform a single, unambiguous action. if (patternId == UIA_InvokePatternId && (props->onAccessibilityTap)) { diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp index 004c260b203..b254d602ef3 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp @@ -142,9 +142,8 @@ struct CompositionInputKeyboardSource : winrt::implements< CompositionEventHandler::CompositionEventHandler( const winrt::Microsoft::ReactNative::ReactContext &context, - const winrt::Microsoft::ReactNative::ReactNativeIsland &reactNativeIsland, - const int fragmentTag) - : m_fragmentTag(fragmentTag), m_context(context), m_wkRootView(reactNativeIsland) {} + const winrt::Microsoft::ReactNative::ReactNativeIsland &reactNativeIsland) + : m_context(context), m_wkRootView(reactNativeIsland) {} void CompositionEventHandler::Initialize() noexcept { #ifdef USE_WINUI3 @@ -348,11 +347,8 @@ facebook::react::SurfaceId CompositionEventHandler::SurfaceId() const noexcept { winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView & CompositionEventHandler::RootComponentView() const noexcept { - auto rootComponentViewDescriptor = (::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) - ->GetViewRegistry() - .componentViewDescriptorWithTag(SurfaceId()); - return *rootComponentViewDescriptor.view - .as(); + auto island = m_wkRootView.get(); + return *winrt::get_self(island)->GetComponentView(); } void CompositionEventHandler::onPointerWheelChanged( @@ -365,6 +361,9 @@ void CompositionEventHandler::onPointerWheelChanged( facebook::react::Point ptLocal; facebook::react::Point ptScaled = {static_cast(position.X), static_cast(position.Y)}; + // In the case of a sub rootview, we may have a non-zero origin. hitTest takes a pt in the parent coords, so we + // need to apply the current origin + ptScaled += RootComponentView().layoutMetrics().frame.origin; auto tag = RootComponentView().hitTest(ptScaled, ptLocal); if (tag == -1) @@ -977,6 +976,11 @@ void CompositionEventHandler::getTargetPointerArgs( tag = -1; ptScaled = {position.X, position.Y}; + + // In the case of a sub rootview, we may have a non-zero origin. hitTest takes a pt in the parent coords, so we need + // to apply the current origin + ptScaled += RootComponentView().layoutMetrics().frame.origin; + if (std::find(m_capturedPointers.begin(), m_capturedPointers.end(), pointerId) != m_capturedPointers.end()) { assert(m_pointerCapturingComponentTag != -1); tag = m_pointerCapturingComponentTag; @@ -989,30 +993,7 @@ void CompositionEventHandler::getTargetPointerArgs( ptLocal.y = ptScaled.y - (clientRect.top / strongRootView.ScaleFactor()); } } else { - if (m_fragmentTag == -1) { - tag = RootComponentView().hitTest(ptScaled, ptLocal); - return; - } - - // check if the fragment tag exists - if (!fabricuiManager->GetViewRegistry().findComponentViewWithTag(m_fragmentTag)) { - return; - } - - auto fagmentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(m_fragmentTag).view; - auto fagmentchildren = fagmentView.Children(); - - // call the hitTest with the fargment as the RootComponent - for (auto index = fagmentchildren.Size(); index > 0; index--) { - auto childView = fagmentchildren.GetAt(index - 1); - auto targetTag = - winrt::get_self(childView)->hitTest( - ptScaled, ptLocal); - if (targetTag != -1) { - tag = targetTag; - break; - } - } + tag = RootComponentView().hitTest(ptScaled, ptLocal); } } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h index f35bd44115d..1826338fadb 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h @@ -31,8 +31,7 @@ class CompositionEventHandler : public std::enable_shared_from_this m_activeTouches; // iOS is map of touch event args to ActiveTouch..? PointerId m_touchId = 0; - int m_fragmentTag = -1; std::map> m_currentlyHoveredViewsPerPointer; winrt::weak_ref m_wkRootView; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp index 5bf4135f57c..a1ab4e62227 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp @@ -167,7 +167,7 @@ HRESULT __stdcall CompositionRootAutomationProvider::get_ProviderOptions(Provide return S_OK; } -winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView * +winrt::com_ptr CompositionRootAutomationProvider::rootComponentView() noexcept { if (auto rootView = m_wkRootView.get()) { auto innerRootView = winrt::get_self(rootView); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h index cdaf5eabd0e..374b4c95f43 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h @@ -63,7 +63,8 @@ class CompositionRootAutomationProvider : public winrt::implements< }; private: - winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *rootComponentView() noexcept; + winrt::com_ptr + rootComponentView() noexcept; HRESULT AdvisePropertiesAdded(SAFEARRAY *psaProperties) noexcept; HRESULT AdvisePropertiesRemoved(SAFEARRAY *psaProperties) noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index 8e4a7c2f5ef..7952c5e990c 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -468,7 +468,7 @@ bool ComponentView::CapturePointer(const winrt::Microsoft::ReactNative::Composit if (!root) return false; - auto rootView{uiManager->GetReactNativeIsland(root->Tag())}; + auto rootView{root->ReactNativeIsland()}; if (!rootView) { return false; } @@ -487,7 +487,7 @@ void ComponentView::ReleasePointerCapture( if (!root) return; - auto rootView{uiManager->GetReactNativeIsland(root->Tag())}; + auto rootView{root->ReactNativeIsland()}; if (!rootView) { return; } @@ -1330,7 +1330,7 @@ winrt::Microsoft::ReactNative::ComponentView lastDeepChild( } // Walks the tree calling the function fn on each node. -// If fn returns true, then walkTree stops itterating over the tree, and returns true. +// If fn returns true, then walkTree stops iterating over the tree, and returns true. // If the tree walk completes without fn returning true, then walkTree returns false. bool walkTree( const winrt::Microsoft::ReactNative::ComponentView &view, diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h deleted file mode 100644 index 041f578f767..00000000000 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -// [Windows -#include "WindowsModalHostViewShadowNode.h" -// ] - -namespace facebook::react { - -/* - * Descriptor for component. - */ - -class WindowsModalHostViewComponentDescriptor final - : public ConcreteComponentDescriptor { - public: - using ConcreteComponentDescriptor::ConcreteComponentDescriptor; - - void adopt(ShadowNode &shadowNode) const override { - auto &layoutableShadowNode = static_cast(shadowNode); - auto &stateData = - static_cast(*shadowNode.getState()).getData(); - - layoutableShadowNode.setSize(Size{stateData.screenSize.width, stateData.screenSize.height}); - layoutableShadowNode.setPositionType(YGPositionTypeAbsolute); - - ConcreteComponentDescriptor::adopt(shadowNode); - } -}; - -} // namespace facebook::react diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp index 08b584f2162..6bb1de556d9 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp @@ -5,379 +5,241 @@ #include "WindowsModalHostViewComponentView.h" -#include -#include -#include "../CompositionDynamicAutomationProvider.h" -#include "Unicode.h" - -#include -#include -#include -#include -#include -#include -#include +#include "../../../codegen/react/components/rnwcore/ModalHostView.g.h" +#include #include +#include +#include #include -#include -#include -#include "IReactContext.h" -#include "ReactHost/ReactInstanceWin.h" -#include "ReactNativeHost.h" -#include "WindowsModalHostViewShadowNode.h" namespace winrt::Microsoft::ReactNative::Composition::implementation { -WindowsModalHostComponentView::WindowsModalHostComponentView( - const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, - facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) - : Super(compContext, tag, reactContext) {} - -WindowsModalHostComponentView::~WindowsModalHostComponentView() { - // dispatch onDismiss event - auto emitter = std::static_pointer_cast(m_eventEmitter); - facebook::react::ModalHostViewEventEmitter::OnDismiss onDismissArgs; - emitter->onDismiss(onDismissArgs); - - // reset the topWindowID - if (m_prevWindowID) { - auto host = - winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties()); - winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId( - host.InstanceSettings().Properties(), m_prevWindowID); - m_prevWindowID = 0; - } - - // enable input to parent - EnableWindow(m_parentHwnd, true); - - // Check if the window handle (m_hwnd) exists and destroy it if necessary - if (m_hwnd) { - // Close/Destroy the modal window - SendMessage(m_hwnd, WM_DESTROY, 0, 0); - m_hwnd = nullptr; - } -} - -winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create( - const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, - facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept { - return winrt::make(compContext, tag, reactContext); -} -// constants for creating a new windows -constexpr PCWSTR c_modalWindowClassName = L"MS_REACTNATIVE_MODAL"; -constexpr auto CompHostProperty = L"CompHost"; -const int MODAL_MIN_WIDTH = 50; -const int MODAL_MIN_HEIGHT = 50; +struct ModalHostView : public winrt::implements, + ::Microsoft::ReactNativeSpecs::BaseModalHostView { + ~ModalHostView() { + if (m_window && m_window.IsVisible()) { + CloseWindow(); + } -float ScaleFactor(HWND hwnd) noexcept { - return GetDpiForWindow(hwnd) / static_cast(USER_DEFAULT_SCREEN_DPI); -} + if (m_reactNativeIsland) { + m_reactNativeIsland.Island().Close(); + } -// creates a new modal window -void WindowsModalHostComponentView::EnsureModalCreated() { - auto host = - winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties()); + if (m_bridge) { + if (m_departFocusToken && !m_bridge.IsClosed()) { + auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge); + navHost.DepartFocusRequested(m_departFocusToken); + } + m_bridge.Close(); + } - // return if hwnd already exists - if (!host || m_hwnd) { - return; + if (m_window) { + m_window.Destroy(); + m_window = nullptr; + } } - RegisterWndClass(); - - HINSTANCE hInstance = GetModuleHandle(NULL); - winrt::com_ptr<::IUnknown> spunk; - - // get the root hwnd - m_prevWindowID = - winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_reactContext.Properties().Handle()); + void InitializePortalViewComponent( + const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portalComponentView) noexcept { + m_reactContext = portalComponentView.ReactContext(); - m_parentHwnd = GetHwndForParenting(); - - auto windowsStyle = m_showTitleBar ? WS_OVERLAPPEDWINDOW : WS_POPUP; - - m_hwnd = CreateWindow( - c_modalWindowClassName, - L"React-Native Modal", - windowsStyle, - CW_USEDEFAULT, - CW_USEDEFAULT, - MODAL_MIN_WIDTH, - MODAL_MIN_HEIGHT, - m_parentHwnd, // parent - nullptr, - hInstance, - spunk.get()); - - // Check if window creation succeeded - if (!m_hwnd) { - throw std::exception("Failed to create new hwnd for Modal: " + GetLastError()); + portalComponentView.Mounted( + [](const auto & /*sender*/, const auto &view) { view.UserData().as()->OnMounted(view); }); + portalComponentView.Unmounted( + [](const auto & /*sender*/, const auto &view) { view.UserData().as()->OnUnmounted(view); }); } - // Disable user sizing of the hwnd - ::SetWindowLong(m_hwnd, GWL_STYLE, GetWindowLong(m_hwnd, GWL_STYLE) & ~WS_SIZEBOX); - - // set the top-level windows as the new hwnd - winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId( - host.InstanceSettings().Properties(), reinterpret_cast(m_hwnd)); - - // get current compositor - handles the creation/manipulation of visual objects - auto compositionContext = CompositionContext(); - auto compositor = - winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerCompositor( - compositionContext); - - // create a react native island - code taken from CompositionHwndHost - auto bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create( - compositor, winrt::Microsoft::UI::GetWindowIdFromWindow(m_hwnd)); - m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland(compositor, m_reactContext.Handle(), *this); - auto contentIsland = m_reactNativeIsland.Island(); - bridge.Connect(contentIsland); - bridge.Show(); - - // set ScaleFactor - ScaleFactor(m_hwnd); - - // set layout contraints - winrt::Microsoft::ReactNative::LayoutConstraints constraints; - constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined; - - RECT rc; - GetClientRect(m_parentHwnd, &rc); - // Maximum size is set to size of parent hwnd - constraints.MaximumSize = {(rc.right - rc.left) * ScaleFactor(m_hwnd), (rc.bottom - rc.top) / ScaleFactor(m_hwnd)}; - constraints.MinimumSize = {MODAL_MIN_WIDTH * ScaleFactor(m_hwnd), MODAL_MIN_HEIGHT * ScaleFactor(m_hwnd)}; - m_reactNativeIsland.Arrange(constraints, {0, 0}); - bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow); - - spunk.detach(); -} - -void WindowsModalHostComponentView::ShowOnUIThread() { - if (m_hwnd && !IsWindowVisible(m_hwnd)) { - ShowWindow(m_hwnd, SW_NORMAL); - BringWindowToTop(m_hwnd); - SetFocus(m_hwnd); - - // disable input to parent - EnableWindow(m_parentHwnd, false); - - // dispatch onShow event - auto emitter = std::static_pointer_cast(m_eventEmitter); - facebook::react::ModalHostViewEventEmitter::OnShow onShowArgs; - emitter->onShow(onShowArgs); + void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::com_ptr<::Microsoft::ReactNativeSpecs::ModalHostViewProps> &newProps, + const winrt::com_ptr<::Microsoft::ReactNativeSpecs::ModalHostViewProps> &oldProps) noexcept override { + if (!oldProps || newProps->visible != oldProps->visible) { + if (newProps->visible.value_or(true)) { + // We do not immediately show the window, since we want to resize/position + // the window based on the layout metrics before we show it + m_showQueued = true; + } else { + CloseWindow(); + } + } + ::Microsoft::ReactNativeSpecs::BaseModalHostView::UpdateProps(view, newProps, oldProps); } -} -void WindowsModalHostComponentView::HideOnUIThread() noexcept { - if (m_hwnd) { - SendMessage(m_hwnd, WM_CLOSE, 0, 0); + void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics & /*oldLayoutMetrics*/) noexcept override { + if (m_window) { + AdjustWindowSize(newLayoutMetrics); + } } - // dispatch onDismiss event - auto emitter = std::static_pointer_cast(m_eventEmitter); - facebook::react::ModalHostViewEventEmitter::OnDismiss onDismissArgs; - emitter->onDismiss(onDismissArgs); + void FinalizeUpdate( + const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept override { + if (m_showQueued) { + ShowOnUIThread(view); + } + } - // enable input to parent - EnableWindow(m_parentHwnd, true); + private: + void OnMounted(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + m_mounted = true; - // reset the topWindowID - if (m_prevWindowID) { - auto host = - winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties()); - winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId( - host.InstanceSettings().Properties(), m_prevWindowID); - m_prevWindowID = 0; + if (m_showQueued) { + ShowOnUIThread(view); + } } -} -// Windows Procedure - callback function used for handling all messages (generated by NTUser or manual calls to -// SendMessage) -LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept { - auto data = reinterpret_cast<::IUnknown *>(GetProp( - hwnd, - CompHostProperty)); // gets data handle from the property list of specified window (ie the window we want to make) - winrt::Microsoft::ReactNative::CompositionHwndHost host{nullptr}; - - if (data) { - winrt::check_hresult(data->QueryInterface( - winrt::guid_of(), - winrt::put_abi(host))); // look into the data for a CompositionHwndHost and store it in host - auto result = static_cast(host.TranslateMessage(message, wparam, lparam)); - if (result) { - return result; - } + void OnUnmounted(const winrt::Microsoft::ReactNative::ComponentView & /*view*/) noexcept { + m_mounted = false; } - switch (message) { - case WM_NCCREATE: { // called before WM_CREATE, lparam should be identical to members of CreateWindowEx - auto createStruct = reinterpret_cast(lparam); // CreateStruct - data = static_cast<::IUnknown *>(createStruct->lpCreateParams); - SetProp(hwnd, CompHostProperty, data); // adds new properties to window - break; + void AdjustWindowSize(const winrt::Microsoft::ReactNative::LayoutMetrics &layoutMetrics) noexcept { + if (layoutMetrics.Frame.Width == 0 && layoutMetrics.Frame.Height == 0) { + return; } - case WM_CLOSE: { - // Just hide the window instead of destroying it - ::ShowWindow(hwnd, SW_HIDE); - return 0; - } - case WM_DESTROY: { // called when we want to destroy the window - ::ShowWindow(hwnd, SW_HIDE); - if (data) { - data->Release(); + + // get Modal's position based on parent + RECT parentRC; + GetWindowRect(m_parentHwnd, &parentRC); + int32_t xCor = static_cast( + (parentRC.left + parentRC.right - layoutMetrics.Frame.Width * layoutMetrics.PointScaleFactor) / 2); + int32_t yCor = static_cast( + (parentRC.top + parentRC.bottom - layoutMetrics.Frame.Height * layoutMetrics.PointScaleFactor) / 2); + + // Adjust window position and size + m_window.ResizeClient( + {static_cast(layoutMetrics.Frame.Width * (layoutMetrics.PointScaleFactor)), + static_cast(layoutMetrics.Frame.Height * (layoutMetrics.PointScaleFactor))}); + m_window.Move({xCor, yCor}); + }; + + void ShowOnUIThread(const winrt::Microsoft::ReactNative::ComponentView &view) { + if (!m_mounted) + return; + + m_showQueued = false; + EnsureModalCreated(view); + + if (m_window && !m_window.IsVisible()) { + m_bridge.Enable(); + m_window.Show(true); + + auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge); + auto result = navHost.NavigateFocus(winrt::Microsoft::UI::Input::FocusNavigationRequest::Create( + winrt::Microsoft::UI::Input::FocusNavigationReason::First)); + + // dispatch onShow event + if (auto eventEmitter = EventEmitter()) { + ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnShow eventArgs; + eventEmitter->onShow(eventArgs); } - SetProp(hwnd, CompHostProperty, nullptr); - break; } } - return DefWindowProc(hwnd, message, wparam, lparam); -} - -// Creates and Register a new window class -void WindowsModalHostComponentView::RegisterWndClass() noexcept { - static bool registered = false; - if (registered) { - return; - } - - HINSTANCE hInstance = - GetModuleHandle(NULL); // returns a handle to the file used to create the calling process (.exe file) - - WNDCLASSEX wcex = {}; // contains window class information - wcex.cbSize = sizeof(wcex); // size of windows class (bytes) - wcex.style = CS_HREDRAW | CS_VREDRAW; // class style (redraw window on size adjustment) - wcex.lpfnWndProc = &ModalBoxWndProc; // pointer to windows procedure - wcex.cbClsExtra = DLGWINDOWEXTRA; // extra bytes to allocate - wcex.cbWndExtra = - sizeof(winrt::impl::abi::type *); // extra bytes to allocate - wcex.hInstance = hInstance; - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); // handle to class cursor - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // background color - wcex.lpszClassName = c_modalWindowClassName; // specify resource name - ATOM classId = RegisterClassEx(&wcex); // register new windows class - WINRT_VERIFY(classId); // 0 = fail - winrt::check_win32(!classId); - - registered = true; -} - -winrt::Microsoft::ReactNative::Composition::Experimental::IVisual -WindowsModalHostComponentView::VisualToMountChildrenInto() noexcept { - return m_reactNativeIsland - .as() - .InternalRootVisual(); -} + void CloseWindow() noexcept { + // enable input to parent before closing the modal window, so focus can return back to the parent window + EnableWindow(m_parentHwnd, true); -// childComponentView - reference to the child component view -// index - the position in which the childComponentView should be mounted -void WindowsModalHostComponentView::MountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView &childComponentView, - uint32_t index) noexcept { - EnsureModalCreated(); - base_type::MountChildComponentView(childComponentView, index); -} + if (m_window) { + m_window.Hide(); + } -void WindowsModalHostComponentView::UnmountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView &childComponentView, - uint32_t index) noexcept { - base_type::UnmountChildComponentView(childComponentView, index); -} + // dispatch onDismiss event + if (auto eventEmitter = EventEmitter()) { + ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnDismiss eventArgs; + eventEmitter->onDismiss(eventArgs); + } -void WindowsModalHostComponentView::updateLayoutMetrics( - facebook::react::LayoutMetrics const &layoutMetrics, - facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept { - base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics); - if (m_hwnd) { - EnsureModalCreated(); - AdjustWindowSize(); - ShowOnUIThread(); - } -} + // reset the topWindowID + if (m_prevWindowID) { + winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId( + m_reactContext.Properties().Handle(), m_prevWindowID); + m_prevWindowID = 0; + } -void WindowsModalHostComponentView::AdjustWindowSize() noexcept { - if (m_layoutMetrics.overflowInset.right == 0 && m_layoutMetrics.overflowInset.bottom == 0) { - return; + m_bridge.Disable(); } - // Modal's size is based on it's children, use the overflow to calculate the width/height - float xPos = (-m_layoutMetrics.overflowInset.right * (m_layoutMetrics.pointScaleFactor)); - float yPos = (-m_layoutMetrics.overflowInset.bottom * (m_layoutMetrics.pointScaleFactor)); - RECT rc; - GetClientRect(m_hwnd, &rc); - RECT rect = {0, 0, (int)xPos, (int)yPos}; - - if (m_showTitleBar) { - AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); // Adjust for title bar and borders - } + // creates a new modal window + void EnsureModalCreated(const winrt::Microsoft::ReactNative::ComponentView &view) { + if (m_window) { + return; + } - // set the layoutMetrics - m_layoutMetrics.frame.size = {(float)rect.right - rect.left, (float)rect.bottom - rect.top}; - m_layoutMetrics.overflowInset.right = 0; - m_layoutMetrics.overflowInset.bottom = 0; + // get the root hwnd + m_prevWindowID = + winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(view.ReactContext().Properties()); - // get Modal's position based on parent - RECT parentRC; - GetWindowRect(m_parentHwnd, &parentRC); - float xCor = (parentRC.left + parentRC.right - m_layoutMetrics.frame.size.width) / 2; // midpointx - width / 2 - float yCor = (parentRC.top + parentRC.bottom - m_layoutMetrics.frame.size.height) / 2; // midpointy - height / 2 + m_parentHwnd = + view.as<::Microsoft::ReactNative::Composition::Experimental::IComponentViewInterop>()->GetHwndForParenting(); - // Adjust window position and size - MoveWindow(m_hwnd, (int)xCor, (int)yCor, (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), true); + auto presenter = winrt::Microsoft::UI::Windowing::OverlappedPresenter::CreateForDialog(); + presenter.SetBorderAndTitleBar(true, false); + presenter.IsModal(true); - // Let RNWIsland know that Modal's size has changed - winrt::get_self(m_reactNativeIsland) - ->NotifySizeChanged(); -}; + m_window = winrt::Microsoft::UI::Windowing::AppWindow::Create( + presenter, winrt::Microsoft::UI::GetWindowIdFromWindow(m_parentHwnd)); -void WindowsModalHostComponentView::updateProps( - facebook::react::Props::Shared const &props, - facebook::react::Props::Shared const &oldProps) noexcept { - const auto &oldModalProps = - *std::static_pointer_cast(oldProps ? oldProps : viewProps()); - const auto &newModalProps = *std::static_pointer_cast(props); - newModalProps.visible ? m_isVisible = true : m_isVisible = false; - if (!m_isVisible) { - HideOnUIThread(); + // set the top-level windows as the new hwnd + winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId( + view.ReactContext().Properties(), + reinterpret_cast(winrt::Microsoft::UI::GetWindowFromWindowId(m_window.Id()))); + + // create a react native island - code taken from CompositionHwndHost + m_bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create( + view.Parent().as().Compositor(), m_window.Id()); + m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal( + view.as()); + auto contentIsland = m_reactNativeIsland.Island(); + + auto navHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteBridge(m_bridge); + m_departFocusToken = navHost.DepartFocusRequested( + [wkView = winrt::make_weak(view)]( + const auto &sender, const winrt::Microsoft::UI::Input::FocusNavigationRequestEventArgs &args) { + if (auto strongView = wkView.get()) { + TrySetFocus(strongView.Parent()); + } + }); + + m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow); + m_bridge.Connect(contentIsland); + AdjustWindowSize(view.LayoutMetrics()); + m_bridge.Show(); } - base_type::updateProps(props, oldProps); -} -facebook::react::SharedViewProps WindowsModalHostComponentView::defaultProps() noexcept { - static auto const defaultProps = std::make_shared(); - return defaultProps; -} -const facebook::react::ModalHostViewProps &WindowsModalHostComponentView::modalHostViewProps() const noexcept { - return *std::static_pointer_cast(viewProps()); -} - -facebook::react::Tag WindowsModalHostComponentView::hitTest( - facebook::react::Point pt, - facebook::react::Point &localPt, - bool ignorePointerEvents) const noexcept { - facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y}; - - if ((ignorePointerEvents || viewProps()->pointerEvents == facebook::react::PointerEventsMode::Auto || - viewProps()->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) && - ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 && - ptLocal.y <= m_layoutMetrics.frame.size.height) { - localPt = ptLocal; - return Tag(); + static void TrySetFocus(const winrt::Microsoft::ReactNative::ComponentView &view) { + auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland( + view.as().Root().ReactNativeIsland().Island()); + focusController.TrySetFocus(); } - return -1; -} - -bool WindowsModalHostComponentView::focusable() const noexcept { - return false; -} + ReactContext m_reactContext{nullptr}; + HWND m_parentHwnd{nullptr}; + winrt::Microsoft::UI::Windowing::AppWindow m_window{nullptr}; + uint64_t m_prevWindowID; + bool m_showTitleBar{false}; + bool m_showQueued{false}; + bool m_mounted{false}; + winrt::Microsoft::UI::Input::InputFocusNavigationHost::DepartFocusRequested_revoker m_departFocusRevoker; + winrt::event_token m_departFocusToken; + winrt::Microsoft::UI::Content::DesktopChildSiteBridge m_bridge{nullptr}; + winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland{nullptr}; +}; -std::string WindowsModalHostComponentView::DefaultControlType() const noexcept { - return "modal"; +void RegisterWindowsModalHostNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept { + ::Microsoft::ReactNativeSpecs::RegisterModalHostViewNativeComponent( + packageBuilder, + [](const winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder &builder) { + builder.SetPortalComponentViewInitializer( + [](const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portalComponentView) noexcept { + auto userData = winrt::make_self(); + userData->InitializePortalViewComponent(portalComponentView); + portalComponentView.UserData(*userData); + }); + }); } } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h index fbb3f10ec21..0f75d74d7a0 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h @@ -3,69 +3,11 @@ #pragma once -#include -#include - -#include "Composition.WindowsModalHostComponentView.g.h" -#include "../CompositionViewComponentView.h" - -#include -#include +#include namespace winrt::Microsoft::ReactNative::Composition::implementation { -struct WindowsModalHostComponentView - : WindowsModalHostComponentViewT { - using Super = WindowsModalHostComponentViewT; - - ~WindowsModalHostComponentView(); - - [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create( - const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, - facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept; - - winrt::Microsoft::ReactNative::Composition::Experimental::IVisual VisualToMountChildrenInto() noexcept override; - void MountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView &childComponentView, - uint32_t index) noexcept override; - void UnmountChildComponentView( - const winrt::Microsoft::ReactNative::ComponentView &childComponentView, - uint32_t index) noexcept override; - - void AdjustWindowSize() noexcept; - - void updateLayoutMetrics( - facebook::react::LayoutMetrics const &layoutMetrics, - facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override; - - void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept - override; - static facebook::react::SharedViewProps defaultProps() noexcept; - const facebook::react::ModalHostViewProps &modalHostViewProps() const noexcept; - bool focusable() const noexcept override; - facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents) - const noexcept override; - virtual std::string DefaultControlType() const noexcept; - - WindowsModalHostComponentView( - const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, - facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext); - - // Used for creating new window - void ShowOnUIThread(); - void HideOnUIThread() noexcept; - void EnsureModalCreated(); - static void RegisterWndClass() noexcept; - - private: - HWND m_parentHwnd{nullptr}; - HWND m_hwnd{nullptr}; - uint64_t m_prevWindowID; - bool m_isVisible{false}; - bool m_showTitleBar{false}; - winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland; -}; +void RegisterWindowsModalHostNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp deleted file mode 100644 index 35d109c5629..00000000000 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// [Windows -#include "WindowsModalHostViewShadowNode.h" -// ] - -#include - -namespace facebook::react { - -extern const char WindowsModalHostViewComponentName[] = "ModalHostView"; - -} // namespace facebook::react \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h b/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h deleted file mode 100644 index caa591fc0d9..00000000000 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -// [Windows -#include -#include -// ] -#include - -namespace facebook::react { - -extern const char WindowsModalHostViewComponentName[]; - -/* - * `ShadowNode` for component. - */ -class WindowsModalHostViewShadowNode final : public ConcreteViewShadowNode< - WindowsModalHostViewComponentName, - ModalHostViewProps, - ModalHostViewEventEmitter, - ModalHostViewState> { - public: - using ConcreteViewShadowNode::ConcreteViewShadowNode; - - static ShadowNodeTraits BaseTraits() { - auto traits = ConcreteViewShadowNode::BaseTraits(); - traits.set(ShadowNodeTraits::Trait::RootNodeKind); - return traits; - } -}; - -} // namespace facebook::react diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp new file mode 100644 index 00000000000..1726973ebe8 --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp @@ -0,0 +1,66 @@ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "PortalComponentView.h" + +#include "Composition.PortalComponentView.g.cpp" + +namespace winrt::Microsoft::ReactNative::Composition::implementation { + +PortalComponentView::PortalComponentView( + const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, + facebook::react::Tag tag, + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder) + : base_type(tag, reactContext, builder) { + m_rootComponentView = winrt::make_self( + compContext, *this, reactContext); +} + +PortalComponentView::~PortalComponentView() {} + +winrt::Microsoft::ReactNative::Composition::RootComponentView PortalComponentView::ContentRoot() const noexcept { + return *m_rootComponentView; +} + +void PortalComponentView::MountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView &childComponentView, + uint32_t index) noexcept { + m_rootComponentView->MountChildComponentView(childComponentView, index); +} + +void PortalComponentView::UnmountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView &childComponentView, + uint32_t index) noexcept { + m_rootComponentView->UnmountChildComponentView(childComponentView, index); +} + +const winrt::Microsoft::ReactNative::IComponentProps PortalComponentView::userProps( + facebook::react::Props::Shared const &props) noexcept { + const auto &abiViewProps = *std::static_pointer_cast(props); + return abiViewProps.UserProps(); +} + +void PortalComponentView::updateProps( + facebook::react::Props::Shared const &props, + facebook::react::Props::Shared const &oldProps) noexcept { + m_rootComponentView->updateProps(props, oldProps); + base_type::updateProps(props, oldProps); +} + +void PortalComponentView::updateLayoutMetrics( + facebook::react::LayoutMetrics const &layoutMetrics, + facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept { + m_rootComponentView->updateLayoutMetrics(layoutMetrics, oldLayoutMetrics); + base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics); +} + +void PortalComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept { + m_rootComponentView->FinalizeUpdates(updateMask); + base_type::FinalizeUpdates(updateMask); +} + +} // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h new file mode 100644 index 00000000000..29089ba6744 --- /dev/null +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h @@ -0,0 +1,52 @@ + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include "RootComponentView.h" + +#include "Composition.PortalComponentView.g.h" + +namespace Microsoft::ReactNative { +struct CompContext; +} // namespace Microsoft::ReactNative + +namespace winrt::Microsoft::ReactNative::Composition::implementation { + +struct PortalComponentView + : public PortalComponentViewT { + PortalComponentView( + const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, + facebook::react::Tag tag, + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder); + virtual ~PortalComponentView(); + + winrt::Microsoft::ReactNative::Composition::RootComponentView ContentRoot() const noexcept; + + void MountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView &childComponentView, + uint32_t index) noexcept override; + void UnmountChildComponentView( + const winrt::Microsoft::ReactNative::ComponentView &childComponentView, + uint32_t index) noexcept override; + + const winrt::Microsoft::ReactNative::IComponentProps userProps( + facebook::react::Props::Shared const &props) noexcept override; + void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept + override; + + void updateLayoutMetrics( + facebook::react::LayoutMetrics const &layoutMetrics, + facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override; + + void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept override; + + private: + winrt::com_ptr m_rootComponentView; +}; + +} // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp index b19c3bd9b56..f7c96535343 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp @@ -5,6 +5,7 @@ #include "ReactCompositionViewComponentBuilder.h" #include #include +#include #include #include "CompositionContextHelper.h" #include "DynamicWriter.h" @@ -111,6 +112,26 @@ void ReactCompositionViewComponentBuilder::SetContentIslandComponentViewInitiali }; } +void ReactCompositionViewComponentBuilder::SetPortalComponentViewInitializer( + const PortalComponentViewInitializer &initializer) noexcept { + m_fnCreateView = [initializer]( + const IReactContext &reactContext, + int32_t tag, + const Experimental::ICompositionContext &context, + ComponentViewFeatures /*features*/, + ReactCompositionViewComponentBuilder &builder) + -> winrt::Microsoft::ReactNative::Composition::PortalComponentView { + auto view = winrt::make( + context, tag, reactContext, &builder); + initializer(view); + return view; + }; + m_descriptorConstructorFactory = []() { + return &facebook::react::concreteComponentDescriptorConstructor< + ::Microsoft::ReactNative::AbiViewComponentDescriptor>; + }; +} + // (Object handle, Microsoft.ReactNative.IComponentState state) => void // void ReactCompositionViewComponentBuilder::SetStateUpdater(StateUpdater impl) noexcept { // m_stateUpdater = impl; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h index 618aae06e5d..852d08a8cd8 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h @@ -12,10 +12,12 @@ namespace winrt::Microsoft::ReactNative::Composition { -struct ReactCompositionViewComponentBuilder : winrt::implements< - ReactCompositionViewComponentBuilder, - IReactViewComponentBuilder, - Composition::IReactCompositionViewComponentBuilder> { +struct ReactCompositionViewComponentBuilder + : winrt::implements< + ReactCompositionViewComponentBuilder, + IReactViewComponentBuilder, + Composition::IReactCompositionViewComponentBuilder, + Composition::Experimental::IReactCompositionViewComponentInternalBuilder> { ReactCompositionViewComponentBuilder() noexcept; public: // IReactViewComponentBuilder @@ -42,6 +44,7 @@ struct ReactCompositionViewComponentBuilder : winrt::implements< public: // Composition::IReactCompositionViewComponentBuilder void SetViewComponentViewInitializer(const ViewComponentViewInitializer &initializer) noexcept; void SetContentIslandComponentViewInitializer(const ComponentIslandComponentViewInitializer &initializer) noexcept; + void SetPortalComponentViewInitializer(const PortalComponentViewInitializer &initializer) noexcept; void SetCreateVisualHandler(CreateVisualDelegate impl) noexcept; void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept; void SetVisualToMountChildrenIntoHandler(VisualToMountChildrenIntoDelegate impl) noexcept; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp index a27be342689..587f7b37c36 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp @@ -127,21 +127,39 @@ ReactNativeIsland::ReactNativeIsland(const winrt::Microsoft::UI::Composition::Co InitTextScaleMultiplier(); } -// Constructor to initialize ReactNativeIsland with context and componentView ReactNativeIsland::ReactNativeIsland( - const winrt::Microsoft::UI::Composition::Compositor &compositor, - winrt::Microsoft::ReactNative::IReactContext context, - winrt::Microsoft::ReactNative::ComponentView componentView) noexcept - : m_compositor(compositor), - m_context(context), + const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept + : m_compositor(portal.ContentRoot().Compositor()), + m_context(portal.ReactContext()), m_layoutConstraints({{0, 0}, {0, 0}, winrt::Microsoft::ReactNative::LayoutDirection::Undefined}), m_isFragment(true) { - m_rootTag = componentView.Tag(); + m_portal = winrt::make_weak(portal); + + auto trueRoot = + winrt::get_self(portal) + ->rootComponentView(); + while (auto p = trueRoot->Portal()) { + trueRoot = winrt::get_self(p) + ->rootComponentView(); + }; + m_rootTag = trueRoot->Tag(); + InitTextScaleMultiplier(); - AddFragmentCompositionEventHandler(context, componentView); + AddFragmentCompositionEventHandler(m_context.Handle(), portal.ContentRoot()); + auto selfPortal = winrt::get_self( + portal.ContentRoot()); + selfPortal->ReactNativeIsland(*this); + NotifySizeChanged(); + selfPortal->start(*this); +} + +winrt::Microsoft::ReactNative::ReactNativeIsland ReactNativeIsland::CreatePortal( + const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept { + return winrt::make(portal); } -ReactNativeIsland::ReactNativeIsland() noexcept : ReactNativeIsland(nullptr) {} +ReactNativeIsland::ReactNativeIsland() noexcept + : ReactNativeIsland(winrt::Microsoft::UI::Composition::Compositor{nullptr}) {} ReactNativeIsland::~ReactNativeIsland() noexcept { #ifdef USE_WINUI3 @@ -159,14 +177,20 @@ ReactNativeIsland::~ReactNativeIsland() noexcept { assert(m_uiDispatcher.HasThreadAccess()); UninitRootView(); } + + if (m_island) { + m_island.Close(); + } } ReactNative::IReactViewHost ReactNativeIsland::ReactViewHost() noexcept { return m_reactViewHost; } -void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewHost const &value) noexcept { - assert(!m_isFragment); // make sure this isn't a FragmentIsalnd +void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewHost const &value) { + if (m_isFragment) + winrt::throw_hresult(E_ACCESSDENIED); + if (m_reactViewHost == value) { return; } @@ -217,6 +241,8 @@ void ReactNativeIsland::AddRenderedVisual( void ReactNativeIsland::RemoveRenderedVisual( const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept { + if (m_isFragment) + return; assert(m_hasRenderedVisual); InternalRootVisual().Remove(visual); m_hasRenderedVisual = false; @@ -442,7 +468,7 @@ void ReactNativeIsland::InitRootView( m_context = winrt::Microsoft::ReactNative::ReactContext(std::move(context)); m_reactViewOptions = std::move(viewOptions); - m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, -1); + m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this); m_CompositionEventHandler->Initialize(); UpdateRootViewInternal(); @@ -457,15 +483,13 @@ void ReactNativeIsland::AddFragmentCompositionEventHandler( .Get(winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty()) .try_as(); VerifyElseCrash(m_uiDispatcher.HasThreadAccess()); - VerifyElseCrash(m_rootTag != -1); auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties( winrt::Microsoft::ReactNative::ReactPropertyBag(context.Properties())); if (!m_CompositionEventHandler) { // Create CompositionEventHandler if not already created m_context = winrt::Microsoft::ReactNative::ReactContext(context); - m_CompositionEventHandler = - std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, componentView.Tag()); + m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this); m_CompositionEventHandler->Initialize(); m_isInitialized = true; } @@ -545,6 +569,7 @@ void ReactNativeIsland::ClearLoadingUI() noexcept { void ReactNativeIsland::EnsureLoadingUI() noexcept {} void ReactNativeIsland::ShowInstanceLoaded() noexcept { + VerifyElseCrash(!m_isFragment); if (m_rootVisual) { ClearLoadingUI(); @@ -740,6 +765,9 @@ void ReactNativeIsland::InitTextScaleMultiplier() noexcept { winrt::Windows::Foundation::Size ReactNativeIsland::Measure( const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints, const winrt::Windows::Foundation::Point &viewportOffset) const { + if (m_isFragment) + winrt::throw_hresult(E_ILLEGAL_METHOD_CALL); + facebook::react::Size size{0, 0}; if (layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight && @@ -781,7 +809,7 @@ void ReactNativeIsland::Arrange( facebook::react::LayoutConstraints fbLayoutConstraints; ApplyConstraints(layoutConstraints, fbLayoutConstraints); - if (m_isInitialized && m_rootTag != -1) { + if (m_isInitialized && m_rootTag != -1 && !m_isFragment) { if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties( winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) { facebook::react::LayoutContext context; @@ -820,6 +848,23 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() { rootVisual)); m_island = winrt::Microsoft::UI::Content::ContentIsland::Create(rootVisual); + auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(m_island); + focusController.NavigateFocusRequested( + [weakThis = get_weak()]( + const auto &sender, const winrt::Microsoft::UI::Input::FocusNavigationRequestEventArgs &args) { + if (auto pThis = weakThis.get()) { + if (auto rootView = pThis->GetComponentView()) { + args.Result( + rootView->NavigateFocus(winrt::Microsoft::ReactNative::FocusNavigationRequest( + winrt::Microsoft::ReactNative::FocusNavigationReason::First)) + ? winrt::Microsoft::UI::Input::FocusNavigationResult::Moved + : winrt::Microsoft::UI::Input::FocusNavigationResult::NotMoved); + } else { + args.Result(winrt::Microsoft::UI::Input::FocusNavigationResult::NoFocusableElements); + } + } + }); + // ContentIsland does not support weak_ref, so we cannot use auto_revoke for these events m_islandAutomationProviderRequestedToken = m_island.AutomationProviderRequested( [weakThis = get_weak()]( @@ -903,13 +948,29 @@ void ReactNativeIsland::OnUnmounted() noexcept { if (!m_mounted) return; m_mounted = false; + + if (m_island && m_island.IsConnected()) { + auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(m_island); + auto request = winrt::Microsoft::UI::Input::FocusNavigationRequest::Create( + winrt::Microsoft::UI::Input::FocusNavigationReason::Programmatic); + if (focusController.HasFocus()) { + focusController.DepartFocus(request); + } + } + if (auto componentView = GetComponentView()) { componentView->onUnmounted(); } } -winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView * +winrt::com_ptr ReactNativeIsland::GetComponentView() noexcept { + if (auto portal = m_portal.get()) { + return winrt::get_self(portal) + ->ContentRoot() + .as(); + } + if (!m_context || m_context.Handle().LoadingState() != winrt::Microsoft::ReactNative::LoadingState::Loaded || m_rootTag == -1) return nullptr; @@ -919,8 +980,7 @@ ReactNativeIsland::GetComponentView() noexcept { auto rootComponentViewDescriptor = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag( static_cast(m_rootTag)); return rootComponentViewDescriptor.view - .as() - .get(); + .as(); } return nullptr; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h index c51aa7bd610..8d8ed359be8 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h @@ -12,6 +12,7 @@ #include #include #include "CompositionEventHandler.h" +#include "PortalComponentView.h" #include "ReactHost/React.h" namespace winrt::Microsoft::ReactNative::implementation { @@ -48,15 +49,15 @@ struct ReactNativeIsland ~ReactNativeIsland() noexcept; ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept; - ReactNativeIsland( - const winrt::Microsoft::UI::Composition::Compositor &compositor, - winrt::Microsoft::ReactNative::IReactContext context, - winrt::Microsoft::ReactNative::ComponentView componentView) noexcept; + ReactNativeIsland(const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept; + + static winrt::Microsoft::ReactNative::ReactNativeIsland CreatePortal( + const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept; winrt::Microsoft::UI::Content::ContentIsland Island(); // property ReactViewHost ReactNative::IReactViewHost ReactViewHost() noexcept; - void ReactViewHost(ReactNative::IReactViewHost const &value) noexcept; + void ReactViewHost(ReactNative::IReactViewHost const &value); winrt::Microsoft::UI::Composition::Visual RootVisual() noexcept; @@ -104,7 +105,8 @@ struct ReactNativeIsland winrt::Microsoft::ReactNative::FocusNavigationResult NavigateFocus( const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept; - winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *GetComponentView() noexcept; + winrt::com_ptr + GetComponentView() noexcept; int64_t RootTag() const noexcept; @@ -153,8 +155,12 @@ struct ReactNativeIsland bool m_hasRenderedVisual{false}; bool m_showingLoadingUI{false}; bool m_mounted{false}; + winrt::weak_ref m_portal{nullptr}; IReactDispatcher m_uiDispatcher{nullptr}; winrt::IInspectable m_uiaProvider{nullptr}; + + // This is the surfaceId that this island belongs to. + // In the case of portal content root, this will be the surfaceId that contains the portal. int64_t m_rootTag{-1}; float m_scaleFactor{1.0}; float m_textScaleMultiplier{1.0}; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp index 45d4a49dc1f..8cb42b9226e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp @@ -17,7 +17,8 @@ namespace winrt::Microsoft::ReactNative::Composition::implementation { RootComponentView::RootComponentView( const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, - winrt::Microsoft::ReactNative::ReactContext const &reactContext) + winrt::Microsoft::ReactNative::ReactContext const &reactContext, + ReactCompositionViewComponentBuilder *builder) : base_type( {}, // default viewProps compContext, @@ -25,20 +26,34 @@ RootComponentView::RootComponentView( reactContext, ComponentViewFeatures::Default & ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps | - ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual)) {} + ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual), + builder) {} + +RootComponentView::RootComponentView( + const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, + const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal, + winrt::Microsoft::ReactNative::ReactContext const &reactContext) + : base_type( + {}, // default viewProps + compContext, + -1, + reactContext, + ComponentViewFeatures::Default & + ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps | + ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual), + nullptr // builder, + ), + m_wkPortal(portal) {} RootComponentView::~RootComponentView() { - if (auto rootView = m_wkRootView.get()) { - winrt::get_self(rootView)->RemoveRenderedVisual( - OuterVisual()); - } + stop(); } winrt::Microsoft::ReactNative::ComponentView RootComponentView::Create( const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext, facebook::react::Tag tag, winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept { - return winrt::make(compContext, tag, reactContext); + return winrt::make(compContext, tag, reactContext, nullptr); } RootComponentView *RootComponentView::rootComponentView() const noexcept { @@ -84,13 +99,13 @@ void RootComponentView::SetFocusedComponent(const winrt::Microsoft::ReactNative: bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept { if (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::Restore) { - // No-op for now - return m_focusedComponent != nullptr; + if (m_focusedComponent) + return true; } - auto view = (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::First) - ? FocusManager::FindFirstFocusableElement(*this) - : FocusManager::FindLastFocusableElement(*this); + auto view = (request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::Last) + ? FocusManager::FindLastFocusableElement(*this) + : FocusManager::FindFirstFocusableElement(*this); if (view) { TrySetFocusedComponent( view, @@ -116,8 +131,10 @@ bool RootComponentView::TrySetFocusedComponent( selfView = winrt::get_self(target); } - if (selfView && selfView->rootComponentView() != this) + if (selfView && selfView->rootComponentView() != this) { + assert(false); return false; + } auto losingFocusArgs = winrt::make( target, direction, m_focusedComponent, target); @@ -197,7 +214,7 @@ HRESULT RootComponentView::GetFragmentRoot(IRawElementProviderFragmentRoot **pRe if (uiManager == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - auto rootView{uiManager->GetReactNativeIsland(Tag())}; + auto rootView = m_wkRootView.get(); if (!rootView) { return UIA_E_ELEMENTNOTAVAILABLE; } @@ -214,10 +231,43 @@ uint32_t RootComponentView::overlayIndex() noexcept { return 1; } -void RootComponentView::start(const winrt::Microsoft::ReactNative::ReactNativeIsland &rootView) noexcept { - winrt::get_self(rootView)->AddRenderedVisual( +void RootComponentView::start(const winrt::Microsoft::ReactNative::ReactNativeIsland &island) noexcept { + theme(winrt::get_self(island.Theme())); + + winrt::get_self(island)->AddRenderedVisual( OuterVisual()); - m_wkRootView = rootView; + m_visualAddedToIsland = true; + ReactNativeIsland(island); +} + +void RootComponentView::stop() noexcept { + SetFocusedComponent(nullptr); + if (m_visualAddedToIsland) { + if (auto rootView = m_wkRootView.get()) { + winrt::get_self(rootView)->RemoveRenderedVisual( + OuterVisual()); + } + m_visualAddedToIsland = false; + } + // Disconnect from the Island. In case of an instance reload, the island may now + // be attached to a new RootComponentView, so we should stop interacting with it. + ReactNativeIsland(nullptr); +} + +void RootComponentView::ReactNativeIsland(const winrt::Microsoft::ReactNative::ReactNativeIsland &island) noexcept { + m_wkRootView = island; +} + +winrt::Microsoft::ReactNative::ReactNativeIsland RootComponentView::ReactNativeIsland() noexcept { + return m_wkRootView.get(); +} + +winrt::Microsoft::ReactNative::Composition::PortalComponentView RootComponentView::Portal() const noexcept { + return m_wkPortal.get(); +} + +facebook::react::Point RootComponentView::getClientOffset() const noexcept { + return {}; } winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixels) noexcept { @@ -226,6 +276,10 @@ winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixel static_cast(ptPixels.y) / m_layoutMetrics.pointScaleFactor}; facebook::react::Point localPt; + + // In the case of a sub rootview, we may have a non-zero origin. hitTest takes a pt in the parent coords, so we need + // to apply the current origin + ptDips += m_layoutMetrics.frame.origin; auto tag = hitTest(ptDips, localPt, true); auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_reactContext.Properties()); diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h index 3043faec6ec..7790d171693 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h @@ -46,6 +46,12 @@ struct RootComponentView : RootComponentViewT m_wkRootView{nullptr}; + winrt::weak_ref m_wkPortal{nullptr}; + bool m_visualAddedToIsland{false}; }; } // namespace winrt::Microsoft::ReactNative::Composition::implementation diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp index 3e03460ad23..4739ca7ff5a 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp @@ -42,44 +42,59 @@ HRESULT UiaNavigateHelper( } } break; - case NavigateDirection_LastChild: - __fallthrough; - + case NavigateDirection_LastChild: { + auto children = view.Children(); + if (children.Size() != 0) { + uint32_t index = children.Size() - 1; + do { + auto child = children.GetAt(index).as(); + if (uiaProvider = child->EnsureUiaProvider()) { + break; + } + } while (index-- != 0); + } + } break; case NavigateDirection_FirstChild: { auto children = view.Children(); - auto index = direction == NavigateDirection_FirstChild ? 0 : children.Size() - 1; - if (!children.Size() == 0) { - uiaProvider = children.GetAt(index) - .as() - ->EnsureUiaProvider(); + if (children.Size() != 0) { + uint32_t index = 0; + do { + auto child = children.GetAt(index).as(); + if (uiaProvider = child->EnsureUiaProvider()) { + break; + } + } while (++index != children.Size()); } } break; - case NavigateDirection_NextSibling: { - auto parentCV = view.Parent().as(); + auto parentCV = view.Parent().as(); if (parentCV != nullptr) { auto children = parentCV->Children(); auto it = std::find(children.begin(), children.end(), view); - if (++it != children.end()) { - uiaProvider = (*it) - .as() - ->EnsureUiaProvider(); + + while (++it != children.end()) { + auto nextchild = (*it).as(); + if (uiaProvider = nextchild->EnsureUiaProvider()) { + break; + } } } } break; case NavigateDirection_PreviousSibling: { - auto parentCV = view.Parent().as(); + auto parentCV = view.Parent().as(); if (parentCV != nullptr) { auto children = parentCV->Children(); - for (auto i = children.Size() - 1; i > 0; i--) { - auto child = children.GetAt(i); - if (child == view) { - uiaProvider = children.GetAt(i - 1) - .as() - ->EnsureUiaProvider(); - break; - } + auto it = std::find(children.begin(), children.end(), view); + + if (it != children.begin()) { + do { + it--; + auto prevchild = (*it).as(); + if (uiaProvider = prevchild->EnsureUiaProvider()) { + break; + } + } while (it != children.begin()); } } } break; diff --git a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp index 42339633147..7ecc02d985c 100644 --- a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp @@ -134,7 +134,6 @@ void FabricUIManager::startSurface( auto root = rootComponentViewDescriptor.view .as(); - root->theme(winrt::get_self(rootView.Theme())); root->start(rootView); }); @@ -154,15 +153,11 @@ void FabricUIManager::startSurface( void FabricUIManager::stopSurface(facebook::react::SurfaceId surfaceId) noexcept { m_surfaceManager->stopSurface(surfaceId); auto &rootDescriptor = m_registry.componentViewDescriptorWithTag(surfaceId); + rootDescriptor.view.as()->stop(); m_registry.enqueueComponentViewWithComponentHandle( facebook::react::RootShadowNode::Handle(), surfaceId, rootDescriptor); } -winrt::Microsoft::ReactNative::ReactNativeIsland FabricUIManager::GetReactNativeIsland( - facebook::react::SurfaceId surfaceId) const noexcept { - return m_surfaceRegistry.at(surfaceId).wkRootView.get(); -} - facebook::react::Size FabricUIManager::measureSurface( facebook::react::SurfaceId surfaceId, const facebook::react::LayoutConstraints &layoutConstraints, diff --git a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h index 03ffd7635d1..32669487df9 100644 --- a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +++ b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h @@ -49,9 +49,6 @@ struct FabricUIManager final : public std::enable_shared_from_this NotifyMountedId() noexcept; private: diff --git a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp index c7947ac85d6..b3c0fc9815e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -37,7 +36,6 @@ WindowsComponentDescriptorRegistry::WindowsComponentDescriptorRegistry() facebook::react::ActivityIndicatorViewComponentDescriptor>()); add(facebook::react::concreteComponentDescriptorProvider()); add(facebook::react::concreteComponentDescriptorProvider()); - add(facebook::react::concreteComponentDescriptorProvider()); add(facebook::react::concreteComponentDescriptorProvider()); add(facebook::react::concreteComponentDescriptorProvider()); add(facebook::react::concreteComponentDescriptorProvider()); diff --git a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl index 2edf2b822aa..788b982e463 100644 --- a/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +++ b/vnext/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl @@ -21,6 +21,10 @@ namespace Microsoft.ReactNative.Composition [experimental] delegate void ComponentIslandComponentViewInitializer(ContentIslandComponentView view); + [webhosthidden] + [experimental] + delegate void PortalComponentViewInitializer(PortalComponentView view); + [experimental] [webhosthidden] delegate Microsoft.UI.Composition.Visual CreateVisualDelegate(Microsoft.ReactNative.ComponentView view); @@ -55,6 +59,7 @@ namespace Microsoft.ReactNative.Composition { void SetViewComponentViewInitializer(ViewComponentViewInitializer initializer); void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer); + void SetPortalComponentViewInitializer(PortalComponentViewInitializer initializer); void SetCreateVisualHandler(CreateVisualDelegate impl); void SetViewFeatures(ComponentViewFeatures viewFeatures); void SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl); diff --git a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp index 781bbd9d657..4b41880ffca 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeHost.cpp +++ b/vnext/Microsoft.ReactNative/ReactNativeHost.cpp @@ -15,6 +15,7 @@ #include "ReactInstanceSettings.h" #ifdef USE_FABRIC +#include #include #include #include @@ -115,6 +116,10 @@ IAsyncAction ReactNativeHost::ReloadInstance() noexcept { #endif m_instanceSettings.UseWebDebugger()); +#ifdef USE_FABRIC + winrt::Microsoft::ReactNative::Composition::implementation::RegisterWindowsModalHostNativeComponent(m_packageBuilder); +#endif + if (auto packageProviders = InstanceSettings().PackageProviders()) { for (auto const &packageProvider : packageProviders) { packageProvider.CreatePackage(m_packageBuilder); diff --git a/vnext/Microsoft.ReactNative/ReactNativeIsland.idl b/vnext/Microsoft.ReactNative/ReactNativeIsland.idl index 453bbb25107..67d1937c34a 100644 --- a/vnext/Microsoft.ReactNative/ReactNativeIsland.idl +++ b/vnext/Microsoft.ReactNative/ReactNativeIsland.idl @@ -6,6 +6,8 @@ import "ReactCoreInjection.idl"; import "ReactNativeHost.idl"; import "Theme.idl"; import "IReactViewComponentBuilder.idl"; +import "CompositionComponentView.idl"; + #include "NamespaceRedirect.h" #include "DocString.h" @@ -83,7 +85,9 @@ namespace Microsoft.ReactNative #ifdef USE_WINUI3 ReactNativeIsland(Microsoft.UI.Composition.Compositor compositor); - ReactNativeIsland(Microsoft.UI.Composition.Compositor compositor, Microsoft.ReactNative.IReactContext context, Microsoft.ReactNative.ComponentView componentView); + + DOC_STRING("Used to create react portals, such as a native modal component.") + static ReactNativeIsland CreatePortal(Microsoft.ReactNative.Composition.PortalComponentView portal); #endif DOC_STRING( diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index 9371302169c..0ee344ffeac 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -111,10 +111,10 @@ true - + true - + true @@ -317,6 +317,7 @@ + diff --git a/vnext/Shared/Shared.vcxitems.filters b/vnext/Shared/Shared.vcxitems.filters index a563dd848cd..de115b08a9e 100644 --- a/vnext/Shared/Shared.vcxitems.filters +++ b/vnext/Shared/Shared.vcxitems.filters @@ -179,9 +179,6 @@ Source Files\Fabric\Composition - - Source Files\Fabric\Composition - Source Files\Fabric\Composition @@ -239,6 +236,7 @@ Source Files\Fabric\platform\react\renderer\textlayoutmanager + @@ -786,6 +784,7 @@ Header Files\Fabric\platform\react\renderer\textlayoutmanager + diff --git a/vnext/codegen/react/components/rnwcore/ActivityIndicatorView.g.h b/vnext/codegen/react/components/rnwcore/ActivityIndicatorView.g.h new file mode 100644 index 00000000000..20bded81dc3 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/ActivityIndicatorView.g.h @@ -0,0 +1,212 @@ + +/* + * This file is auto-generated from ActivityIndicatorViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(ActivityIndicatorViewProps) +struct ActivityIndicatorViewProps : winrt::implements { + ActivityIndicatorViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + hidesWhenStopped = cloneFromProps->hidesWhenStopped; + animating = cloneFromProps->animating; + color = cloneFromProps->color; + size = cloneFromProps->size; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(hidesWhenStopped) + bool hidesWhenStopped{true}; + + REACT_FIELD(animating) + bool animating{true}; + + REACT_FIELD(color) + winrt::Microsoft::ReactNative::Color color{nullptr}; + + REACT_FIELD(size) + std::optional size; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct ActivityIndicatorViewEventEmitter { + ActivityIndicatorViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseActivityIndicatorView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterActivityIndicatorViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"ActivityIndicatorView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseActivityIndicatorView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseActivityIndicatorView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseActivityIndicatorView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseActivityIndicatorView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseActivityIndicatorView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseActivityIndicatorView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h b/vnext/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h new file mode 100644 index 00000000000..5b57b09eb35 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h @@ -0,0 +1,295 @@ + +/* + * This file is auto-generated from AndroidDrawerLayoutNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(AndroidDrawerLayoutProps) +struct AndroidDrawerLayoutProps : winrt::implements { + AndroidDrawerLayoutProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + keyboardDismissMode = cloneFromProps->keyboardDismissMode; + drawerBackgroundColor = cloneFromProps->drawerBackgroundColor; + drawerPosition = cloneFromProps->drawerPosition; + drawerWidth = cloneFromProps->drawerWidth; + drawerLockMode = cloneFromProps->drawerLockMode; + statusBarBackgroundColor = cloneFromProps->statusBarBackgroundColor; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(keyboardDismissMode) + std::optional keyboardDismissMode; + + REACT_FIELD(drawerBackgroundColor) + winrt::Microsoft::ReactNative::Color drawerBackgroundColor{nullptr}; + + REACT_FIELD(drawerPosition) + std::optional drawerPosition; + + REACT_FIELD(drawerWidth) + std::optional drawerWidth{}; + + REACT_FIELD(drawerLockMode) + std::optional drawerLockMode; + + REACT_FIELD(statusBarBackgroundColor) + winrt::Microsoft::ReactNative::Color statusBarBackgroundColor{nullptr}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(AndroidDrawerLayout_OnDrawerSlide) +struct AndroidDrawerLayout_OnDrawerSlide { + REACT_FIELD(offset) + float offset{}; +}; + +REACT_STRUCT(AndroidDrawerLayout_OnDrawerStateChanged) +struct AndroidDrawerLayout_OnDrawerStateChanged { + REACT_FIELD(drawerState) + int32_t drawerState{}; +}; + +REACT_STRUCT(AndroidDrawerLayout_OnDrawerOpen) +struct AndroidDrawerLayout_OnDrawerOpen { +}; + +REACT_STRUCT(AndroidDrawerLayout_OnDrawerClose) +struct AndroidDrawerLayout_OnDrawerClose { +}; + +struct AndroidDrawerLayoutEventEmitter { + AndroidDrawerLayoutEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnDrawerSlide = AndroidDrawerLayout_OnDrawerSlide; + using OnDrawerStateChanged = AndroidDrawerLayout_OnDrawerStateChanged; + using OnDrawerOpen = AndroidDrawerLayout_OnDrawerOpen; + using OnDrawerClose = AndroidDrawerLayout_OnDrawerClose; + + void onDrawerSlide(OnDrawerSlide &value) const { + m_eventEmitter.DispatchEvent(L"drawerSlide", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onDrawerStateChanged(OnDrawerStateChanged &value) const { + m_eventEmitter.DispatchEvent(L"drawerStateChanged", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onDrawerOpen(OnDrawerOpen &value) const { + m_eventEmitter.DispatchEvent(L"drawerOpen", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onDrawerClose(OnDrawerClose &value) const { + m_eventEmitter.DispatchEvent(L"drawerClose", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseAndroidDrawerLayout { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "openDrawer" command + virtual void HandleOpenDrawerCommand() noexcept = 0; + + // You must provide an implementation of this method to handle the "closeDrawer" command + virtual void HandleCloseDrawerCommand() noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"openDrawer") { + + userData->HandleOpenDrawerCommand(); + return; + } + + if (commandName == L"closeDrawer") { + + userData->HandleCloseDrawerCommand(); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterAndroidDrawerLayoutNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"AndroidDrawerLayout", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseAndroidDrawerLayout::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseAndroidDrawerLayout::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BaseAndroidDrawerLayout::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseAndroidDrawerLayout::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseAndroidDrawerLayout::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseAndroidDrawerLayout::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h b/vnext/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h new file mode 100644 index 00000000000..a42ace8fd41 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h @@ -0,0 +1,200 @@ + +/* + * This file is auto-generated from AndroidHorizontalScrollContentViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(AndroidHorizontalScrollContentViewProps) +struct AndroidHorizontalScrollContentViewProps : winrt::implements { + AndroidHorizontalScrollContentViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + removeClippedSubviews = cloneFromProps->removeClippedSubviews; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(removeClippedSubviews) + std::optional removeClippedSubviews{}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct AndroidHorizontalScrollContentViewEventEmitter { + AndroidHorizontalScrollContentViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseAndroidHorizontalScrollContentView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterAndroidHorizontalScrollContentViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"AndroidHorizontalScrollContentView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseAndroidHorizontalScrollContentView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseAndroidHorizontalScrollContentView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseAndroidHorizontalScrollContentView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseAndroidHorizontalScrollContentView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseAndroidHorizontalScrollContentView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseAndroidHorizontalScrollContentView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/AndroidProgressBar.g.h b/vnext/codegen/react/components/rnwcore/AndroidProgressBar.g.h new file mode 100644 index 00000000000..5f606f132f0 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/AndroidProgressBar.g.h @@ -0,0 +1,224 @@ + +/* + * This file is auto-generated from AndroidProgressBarNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(AndroidProgressBarProps) +struct AndroidProgressBarProps : winrt::implements { + AndroidProgressBarProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + styleAttr = cloneFromProps->styleAttr; + typeAttr = cloneFromProps->typeAttr; + indeterminate = cloneFromProps->indeterminate; + progress = cloneFromProps->progress; + animating = cloneFromProps->animating; + color = cloneFromProps->color; + testID = cloneFromProps->testID; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(styleAttr) + std::optional styleAttr; + + REACT_FIELD(typeAttr) + std::optional typeAttr; + + REACT_FIELD(indeterminate) + bool indeterminate{}; + + REACT_FIELD(progress) + std::optional progress{}; + + REACT_FIELD(animating) + bool animating{true}; + + REACT_FIELD(color) + winrt::Microsoft::ReactNative::Color color{nullptr}; + + REACT_FIELD(testID) + std::optional testID; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct AndroidProgressBarEventEmitter { + AndroidProgressBarEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseAndroidProgressBar { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterAndroidProgressBarNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"AndroidProgressBar", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseAndroidProgressBar::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseAndroidProgressBar::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseAndroidProgressBar::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseAndroidProgressBar::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseAndroidProgressBar::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseAndroidProgressBar::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h b/vnext/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h new file mode 100644 index 00000000000..2254e963093 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h @@ -0,0 +1,250 @@ + +/* + * This file is auto-generated from AndroidSwipeRefreshLayoutNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(AndroidSwipeRefreshLayoutProps) +struct AndroidSwipeRefreshLayoutProps : winrt::implements { + AndroidSwipeRefreshLayoutProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + enabled = cloneFromProps->enabled; + colors = cloneFromProps->colors; + progressBackgroundColor = cloneFromProps->progressBackgroundColor; + size = cloneFromProps->size; + progressViewOffset = cloneFromProps->progressViewOffset; + refreshing = cloneFromProps->refreshing; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(enabled) + bool enabled{true}; + + REACT_FIELD(colors) + std::optional> colors; + + REACT_FIELD(progressBackgroundColor) + winrt::Microsoft::ReactNative::Color progressBackgroundColor{nullptr}; + + REACT_FIELD(size) + std::optional size; + + REACT_FIELD(progressViewOffset) + std::optional progressViewOffset{}; + + REACT_FIELD(refreshing) + bool refreshing{}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(AndroidSwipeRefreshLayout_OnRefresh) +struct AndroidSwipeRefreshLayout_OnRefresh { +}; + +struct AndroidSwipeRefreshLayoutEventEmitter { + AndroidSwipeRefreshLayoutEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnRefresh = AndroidSwipeRefreshLayout_OnRefresh; + + void onRefresh(OnRefresh &value) const { + m_eventEmitter.DispatchEvent(L"refresh", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseAndroidSwipeRefreshLayout { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "setNativeRefreshing" command + virtual void HandleSetNativeRefreshingCommand(bool value) noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"setNativeRefreshing") { + bool value; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), value); + userData->HandleSetNativeRefreshingCommand(value); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterAndroidSwipeRefreshLayoutNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"AndroidSwipeRefreshLayout", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseAndroidSwipeRefreshLayout::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseAndroidSwipeRefreshLayout::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BaseAndroidSwipeRefreshLayout::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseAndroidSwipeRefreshLayout::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseAndroidSwipeRefreshLayout::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseAndroidSwipeRefreshLayout::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/AndroidSwitch.g.h b/vnext/codegen/react/components/rnwcore/AndroidSwitch.g.h new file mode 100644 index 00000000000..5b07056e871 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/AndroidSwitch.g.h @@ -0,0 +1,267 @@ + +/* + * This file is auto-generated from AndroidSwitchNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(AndroidSwitchProps) +struct AndroidSwitchProps : winrt::implements { + AndroidSwitchProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + disabled = cloneFromProps->disabled; + enabled = cloneFromProps->enabled; + thumbColor = cloneFromProps->thumbColor; + trackColorForFalse = cloneFromProps->trackColorForFalse; + trackColorForTrue = cloneFromProps->trackColorForTrue; + value = cloneFromProps->value; + on = cloneFromProps->on; + thumbTintColor = cloneFromProps->thumbTintColor; + trackTintColor = cloneFromProps->trackTintColor; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(disabled) + std::optional disabled{}; + + REACT_FIELD(enabled) + bool enabled{true}; + + REACT_FIELD(thumbColor) + winrt::Microsoft::ReactNative::Color thumbColor{nullptr}; + + REACT_FIELD(trackColorForFalse) + winrt::Microsoft::ReactNative::Color trackColorForFalse{nullptr}; + + REACT_FIELD(trackColorForTrue) + winrt::Microsoft::ReactNative::Color trackColorForTrue{nullptr}; + + REACT_FIELD(value) + std::optional value{}; + + REACT_FIELD(on) + std::optional on{}; + + REACT_FIELD(thumbTintColor) + winrt::Microsoft::ReactNative::Color thumbTintColor{nullptr}; + + REACT_FIELD(trackTintColor) + winrt::Microsoft::ReactNative::Color trackTintColor{nullptr}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(AndroidSwitch_OnChange) +struct AndroidSwitch_OnChange { + REACT_FIELD(value) + bool value{}; + + REACT_FIELD(target) + int32_t target{}; +}; + +struct AndroidSwitchEventEmitter { + AndroidSwitchEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnChange = AndroidSwitch_OnChange; + + void onChange(OnChange &value) const { + m_eventEmitter.DispatchEvent(L"change", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseAndroidSwitch { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "setNativeValue" command + virtual void HandleSetNativeValueCommand(bool value) noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"setNativeValue") { + bool value; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), value); + userData->HandleSetNativeValueCommand(value); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterAndroidSwitchNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"AndroidSwitch", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseAndroidSwitch::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseAndroidSwitch::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BaseAndroidSwitch::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseAndroidSwitch::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseAndroidSwitch::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseAndroidSwitch::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/DebuggingOverlay.g.h b/vnext/codegen/react/components/rnwcore/DebuggingOverlay.g.h new file mode 100644 index 00000000000..fe40aa30d7d --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/DebuggingOverlay.g.h @@ -0,0 +1,234 @@ + +/* + * This file is auto-generated from DebuggingOverlayNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(DebuggingOverlayProps) +struct DebuggingOverlayProps : winrt::implements { + DebuggingOverlayProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct DebuggingOverlayEventEmitter { + DebuggingOverlayEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseDebuggingOverlay { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "highlightTraceUpdates" command + virtual void HandleHighlightTraceUpdatesCommand(std::vector updates) noexcept = 0; + + // You must provide an implementation of this method to handle the "highlightElements" command + virtual void HandleHighlightElementsCommand(std::vector elements) noexcept = 0; + + // You must provide an implementation of this method to handle the "clearElementsHighlights" command + virtual void HandleClearElementsHighlightsCommand() noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"highlightTraceUpdates") { + std::vector updates; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), updates); + userData->HandleHighlightTraceUpdatesCommand(updates); + return; + } + + if (commandName == L"highlightElements") { + std::vector elements; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), elements); + userData->HandleHighlightElementsCommand(elements); + return; + } + + if (commandName == L"clearElementsHighlights") { + + userData->HandleClearElementsHighlightsCommand(); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterDebuggingOverlayNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"DebuggingOverlay", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseDebuggingOverlay::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseDebuggingOverlay::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BaseDebuggingOverlay::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseDebuggingOverlay::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseDebuggingOverlay::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseDebuggingOverlay::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/InputAccessory.g.h b/vnext/codegen/react/components/rnwcore/InputAccessory.g.h new file mode 100644 index 00000000000..f9e8e469905 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/InputAccessory.g.h @@ -0,0 +1,200 @@ + +/* + * This file is auto-generated from InputAccessoryNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(InputAccessoryProps) +struct InputAccessoryProps : winrt::implements { + InputAccessoryProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + backgroundColor = cloneFromProps->backgroundColor; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(backgroundColor) + winrt::Microsoft::ReactNative::Color backgroundColor{nullptr}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct InputAccessoryEventEmitter { + InputAccessoryEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseInputAccessory { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterInputAccessoryNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"InputAccessory", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseInputAccessory::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseInputAccessory::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseInputAccessory::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseInputAccessory::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseInputAccessory::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseInputAccessory::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/ModalHostView.g.h b/vnext/codegen/react/components/rnwcore/ModalHostView.g.h new file mode 100644 index 00000000000..1529aea68ad --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/ModalHostView.g.h @@ -0,0 +1,283 @@ + +/* + * This file is auto-generated from ModalHostViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(ModalHostViewProps) +struct ModalHostViewProps : winrt::implements { + ModalHostViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + animationType = cloneFromProps->animationType; + presentationStyle = cloneFromProps->presentationStyle; + transparent = cloneFromProps->transparent; + statusBarTranslucent = cloneFromProps->statusBarTranslucent; + navigationBarTranslucent = cloneFromProps->navigationBarTranslucent; + hardwareAccelerated = cloneFromProps->hardwareAccelerated; + visible = cloneFromProps->visible; + animated = cloneFromProps->animated; + supportedOrientations = cloneFromProps->supportedOrientations; + identifier = cloneFromProps->identifier; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(animationType) + std::optional animationType; + + REACT_FIELD(presentationStyle) + std::optional presentationStyle; + + REACT_FIELD(transparent) + std::optional transparent{}; + + REACT_FIELD(statusBarTranslucent) + std::optional statusBarTranslucent{}; + + REACT_FIELD(navigationBarTranslucent) + std::optional navigationBarTranslucent{}; + + REACT_FIELD(hardwareAccelerated) + std::optional hardwareAccelerated{}; + + REACT_FIELD(visible) + std::optional visible{}; + + REACT_FIELD(animated) + std::optional animated{}; + + REACT_FIELD(supportedOrientations) + std::optional> supportedOrientations; + + REACT_FIELD(identifier) + std::optional identifier{}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(ModalHostView_OnRequestClose) +struct ModalHostView_OnRequestClose { +}; + +REACT_STRUCT(ModalHostView_OnShow) +struct ModalHostView_OnShow { +}; + +REACT_STRUCT(ModalHostView_OnDismiss) +struct ModalHostView_OnDismiss { +}; + +REACT_STRUCT(ModalHostView_OnOrientationChange) +struct ModalHostView_OnOrientationChange { + REACT_FIELD(orientation) + std::string orientation; +}; + +struct ModalHostViewEventEmitter { + ModalHostViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnRequestClose = ModalHostView_OnRequestClose; + using OnShow = ModalHostView_OnShow; + using OnDismiss = ModalHostView_OnDismiss; + using OnOrientationChange = ModalHostView_OnOrientationChange; + + void onRequestClose(OnRequestClose &value) const { + m_eventEmitter.DispatchEvent(L"requestClose", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onShow(OnShow &value) const { + m_eventEmitter.DispatchEvent(L"show", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onDismiss(OnDismiss &value) const { + m_eventEmitter.DispatchEvent(L"dismiss", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + void onOrientationChange(OnOrientationChange &value) const { + m_eventEmitter.DispatchEvent(L"orientationChange", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseModalHostView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterModalHostViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"ModalHostView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseModalHostView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseModalHostView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseModalHostView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseModalHostView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseModalHostView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseModalHostView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/PullToRefreshView.g.h b/vnext/codegen/react/components/rnwcore/PullToRefreshView.g.h new file mode 100644 index 00000000000..c9aabcd6cb1 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/PullToRefreshView.g.h @@ -0,0 +1,246 @@ + +/* + * This file is auto-generated from PullToRefreshViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(PullToRefreshViewProps) +struct PullToRefreshViewProps : winrt::implements { + PullToRefreshViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + tintColor = cloneFromProps->tintColor; + titleColor = cloneFromProps->titleColor; + title = cloneFromProps->title; + progressViewOffset = cloneFromProps->progressViewOffset; + refreshing = cloneFromProps->refreshing; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(tintColor) + winrt::Microsoft::ReactNative::Color tintColor{nullptr}; + + REACT_FIELD(titleColor) + winrt::Microsoft::ReactNative::Color titleColor{nullptr}; + + REACT_FIELD(title) + std::optional title; + + REACT_FIELD(progressViewOffset) + std::optional progressViewOffset{}; + + REACT_FIELD(refreshing) + bool refreshing{}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(PullToRefreshView_OnRefresh) +struct PullToRefreshView_OnRefresh { +}; + +struct PullToRefreshViewEventEmitter { + PullToRefreshViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnRefresh = PullToRefreshView_OnRefresh; + + void onRefresh(OnRefresh &value) const { + m_eventEmitter.DispatchEvent(L"refresh", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BasePullToRefreshView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "setNativeRefreshing" command + virtual void HandleSetNativeRefreshingCommand(bool refreshing) noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"setNativeRefreshing") { + bool refreshing; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), refreshing); + userData->HandleSetNativeRefreshingCommand(refreshing); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterPullToRefreshViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"PullToRefreshView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BasePullToRefreshView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BasePullToRefreshView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BasePullToRefreshView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BasePullToRefreshView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BasePullToRefreshView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BasePullToRefreshView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/SafeAreaView.g.h b/vnext/codegen/react/components/rnwcore/SafeAreaView.g.h new file mode 100644 index 00000000000..6e7a2f07a67 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/SafeAreaView.g.h @@ -0,0 +1,197 @@ + +/* + * This file is auto-generated from SafeAreaViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(SafeAreaViewProps) +struct SafeAreaViewProps : winrt::implements { + SafeAreaViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct SafeAreaViewEventEmitter { + SafeAreaViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseSafeAreaView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterSafeAreaViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"SafeAreaView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseSafeAreaView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseSafeAreaView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseSafeAreaView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseSafeAreaView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseSafeAreaView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseSafeAreaView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/Switch.g.h b/vnext/codegen/react/components/rnwcore/Switch.g.h new file mode 100644 index 00000000000..18bf2b47fc4 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/Switch.g.h @@ -0,0 +1,263 @@ + +/* + * This file is auto-generated from SwitchNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(SwitchProps) +struct SwitchProps : winrt::implements { + SwitchProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + disabled = cloneFromProps->disabled; + value = cloneFromProps->value; + tintColor = cloneFromProps->tintColor; + onTintColor = cloneFromProps->onTintColor; + thumbTintColor = cloneFromProps->thumbTintColor; + thumbColor = cloneFromProps->thumbColor; + trackColorForFalse = cloneFromProps->trackColorForFalse; + trackColorForTrue = cloneFromProps->trackColorForTrue; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(disabled) + std::optional disabled{}; + + REACT_FIELD(value) + std::optional value{}; + + REACT_FIELD(tintColor) + winrt::Microsoft::ReactNative::Color tintColor{nullptr}; + + REACT_FIELD(onTintColor) + winrt::Microsoft::ReactNative::Color onTintColor{nullptr}; + + REACT_FIELD(thumbTintColor) + winrt::Microsoft::ReactNative::Color thumbTintColor{nullptr}; + + REACT_FIELD(thumbColor) + winrt::Microsoft::ReactNative::Color thumbColor{nullptr}; + + REACT_FIELD(trackColorForFalse) + winrt::Microsoft::ReactNative::Color trackColorForFalse{nullptr}; + + REACT_FIELD(trackColorForTrue) + winrt::Microsoft::ReactNative::Color trackColorForTrue{nullptr}; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +REACT_STRUCT(Switch_OnChange) +struct Switch_OnChange { + REACT_FIELD(value) + bool value{}; + + REACT_FIELD(target) + int32_t target{}; +}; + +struct SwitchEventEmitter { + SwitchEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + using OnChange = Switch_OnChange; + + void onChange(OnChange &value) const { + m_eventEmitter.DispatchEvent(L"change", [value](const winrt::Microsoft::ReactNative::IJSValueWriter writer) { + winrt::Microsoft::ReactNative::WriteValue(writer, value); + }); + } + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseSwitch { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + // You must provide an implementation of this method to handle the "setValue" command + virtual void HandleSetValueCommand(bool value) noexcept = 0; + + void HandleCommand(const winrt::Microsoft::ReactNative::ComponentView &view, const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + auto commandName = args.CommandName(); + if (commandName == L"setValue") { + bool value; + winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), value); + userData->HandleSetValueCommand(value); + return; + } + } + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterSwitchNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"Switch", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseSwitch::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseSwitch::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + builder.SetCustomCommandHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::HandleCommandArgs& args) noexcept { + auto userData = view.UserData().as(); + userData->HandleCommand(view, args); + }); + + if constexpr (&TUserData::MountChildComponentView != &BaseSwitch::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseSwitch::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseSwitch::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseSwitch::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/codegen/react/components/rnwcore/UnimplementedNativeView.g.h b/vnext/codegen/react/components/rnwcore/UnimplementedNativeView.g.h new file mode 100644 index 00000000000..1251cb720d2 --- /dev/null +++ b/vnext/codegen/react/components/rnwcore/UnimplementedNativeView.g.h @@ -0,0 +1,200 @@ + +/* + * This file is auto-generated from UnimplementedNativeViewNativeComponent spec file in flow / TypeScript. + */ +// clang-format off +#pragma once + +#include + +#ifdef RNW_NEW_ARCH +#include + +#include +#include +#endif // #ifdef RNW_NEW_ARCH + +#ifdef RNW_NEW_ARCH + +namespace Microsoft::ReactNativeSpecs { + +REACT_STRUCT(UnimplementedNativeViewProps) +struct UnimplementedNativeViewProps : winrt::implements { + UnimplementedNativeViewProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) + : ViewProps(props) + { + if (cloneFrom) { + auto cloneFromProps = cloneFrom.as(); + name = cloneFromProps->name; + } + } + + void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept { + winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this); + } + + REACT_FIELD(name) + std::optional name; + + const winrt::Microsoft::ReactNative::ViewProps ViewProps; +}; + +struct UnimplementedNativeViewEventEmitter { + UnimplementedNativeViewEventEmitter(const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) + : m_eventEmitter(eventEmitter) {} + + private: + winrt::Microsoft::ReactNative::EventEmitter m_eventEmitter{nullptr}; +}; + +template +struct BaseUnimplementedNativeView { + + virtual void UpdateProps( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::com_ptr &newProps, + const winrt::com_ptr &/*oldProps*/) noexcept { + m_props = newProps; + } + + // UpdateLayoutMetrics will only be called if this method is overridden + virtual void UpdateLayoutMetrics( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*newLayoutMetrics*/, + const winrt::Microsoft::ReactNative::LayoutMetrics &/*oldLayoutMetrics*/) noexcept { + } + + // UpdateState will only be called if this method is overridden + virtual void UpdateState( + const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::IComponentState &/*newState*/) noexcept { + } + + virtual void UpdateEventEmitter(const std::shared_ptr &eventEmitter) noexcept { + m_eventEmitter = eventEmitter; + } + + // MountChildComponentView will only be called if this method is overridden + virtual void MountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &/*args*/) noexcept { + } + + // UnmountChildComponentView will only be called if this method is overridden + virtual void UnmountChildComponentView(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &/*args*/) noexcept { + } + + // Initialize will only be called if this method is overridden + virtual void Initialize(const winrt::Microsoft::ReactNative::ComponentView &/*view*/) noexcept { + } + + // CreateVisual will only be called if this method is overridden + virtual winrt::Microsoft::UI::Composition::Visual CreateVisual(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + return view.as().Compositor().CreateSpriteVisual(); + } + + // FinalizeUpdate will only be called if this method is overridden + virtual void FinalizeUpdate(const winrt::Microsoft::ReactNative::ComponentView &/*view*/, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask /*mask*/) noexcept { + } + + + + const std::shared_ptr& EventEmitter() const { return m_eventEmitter; } + const winrt::com_ptr& Props() const { return m_props; } + +private: + winrt::com_ptr m_props; + std::shared_ptr m_eventEmitter; +}; + +template +void RegisterUnimplementedNativeViewNativeComponent( + winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder, + std::function builderCallback) noexcept { + packageBuilder.as().AddViewComponent( + L"UnimplementedNativeView", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept { + auto compBuilder = builder.as(); + + builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props, + const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept { + return winrt::make(props, cloneFrom); + }); + + builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentProps &newProps, + const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept { + auto userData = view.UserData().as(); + userData->UpdateProps(view, newProps ? newProps.as() : nullptr, oldProps ? oldProps.as() : nullptr); + }); + + compBuilder.SetUpdateLayoutMetricsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::LayoutMetrics &newLayoutMetrics, + const winrt::Microsoft::ReactNative::LayoutMetrics &oldLayoutMetrics) noexcept { + auto userData = view.UserData().as(); + userData->UpdateLayoutMetrics(view, newLayoutMetrics, oldLayoutMetrics); + }); + + builder.SetUpdateEventEmitterHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::EventEmitter &eventEmitter) noexcept { + auto userData = view.UserData().as(); + userData->UpdateEventEmitter(std::make_shared(eventEmitter)); + }); + + if constexpr (&TUserData::FinalizeUpdate != &BaseUnimplementedNativeView::FinalizeUpdate) { + builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + winrt::Microsoft::ReactNative::ComponentViewUpdateMask mask) noexcept { + auto userData = view.UserData().as(); + userData->FinalizeUpdate(view, mask); + }); + } + + if constexpr (&TUserData::UpdateState != &BaseUnimplementedNativeView::UpdateState) { + builder.SetUpdateStateHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::IComponentState &newState) noexcept { + auto userData = view.UserData().as(); + userData->member(view, newState); + }); + } + + if constexpr (&TUserData::MountChildComponentView != &BaseUnimplementedNativeView::MountChildComponentView) { + builder.SetMountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::MountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->MountChildComponentView(view, args); + }); + } + + if constexpr (&TUserData::UnmountChildComponentView != &BaseUnimplementedNativeView::UnmountChildComponentView) { + builder.SetUnmountChildComponentViewHandler([](const winrt::Microsoft::ReactNative::ComponentView &view, + const winrt::Microsoft::ReactNative::UnmountChildComponentViewArgs &args) noexcept { + auto userData = view.UserData().as(); + return userData->UnmountChildComponentView(view, args); + }); + } + + compBuilder.SetViewComponentViewInitializer([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = winrt::make_self(); + if constexpr (&TUserData::Initialize != &BaseUnimplementedNativeView::Initialize) { + userData->Initialize(view); + } + view.UserData(*userData); + }); + + if constexpr (&TUserData::CreateVisual != &BaseUnimplementedNativeView::CreateVisual) { + compBuilder.SetCreateVisualHandler([](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept { + auto userData = view.UserData().as(); + return userData->CreateVisual(view); + }); + } + + // Allow app to further customize the builder + if (builderCallback) { + builderCallback(compBuilder); + } + }); +} + +} // namespace Microsoft::ReactNativeSpecs + +#endif // #ifdef RNW_NEW_ARCH diff --git a/vnext/just-task.js b/vnext/just-task.js index fe151b5579d..957cf343e1a 100644 --- a/vnext/just-task.js +++ b/vnext/just-task.js @@ -28,7 +28,7 @@ option('clean'); function codegen(test) { execSync( - `react-native-windows-codegen --files src/**/*Native*.js --namespace Microsoft::ReactNativeSpecs --libraryName rnwcore --modulesWindows --internalComponents --modulesCxx${ + `react-native-windows-codegen --files src/**/*Native*.js --namespace Microsoft::ReactNativeSpecs --libraryName rnwcore --componentsWindows --modulesWindows --internalComponents --modulesCxx${ test ? ' --test' : '' }`, {env: process.env}, diff --git a/vnext/overrides.json b/vnext/overrides.json index c7128a98d0e..ed259f8a837 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -16,24 +16,6 @@ "baseFile": ".flowconfig", "baseHash": "38943f268bd48c91a2ace6ad2a9302a3bb346dbd" }, - { - "type": "derived", - "file": "Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h", - "baseFile": "packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h", - "baseHash": "e565039785bb3cf479021322074870c82be58b82" - }, - { - "type": "derived", - "file": "Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp", - "baseFile": "packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.cpp", - "baseHash": "18699cf9b127e7c09be0ae406ca57051691b52e2" - }, - { - "type": "derived", - "file": "Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h", - "baseFile": "packages/react-native/ReactCommon/react/renderer/components/modal/ModalHostViewShadowNode.h", - "baseHash": "29d8881a9ebce7a85d1f6b80a6a3c6e6768a7bfc" - }, { "type": "derived", "file": "Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h",