Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Fix issue when creating a ContentIslandComponentView when the root ReactNativeIsland is not connected",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}
2 changes: 2 additions & 0 deletions vnext/Microsoft.ReactNative/CompositionComponentView.idl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ namespace Microsoft.ReactNative.Composition
[webhosthidden]
runtimeclass ContentIslandComponentView : ViewComponentView {
void Connect(Microsoft.UI.Content.ContentIsland contentIsland);
DOC_STRING("The ChildSiteLink will be unavailable until after the ContentIslandComponentView is mounted")
Microsoft.UI.Content.ChildSiteLink ChildSiteLink { get; };
};

[experimental]
Expand Down
2 changes: 1 addition & 1 deletion vnext/Microsoft.ReactNative/Fabric/ComponentView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void ComponentView::onMounted() noexcept {
m_mountedEvent(*this, *this);
}

bool ComponentView::isMounted() noexcept {
bool ComponentView::isMounted() const noexcept {
return m_mounted;
}

Expand Down
2 changes: 1 addition & 1 deletion vnext/Microsoft.ReactNative/Fabric/ComponentView.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ struct ComponentView
virtual void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
virtual void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
virtual void onMounted() noexcept;
bool isMounted() noexcept;
bool isMounted() const noexcept;
virtual void onUnmounted() noexcept;
void onDestroying() noexcept;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,23 @@ winrt::Microsoft::UI::Content::ContentIsland ContentIslandComponentView::ParentC
return root->parentContentIsland();
}

winrt::Microsoft::UI::Content::ChildSiteLink ContentIslandComponentView::ChildSiteLink() noexcept {
if (!isMounted())
return nullptr;
if (!m_childSiteLink) {
m_childSiteLink = winrt::Microsoft::UI::Content::ChildSiteLink::Create(
m_parentContentIsland,
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(Visual())
.as<winrt::Microsoft::UI::Composition::ContainerVisual>());
}
return m_childSiteLink;
}

void ContentIslandComponentView::ConnectInternal() noexcept {
if (!m_islandToConnect)
return;

m_childSiteLink = winrt::Microsoft::UI::Content::ChildSiteLink::Create(
m_parentContentIsland,
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(Visual())
.as<winrt::Microsoft::UI::Composition::ContainerVisual>());
m_childSiteLink.ActualSize({m_layoutMetrics.frame.size.width, m_layoutMetrics.frame.size.height});
ChildSiteLink().ActualSize({m_layoutMetrics.frame.size.width, m_layoutMetrics.frame.size.height});

m_navigationHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteLink(m_childSiteLink);

Expand All @@ -76,10 +84,18 @@ void ContentIslandComponentView::ConnectInternal() noexcept {
ConfigureChildSiteLinkAutomation();

if (m_islandToConnect) {
Assert(m_childSiteLink.SiteView().IsConnected());
Assert(!m_islandToConnect.IsConnected());

m_childSiteLink.Connect(m_islandToConnect);
m_islandToConnect = nullptr;
}
UnregisterForRootIslandEvents();

if (m_pendingNavigateFocus) {
m_navigationHost.NavigateFocus(
winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(*m_pendingNavigateFocus));
m_pendingNavigateFocus.reset();
}

ParentLayoutChanged();
auto view = Parent();
Expand All @@ -96,33 +112,9 @@ void ContentIslandComponentView::ConnectInternal() noexcept {
}
}

void ContentIslandComponentView::RegisterForRootIslandEvents() noexcept {
m_parentContentIsland = ParentContentIsland();

if (m_parentContentIsland.IsConnected()) {
ConnectInternal();
} else {
m_islandStateChangedToken = m_parentContentIsland.StateChanged(
[wkThis = get_weak()](
const winrt::Microsoft::UI::Content::ContentIsland & /*island*/,
const winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs & /*args*/) {
if (auto strongThis = wkThis.get()) {
strongThis->ConnectInternal();
}
});
}
}

void ContentIslandComponentView::UnregisterForRootIslandEvents() noexcept {
if (m_islandStateChangedToken) {
m_parentContentIsland.StateChanged(m_islandStateChangedToken);
m_islandStateChangedToken = {};
m_parentContentIsland = nullptr;
}
}

void ContentIslandComponentView::OnMounted() noexcept {
RegisterForRootIslandEvents();
m_parentContentIsland = ParentContentIsland();
ConnectInternal();
}

void ContentIslandComponentView::OnUnmounted() noexcept {
Expand All @@ -131,7 +123,6 @@ void ContentIslandComponentView::OnUnmounted() noexcept {
m_navigationHost.DepartFocusRequested(m_navigationHostDepartFocusRequestedToken);
m_navigationHostDepartFocusRequestedToken = {};
}
UnregisterForRootIslandEvents();
}

void ContentIslandComponentView::ParentLayoutChanged() noexcept {
Expand Down Expand Up @@ -205,7 +196,10 @@ void ContentIslandComponentView::onGotFocus(
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
auto gotFocusEventArgs = args.as<winrt::Microsoft::ReactNative::implementation::GotFocusEventArgs>();
const auto navigationReason = GetFocusNavigationReason(gotFocusEventArgs->Direction());
m_navigationHost.NavigateFocus(winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(navigationReason));
if (m_navigationHost)
m_navigationHost.NavigateFocus(winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(navigationReason));
else
m_pendingNavigateFocus = navigationReason;
}

ContentIslandComponentView::~ContentIslandComponentView() noexcept {
Expand Down Expand Up @@ -264,6 +258,9 @@ void ContentIslandComponentView::Connect(const winrt::Microsoft::UI::Content::Co
m_childSiteLink.Connect(contentIsland);
} else {
m_islandToConnect = contentIsland;
if (isMounted()) {
ConnectInternal();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
uint32_t index) noexcept override;
void Connect(const winrt::Microsoft::UI::Content::ContentIsland &contentIsland) noexcept;

winrt::Microsoft::UI::Content::ChildSiteLink ChildSiteLink() noexcept;

void updateLayoutMetrics(
facebook::react::LayoutMetrics const &layoutMetrics,
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept;
Expand Down Expand Up @@ -59,21 +61,20 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
void OnUnmounted() noexcept;
void ParentLayoutChanged() noexcept;
void ConnectInternal() noexcept;
void RegisterForRootIslandEvents() noexcept;
void UnregisterForRootIslandEvents() noexcept;
winrt::Microsoft::UI::Content::ContentIsland ParentContentIsland() noexcept;

bool m_layoutChangePosted{false};
winrt::Microsoft::UI::Content::ContentIsland m_parentContentIsland{nullptr};
winrt::Microsoft::UI::Content::ContentIsland m_islandToConnect{nullptr};
winrt::event_token m_islandStateChangedToken;
std::optional<winrt::Microsoft::UI::Input::FocusNavigationReason> m_pendingNavigateFocus;

winrt::event_token m_mountedToken;
winrt::event_token m_unmountedToken;
std::vector<winrt::Microsoft::ReactNative::ComponentView::LayoutMetricsChanged_revoker> m_layoutMetricChangedRevokers;
winrt::Microsoft::UI::Content::ChildSiteLink m_childSiteLink{nullptr};
winrt::Microsoft::UI::Input::InputFocusNavigationHost m_navigationHost{nullptr};
winrt::event_token m_navigationHostDepartFocusRequestedToken{};
std::optional<winrt::Microsoft::UI::Input::FocusNavigationReason> m_pendingFocus;

// Automation
void ConfigureChildSiteLinkAutomation() noexcept;
Expand Down
Loading