[Fabric] Adds an example of using XamlIslands within fabric (#12589)

* [Fabric] Add support for custom native component to have c++ state and custom measure

* format

* Change files

* fix

* fix

* fix

* More c++ state methods

* Implementation of hosting xaml controls using winappsdk

* format

* build fix

* code review feedback

* Add yoga and inf sized hosting samples

* [Fabric] Add support for custom theme's, and support runtime theme change

* Change files

* buildfix

* cleanup

* Change files

* Remove scrollview changes as they have been split into its own change

* fix

* Bump default SDK to 22000

* lint fix

* fix

* snapshots

* no longer need ExperimentalFeatures.props import in sdx props.
This commit is contained in:
Andrew Coates 2024-01-22 17:02:51 -08:00 коммит произвёл GitHub
Родитель 1b06c4a6ac
Коммит 1e8b8a0d0f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
28 изменённых файлов: 1965 добавлений и 653 удалений

Просмотреть файл

@ -8,5 +8,10 @@
<clear />
<!-- Warning: Do not add/change the NuGet feeds here. To be compliant this repo must only rely on this single ADO feed. -->
<add key="react-native" value="https://pkgs.dev.azure.com/ms/react-native/_packaging/react-native-public/nuget/v3/index.json" />
<!-- For local internal development only, this will allow usage of internal WindowsApp.Sdk builds -->
<!--
<add key="Project.Reunion.nuget.internal" value="https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json" />
-->
</packageSources>
</configuration>

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Update WinUI3Version ",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,34 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import {get} from 'react-native/Libraries/NativeComponent/NativeComponentRegistry';
type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
label: string,
|}>;
// Cannot just use codegenNativeComponent, or registerNativeComponent, since we need to provide a custom config
const MyCustomComponent = get<NativeProps>('MyCustomComponent', () => {
return {
uiViewClassName: 'MyCustomComponent',
bubblingEventTypes: {},
directEventTypes: {},
validAttributes: {
label: true,
},
};
});
exports.MyCustomComponent = MyCustomComponent;

Просмотреть файл

@ -0,0 +1,34 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import {get} from 'react-native/Libraries/NativeComponent/NativeComponentRegistry';
type NativeProps = $ReadOnly<{|
...ViewProps,
// Props
label: string,
|}>;
// Cannot just use codegenNativeComponent, or registerNativeComponent, since we need to provide a custom config
const MyCustomComponentYoga = get<NativeProps>('MyCustomComponentYoga', () => {
return {
uiViewClassName: 'MyCustomComponentYoga',
bubblingEventTypes: {},
directEventTypes: {},
validAttributes: {
label: true,
},
};
});
exports.MyCustomComponentYoga = MyCustomComponentYoga;

Просмотреть файл

@ -0,0 +1,55 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import React from 'react';
import {Text, View} from 'react-native';
import {MyCustomComponent} from './MyCustomComponentNativeComponent';
exports.displayName = 'NativeFabricComponent';
exports.framework = 'React';
exports.category = 'UI';
exports.title = 'Fabric Native Component';
//exports.documentationURL = 'https://reactnative.dev/docs/button';
exports.description =
'Sample Fabric Native Component that sizes based on max desired size of native XAML contained within';
exports.examples = [
{
title: 'Native Component',
render: function (): React.Node {
return (
<View
style={{
borderRadius: 0,
margin: 10,
borderWidth: 2,
flexWrap: 'wrap',
flexDirection: 'row',
gap: 5,
}}>
<View style={{width: 100, height: 100, backgroundColor: 'green'}} />
<View style={{width: 100, height: 100, backgroundColor: 'red'}} />
<View style={{width: 100, height: 100, backgroundColor: 'blue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'pink'}} />
<View style={{width: 100, height: 100, backgroundColor: 'gray'}} />
<Text style={{color: 'gray'}}>This is RN Text</Text>
<MyCustomComponent label="test" style={{flexShrink: 1}} />
<View style={{width: 100, height: 100, backgroundColor: 'green'}} />
<View style={{width: 100, height: 100, backgroundColor: 'red'}} />
<View style={{width: 100, height: 100, backgroundColor: 'blue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'pink'}} />
<View style={{width: 100, height: 100, backgroundColor: 'gray'}} />
</View>
);
},
},
];

Просмотреть файл

@ -0,0 +1,58 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import React from 'react';
import {Text, View} from 'react-native';
import {MyCustomComponentYoga} from './MyCustomComponentYogaNativeComponent';
exports.displayName = 'NativeFabricComponentYoga';
exports.framework = 'React';
exports.category = 'UI';
exports.title = 'Fabric Native Component Yoga';
//exports.documentationURL = 'https://reactnative.dev/docs/button';
exports.description =
'Sample Fabric Native Component that places native XAML inside a container sized by yoga';
exports.examples = [
{
title: 'Native Component',
render: function (): React.Node {
return (
<View
style={{
borderRadius: 0,
margin: 10,
borderWidth: 2,
flexWrap: 'wrap',
flexDirection: 'row',
gap: 5,
}}>
<View style={{width: 100, height: 100, backgroundColor: 'green'}} />
<View style={{width: 100, height: 100, backgroundColor: 'red'}} />
<View style={{width: 100, height: 100, backgroundColor: 'blue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'pink'}} />
<View style={{width: 100, height: 100, backgroundColor: 'gray'}} />
<Text style={{color: 'gray'}}>This is RN Text</Text>
<MyCustomComponentYoga
label="test"
style={{flex: 1, minWidth: 100}}
/>
<View style={{width: 100, height: 100, backgroundColor: 'green'}} />
<View style={{width: 100, height: 100, backgroundColor: 'red'}} />
<View style={{width: 100, height: 100, backgroundColor: 'blue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'pink'}} />
<View style={{width: 100, height: 100, backgroundColor: 'gray'}} />
</View>
);
},
},
];

Просмотреть файл

@ -68,6 +68,14 @@ const Components: Array<RNTesterModuleInfo> = [
// category: 'UI',
// module: require('../examples/Modal/ModalExample'),
// },
{
key: 'Native Component',
module: require('../examples-win/NativeComponents/NativeComponent'),
},
{
key: 'Native Component Yoga',
module: require('../examples-win/NativeComponents/NativeComponentYoga'),
},
{
key: 'NewAppScreenExample',
module: require('../examples/NewAppScreen/NewAppScreenExample'),

Просмотреть файл

@ -1 +1,18 @@
require('react-native');
function componentHasNativeconfig(name: string) {
return name !== 'MyCustomComponent' && name !== 'MyCustomComponentYoga'
}
const nativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
nativeComponentRegistry.setRuntimeConfigProvider((name: string) => {
return {
native: componentHasNativeconfig(name), // The fabric native component test has no viewmanager to get native config from
strict: false,
verify: componentHasNativeconfig(name),
};
});
require('@react-native-windows/tester/js/RNTesterApp');
export {};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9322,6 +9322,253 @@ exports[`snapshotAllPages Display:none Style 1`] = `
</View>
`;
exports[`snapshotAllPages Fabric Native Component 1`] = `
<View
style={
{
"borderRadius": 0,
"borderWidth": 2,
"flexDirection": "row",
"flexWrap": "wrap",
"gap": 5,
"margin": 10,
}
}
>
<View
style={
{
"backgroundColor": "green",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "red",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "blue",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "pink",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "gray",
"height": 100,
"width": 100,
}
}
/>
<Text
style={
{
"color": "gray",
}
}
>
This is RN Text
</Text>
<MyCustomComponent
label="test"
style={
{
"flexShrink": 1,
}
}
/>
<View
style={
{
"backgroundColor": "green",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "red",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "blue",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "pink",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "gray",
"height": 100,
"width": 100,
}
}
/>
</View>
`;
exports[`snapshotAllPages Fabric Native Component Yoga 1`] = `
<View
style={
{
"borderRadius": 0,
"borderWidth": 2,
"flexDirection": "row",
"flexWrap": "wrap",
"gap": 5,
"margin": 10,
}
}
>
<View
style={
{
"backgroundColor": "green",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "red",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "blue",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "pink",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "gray",
"height": 100,
"width": 100,
}
}
/>
<Text
style={
{
"color": "gray",
}
}
>
This is RN Text
</Text>
<MyCustomComponentYoga
label="test"
style={
{
"flex": 1,
"minWidth": 100,
}
}
/>
<View
style={
{
"backgroundColor": "green",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "red",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "blue",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "pink",
"height": 100,
"width": 100,
}
}
/>
<View
style={
{
"backgroundColor": "gray",
"height": 100,
"width": 100,
}
}
/>
</View>
`;
exports[`snapshotAllPages Fast Path Texts 1`] = `
<View>
<Text>

Просмотреть файл

@ -34,6 +34,13 @@ const componentExamples = testerList.Components.map(e => e.module.title);
describe('visitAllPages', () => {
for (const component of componentExamples) {
if (
component === 'Fabric Native Component' ||
component === 'Fabric Native Component Yoga'
) {
continue; // disable fabric specific tests
}
test(component, async () => await goToComponentExample(component));
}

Просмотреть файл

@ -4,7 +4,7 @@
* @format
*/
import React from 'react';
import {AppRegistry, View} from 'react-native';
import {AppRegistry, Text, View} from 'react-native';
import type {ViewProps} from 'react-native';
import {
@ -49,7 +49,8 @@ const Bootstrap = () => {
gap: 5,
height: 500,
}}>
<MyCustomComponent label="test" style={{flex: 1}} />
<Text>This is RN Texsst - </Text>
<MyCustomComponent label="test" />
</View>
);
};

Просмотреть файл

@ -16,12 +16,16 @@
*/
require('react-native');
function componentHasNativeconfig(name: string) {
return name !== 'MyCustomComponent' && name !== 'MyCustomComponentYoga'
}
const nativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
nativeComponentRegistry.setRuntimeConfigProvider((name: string) => {
return {
native: true,
native: componentHasNativeconfig(name), // The fabric native component test has no viewmanager to get native config from
strict: false,
verify: true,
verify: componentHasNativeconfig(name),
};
});

Просмотреть файл

@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace PlaygroundApp
{
}

Просмотреть файл

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation.
Licensed under the MIT License. -->
<Application
x:Class="Playground.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlIslandApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "App.xaml.h"
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::Playground::implementation {
void App::OnLaunched(winrt::Microsoft::UI::Xaml::LaunchActivatedEventArgs const &) {}
} // namespace winrt::Playground::implementation

Просмотреть файл

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "App.xaml.g.h"
#include <winrt/Microsoft.UI.Xaml.Hosting.h>
namespace winrt::Playground::implementation {
struct App : AppT<App> {
App() : m_windowsXamlManager(winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread()) {}
void OnLaunched(winrt::Microsoft::UI::Xaml::LaunchActivatedEventArgs const &);
private:
winrt::Microsoft::UI::Xaml::Hosting::WindowsXamlManager m_windowsXamlManager{nullptr};
};
} // namespace winrt::Playground::implementation

Просмотреть файл

@ -3,12 +3,21 @@
#include <winrt/Microsoft.ReactNative.Composition.Input.h>
#include <winrt/Microsoft.ReactNative.Composition.h>
#include <winrt/Microsoft.ReactNative.h>
#include <winrt/Windows.UI.Composition.h>
#include <winrt/Windows.UI.h>
#ifdef USE_WINUI3
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Microsoft.UI.Content.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Media.h>
#include <winrt/Microsoft.UI.Xaml.h>
#include <winrt/Microsoft.UI.interop.h>
#endif
#include "YogaXamlPanel.h"
/*
* Custom Properties can be passed from JS to this native component
* This struct will eventually be codegen'd from the JS spec file
@ -32,93 +41,108 @@ struct CustomProps : winrt::implements<CustomProps, winrt::Microsoft::ReactNativ
struct CustomComponent : winrt::implements<CustomComponent, winrt::IInspectable> {
CustomComponent(
bool nativeLayout,
winrt::Microsoft::ReactNative::IReactContext reactContext,
winrt::Microsoft::ReactNative::Composition::ICompositionContext compContext)
: m_compContext(compContext) {}
: m_nativeLayout(nativeLayout), m_compContext(compContext), m_reactContext(reactContext) {}
~CustomComponent() {
m_xamlIsland.Close();
m_siteBridge.Close();
// Hit a crash when calling m_contentIsland.Close?
// m_contentIsland.Close();
}
void UpdateProps(winrt::Microsoft::ReactNative::IComponentProps props) noexcept {
auto customProps = props.as<CustomProps>();
}
// This is called with the results of layout from RN. We use this to set the size of the ContentIsland.
void UpdateLayoutMetrics(winrt::Microsoft::ReactNative::Composition::LayoutMetrics layoutMetrics) noexcept {
m_layoutMetrics = layoutMetrics;
m_visual.Size(
{m_layoutMetrics.Frame.Width * m_layoutMetrics.PointScaleFactor,
m_layoutMetrics.Frame.Height * m_layoutMetrics.PointScaleFactor});
{layoutMetrics.Frame.Width * layoutMetrics.PointScaleFactor,
layoutMetrics.Frame.Height * layoutMetrics.PointScaleFactor});
auto site = m_siteBridge.Site();
auto siteWindow = site.Environment();
auto displayScale = siteWindow.DisplayScale();
site.ParentScale(displayScale);
site.ActualSize({layoutMetrics.Frame.Width, layoutMetrics.Frame.Height});
site.ClientSize(winrt::Windows::Graphics::SizeInt32{
static_cast<int32_t>(layoutMetrics.Frame.Width * layoutMetrics.PointScaleFactor),
static_cast<int32_t>(layoutMetrics.Frame.Height * layoutMetrics.PointScaleFactor)});
}
// Custom state used in when using native layout to store the desired size of the Xaml control for use during RN
// layout on a background thread
struct MyStateData : winrt::implements<MyStateData, winrt::IInspectable> {
MyStateData(winrt::Windows::Foundation::Size ds) : desiredSize(ds) {}
winrt::Windows::Foundation::Size desiredSize;
};
winrt::Microsoft::UI::Xaml::UIElement CreateXamlButtonContent() {
auto text = winrt::Microsoft::UI::Xaml::Controls::TextBlock();
text.Text(L"This is a Xaml Button set to ellipisify on truncation");
text.TextTrimming(winrt::Microsoft::UI::Xaml::TextTrimming::CharacterEllipsis);
auto button = winrt::Microsoft::UI::Xaml::Controls::Button();
button.Margin({3, 3, 3, 3});
button.Content(text);
// If we are using native layout then wrap the element in a YogaXamlPanel which reports any changes to desired size
// of the XAML element.
if (!m_nativeLayout) {
return button;
}
auto yogaXamlPanel = winrt::make<winrt::PlaygroundApp::implementation::YogaXamlPanel>(
[&](winrt::Windows::Foundation::Size desiredSize) {
if (m_state) {
auto state = winrt::get_self<MyStateData>(m_state.Data());
if (desiredSize != state->desiredSize) {
m_state.UpdateStateWithMutation([desiredSize](winrt::Windows::Foundation::IInspectable data) {
auto oldData = winrt::get_self<MyStateData>(data);
return winrt::make<MyStateData>(desiredSize);
});
}
}
});
// yogaXamlPanel.Background(winrt::Microsoft::UI::Xaml::Media::SolidColorBrush({255, 124, 124, 155}));
yogaXamlPanel.VerticalAlignment(winrt::Microsoft::UI::Xaml::VerticalAlignment::Stretch);
yogaXamlPanel.HorizontalAlignment(winrt::Microsoft::UI::Xaml::HorizontalAlignment::Stretch);
yogaXamlPanel.Children().Append(button);
return yogaXamlPanel;
}
winrt::Microsoft::ReactNative::Composition::IVisual CreateVisual() noexcept {
m_xamlIsland = winrt::Microsoft::UI::Xaml::XamlIsland{};
m_xamlIsland.Content(CreateXamlButtonContent());
m_contentIsland = m_xamlIsland.ContentIsland();
m_visual = m_compContext.CreateSpriteVisual();
m_visual.Brush(m_compContext.CreateColorBrush(winrt::Windows::UI::Colors::White()));
// m_visual.Brush(m_compContext.CreateColorBrush({255, 255, 0, 255}));
auto parentSystemVisual =
winrt::Microsoft::ReactNative::Composition::WindowsCompositionContextHelper::InnerVisual(m_visual)
.as<winrt::Windows::UI::Composition::ContainerVisual>();
#ifdef USE_WINUI3
auto compositor =
winrt::Microsoft::ReactNative::Composition::MicrosoftCompositionContextHelper::InnerCompositor(m_compContext);
auto hwnd = reinterpret_cast<HWND>(
winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_reactContext.Properties()));
if (compositor) {
m_spotlight = compositor.CreateSpotLight();
m_spotlight.InnerConeAngleInDegrees(50.0f);
m_spotlight.InnerConeColor(winrt::Windows::UI::Colors::FloralWhite());
m_spotlight.InnerConeIntensity(5.0f);
m_spotlight.OuterConeAngleInDegrees(0.0f);
m_spotlight.ConstantAttenuation(1.0f);
m_spotlight.LinearAttenuation(0.253f);
m_spotlight.QuadraticAttenuation(0.58f);
m_spotlight.CoordinateSpace(
winrt::Microsoft::ReactNative::Composition::MicrosoftCompositionContextHelper::InnerVisual(m_visual));
m_spotlight.Targets().Add(
winrt::Microsoft::ReactNative::Composition::MicrosoftCompositionContextHelper::InnerVisual(m_visual));
m_siteBridge = winrt::Microsoft::UI::Content::SystemVisualSiteBridge::Create(
m_contentIsland.Compositor(), parentSystemVisual, winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd));
m_siteBridge.Connect(m_contentIsland);
auto implicitAnimations = compositor.CreateImplicitAnimationCollection();
implicitAnimations.Insert(L"Offset", CreateAnimation(compositor));
m_spotlight.ImplicitAnimations(implicitAnimations);
}
#endif
auto rootXamlVisualSize = m_contentIsland.Root().Size();
return m_visual;
}
#ifdef USE_WINUI3
winrt::Microsoft::UI::Composition::Vector3KeyFrameAnimation CreateAnimation(
winrt::Microsoft::UI::Composition::Compositor compositor) {
auto animation = compositor.CreateVector3KeyFrameAnimation();
animation.InsertExpressionKeyFrame(0.0f, L"this.StartingValue");
animation.InsertExpressionKeyFrame(
1.0f, L"this.FinalValue", compositor.CreateCubicBezierEasingFunction({.38f, .29f}, {.64f, 1.52f}));
animation.Target(L"Offset");
animation.Duration(std::chrono::milliseconds(250));
return animation;
}
#endif
void PointerMoved(const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
// Ideally we'd get the coords based on this view's tag, but that is NYI - so we'll just mod the coords to keep them
// in view for now
auto position = args.GetCurrentPoint(-1).Position();
#ifdef USE_WINUI3
m_spotlight.Offset(
{std::fmodf(
position.X * m_layoutMetrics.PointScaleFactor,
m_layoutMetrics.Frame.Width * m_layoutMetrics.PointScaleFactor),
std::fmodf(
position.Y * m_layoutMetrics.PointScaleFactor,
m_layoutMetrics.Frame.Height * m_layoutMetrics.PointScaleFactor),
std::fmodf((position.X + position.Y) / 40, 50) + 15.0f});
#endif
}
void PointerEntered(const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
m_visual.Brush(m_compContext.CreateColorBrush(winrt::Windows::UI::Colors::Red()));
}
void PointerExited(const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
m_visual.Brush(m_compContext.CreateColorBrush(winrt::Windows::UI::Colors::White()));
#ifdef USE_WINUI3
m_spotlight.Offset(
{m_layoutMetrics.Frame.Width / 2.0f * m_layoutMetrics.PointScaleFactor,
m_layoutMetrics.Frame.Height / 2 * m_layoutMetrics.PointScaleFactor,
75.0f});
#endif
void UpdateState(winrt::Microsoft::ReactNative::IComponentState state) noexcept {
m_state = state;
}
static void RegisterViewComponent(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) {
@ -131,35 +155,77 @@ struct CustomComponent : winrt::implements<CustomComponent, winrt::IInspectable>
compBuilder.SetCreateView(
[](winrt::Microsoft::ReactNative::IReactContext reactContext,
winrt::Microsoft::ReactNative::Composition::ICompositionContext context) noexcept {
return winrt::make<CustomComponent>(reactContext, context);
return winrt::make<CustomComponent>(true, reactContext, context);
});
compBuilder.SetPropsUpdater([](winrt::Windows::Foundation::IInspectable handle,
compBuilder.SetPropsUpdater([](winrt::Windows::Foundation::IInspectable componentHandle,
winrt::Microsoft::ReactNative::IComponentProps props) noexcept {
handle.as<CustomComponent>()->UpdateProps(props);
componentHandle.as<CustomComponent>()->UpdateProps(props);
});
compBuilder.SetLayoutMetricsUpdater(
[](winrt::Windows::Foundation::IInspectable handle,
[](winrt::Windows::Foundation::IInspectable componentHandle,
winrt::Microsoft::ReactNative::Composition::LayoutMetrics metrics) noexcept {
handle.as<CustomComponent>()->UpdateLayoutMetrics(metrics);
componentHandle.as<CustomComponent>()->UpdateLayoutMetrics(metrics);
});
compBuilder.SetVisualCreator([](winrt::Windows::Foundation::IInspectable handle) noexcept {
return handle.as<CustomComponent>()->CreateVisual();
compBuilder.SetVisualCreator([](winrt::Windows::Foundation::IInspectable componentHandle) noexcept {
return componentHandle.as<CustomComponent>()->CreateVisual();
});
compBuilder.SetPointerMovedHandler(
[](winrt::Windows::Foundation::IInspectable handle,
const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
return handle.as<CustomComponent>()->PointerMoved(args);
builder.SetStateUpdater([](winrt::Windows::Foundation::IInspectable componentHandle,
winrt::Microsoft::ReactNative::IComponentState state) noexcept {
return componentHandle.as<CustomComponent>()->UpdateState(state);
});
builder.SetMeasureContentHandler(
[](winrt::Microsoft::ReactNative::ShadowNode shadowNode,
winrt::Microsoft::ReactNative::LayoutContext layoutContext,
winrt::Microsoft::ReactNative::LayoutConstraints layoutContraints) noexcept {
shadowNode.Tag(winrt::box_value(layoutContraints));
auto currentState = winrt::get_self<MyStateData>(shadowNode.StateData());
if (currentState) {
// Snap up to the nearest whole pixel to avoid pixel snapping truncations
auto size = winrt::Windows::Foundation::Size{
std::ceil(currentState->desiredSize.Width * layoutContext.PointScaleFactor()) /
layoutContext.PointScaleFactor() +
1.0f,
std::ceil(currentState->desiredSize.Height * layoutContext.PointScaleFactor()) /
layoutContext.PointScaleFactor() +
1.0f,
};
return size;
}
return winrt::Windows::Foundation::Size{0, 0};
});
compBuilder.SetPointerEnteredHandler(
[](winrt::Windows::Foundation::IInspectable handle,
const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
return handle.as<CustomComponent>()->PointerEntered(args);
builder.SetInitialStateDataFactory([](const winrt::Microsoft::ReactNative::IComponentProps & /*props*/) {
return winrt::make<MyStateData>(winrt::Windows::Foundation::Size{0, 0});
});
});
packageBuilder.as<winrt::Microsoft::ReactNative::IReactPackageBuilderFabric>().AddViewComponent(
L"MyCustomComponentYoga",
[](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
builder.SetCreateProps(
[](winrt::Microsoft::ReactNative::ViewProps props) noexcept { return winrt::make<CustomProps>(props); });
auto compBuilder =
builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();
compBuilder.SetCreateView(
[](winrt::Microsoft::ReactNative::IReactContext reactContext,
winrt::Microsoft::ReactNative::Composition::ICompositionContext context) noexcept {
return winrt::make<CustomComponent>(false, reactContext, context);
});
compBuilder.SetPointerExitedHandler(
[](winrt::Windows::Foundation::IInspectable handle,
const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
return handle.as<CustomComponent>()->PointerExited(args);
compBuilder.SetPropsUpdater([](winrt::Windows::Foundation::IInspectable componentHandle,
winrt::Microsoft::ReactNative::IComponentProps props) noexcept {
componentHandle.as<CustomComponent>()->UpdateProps(props);
});
compBuilder.SetLayoutMetricsUpdater(
[](winrt::Windows::Foundation::IInspectable componentHandle,
winrt::Microsoft::ReactNative::Composition::LayoutMetrics metrics) noexcept {
componentHandle.as<CustomComponent>()->UpdateLayoutMetrics(metrics);
});
compBuilder.SetVisualCreator([](winrt::Windows::Foundation::IInspectable componentHandle) noexcept {
return componentHandle.as<CustomComponent>()->CreateVisual();
});
});
}
@ -168,9 +234,14 @@ struct CustomComponent : winrt::implements<CustomComponent, winrt::IInspectable>
winrt::Microsoft::UI::Composition::SpotLight m_spotlight{nullptr};
#endif
winrt::Microsoft::ReactNative::Composition::LayoutMetrics m_layoutMetrics;
bool m_nativeLayout;
winrt::Microsoft::ReactNative::IComponentState m_state;
winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr};
winrt::Microsoft::ReactNative::Composition::ICompositionContext m_compContext;
winrt::Microsoft::ReactNative::IReactContext m_reactContext;
winrt::Microsoft::UI::Xaml::XamlIsland m_xamlIsland{nullptr};
winrt::Microsoft::UI::Content::ContentIsland m_contentIsland{nullptr};
winrt::Microsoft::UI::Content::SystemVisualSiteBridge m_siteBridge{nullptr};
};
void RegisterCustomComponent(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept {

Просмотреть файл

@ -21,6 +21,7 @@
#include <winrt/Windows.UI.Composition.h>
#include <DesktopWindowBridge.h>
#include "App.xaml.h"
#include "NativeModules.h"
#include "ReactPropertyBag.h"
@ -152,7 +153,12 @@ struct WindowData {
std::wstring(L"file:").append(workingDir).append(L"\\Bundle\\").c_str());
host.InstanceSettings().UseDeveloperSupport(true);
host.PackageProviders().Append(winrt::make<CompReactPackageProvider>());
// Currently there is only SystemVisualSiteBridge which supports hosing ContentIslands within System
// Composition So our custom components do not run when running on lifted composition. This can be enabled in
// lifted once we have a VisualSiteBridge that works in lifted
if (!m_useLiftedComposition) {
host.PackageProviders().Append(winrt::make<CompReactPackageProvider>());
}
winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
host.InstanceSettings().Properties(), reinterpret_cast<uint64_t>(hwnd));
@ -163,80 +169,79 @@ struct WindowData {
viewOptions.ComponentName(appName);
auto windowData = WindowData::GetFromWindow(hwnd);
if (m_compRootView)
break;
if (!m_compRootView) {
if (windowData->m_useLiftedComposition) {
m_compRootView = winrt::Microsoft::ReactNative::CompositionRootView(g_liftedCompositor);
} else {
m_compRootView = winrt::Microsoft::ReactNative::CompositionRootView();
}
if (windowData->m_useLiftedComposition) {
m_compRootView = winrt::Microsoft::ReactNative::CompositionRootView(g_liftedCompositor);
} else {
m_compRootView = winrt::Microsoft::ReactNative::CompositionRootView();
if (windowData->m_useLiftedComposition) {
// By using the MicrosoftCompositionContextHelper here, React Native Windows will use Lifted Visuals for
// its tree.
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositionContext(
InstanceSettings().Properties(),
winrt::Microsoft::ReactNative::Composition::MicrosoftCompositionContextHelper::CreateContext(
g_liftedCompositor));
auto bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
g_liftedCompositor, winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd));
auto appContent = m_compRootView.Island();
auto invScale = 1.0f / ScaleFactor(hwnd);
m_compRootView.RootVisual().Scale({invScale, invScale, invScale});
/*
// Future versions of WinAppSDK will have more capabilities around scale and size
auto site = bridge.Site();
auto siteWindow = site.Environment();
auto displayScale = siteWindow.DisplayScale();
site.ParentScale(displayScale);
site.ActualSize({m_width / displayScale, m_height / displayScale});
site.ClientSize({m_width / displayScale, m_height / displayScale});
*/
bridge.Connect(appContent);
bridge.Show();
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
m_compRootView.Size({m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)});
bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
} else if (!m_target) {
// By using the WindowsCompositionContextHelper here, React Native Windows will use System Visuals for its
// tree.
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositionContext(
InstanceSettings().Properties(),
winrt::Microsoft::ReactNative::Composition::WindowsCompositionContextHelper::CreateContext(
g_compositor));
auto interop = g_compositor.as<ABI::Windows::UI::Composition::Desktop::ICompositorDesktopInterop>();
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr};
winrt::check_hresult(interop->CreateDesktopWindowTarget(
hwnd,
false,
reinterpret_cast<ABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget **>(
winrt::put_abi(target))));
m_target = target;
auto root = g_compositor.CreateContainerVisual();
root.RelativeSizeAdjustment({1.0f, 1.0f});
root.Offset({0, 0, 0});
m_target.Root(root);
m_compRootView.SetWindow(reinterpret_cast<uint64_t>(hwnd));
m_compRootView.RootVisual(
winrt::Microsoft::ReactNative::Composition::WindowsCompositionContextHelper::CreateVisual(root));
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
m_compRootView.Size({m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)});
}
}
m_compRootView.ReactViewHost(
winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions));
if (windowData->m_useLiftedComposition) {
// By using the MicrosoftCompositionContextHelper here, React Native Windows will use Lifted Visuals for its
// tree.
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositionContext(
InstanceSettings().Properties(),
winrt::Microsoft::ReactNative::Composition::MicrosoftCompositionContextHelper::CreateContext(
g_liftedCompositor));
auto bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
g_liftedCompositor, winrt::Microsoft::UI::GetWindowIdFromWindow(hwnd));
auto appContent = m_compRootView.Island();
auto invScale = 1.0f / ScaleFactor(hwnd);
m_compRootView.RootVisual().Scale({invScale, invScale, invScale});
/*
// Future versions of WinAppSDK will have more capabilities around scale and size
auto site = bridge.Site();
auto siteWindow = site.Environment();
auto displayScale = siteWindow.DisplayScale();
site.ParentScale(displayScale);
site.ActualSize({m_width / displayScale, m_height / displayScale});
site.ClientSize({m_width / displayScale, m_height / displayScale});
*/
bridge.Connect(appContent);
bridge.Show();
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
m_compRootView.Size({m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)});
bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
} else if (!m_target) {
// By using the WindowsCompositionContextHelper here, React Native Windows will use System Visuals for its
// tree.
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositionContext(
InstanceSettings().Properties(),
winrt::Microsoft::ReactNative::Composition::WindowsCompositionContextHelper::CreateContext(
g_compositor));
auto interop = g_compositor.as<ABI::Windows::UI::Composition::Desktop::ICompositorDesktopInterop>();
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr};
winrt::check_hresult(interop->CreateDesktopWindowTarget(
hwnd,
false,
reinterpret_cast<ABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget **>(
winrt::put_abi(target))));
m_target = target;
auto root = g_compositor.CreateContainerVisual();
root.RelativeSizeAdjustment({1.0f, 1.0f});
root.Offset({0, 0, 0});
m_target.Root(root);
m_compRootView.SetWindow(reinterpret_cast<uint64_t>(hwnd));
m_compRootView.RootVisual(
winrt::Microsoft::ReactNative::Composition::WindowsCompositionContextHelper::CreateVisual(root));
m_compRootView.ScaleFactor(ScaleFactor(hwnd));
m_compRootView.Size({m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)});
}
}
break;
@ -523,6 +528,9 @@ int RunPlayground(int showCmd, bool useWebDebugger) {
}
_Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR /* commandLine */, int showCmd) {
// Island-support: Call init_apartment to initialize COM and WinRT for the thread.
winrt::init_apartment(winrt::apartment_type::single_threaded);
WNDCLASSEXW wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
@ -558,6 +566,10 @@ _Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR
g_liftedDispatcherQueueController =
winrt::Microsoft::UI::Dispatching::DispatcherQueueController::CreateOnCurrentThread();
g_liftedCompositor = winrt::Microsoft::UI::Composition::Compositor();
// Island-support: Create our custom Xaml App object. This is needed to properly use the controls and metadata
// in Microsoft.ui.xaml.controls.dll.
auto playgroundApp{winrt::make<winrt::Playground::implementation::App>()};
#endif
return RunPlayground(showCmd, false);

Просмотреть файл

@ -102,6 +102,11 @@
<ClInclude Include="AutolinkedNativeModules.g.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="App.xaml.h">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="YogaXamlPanel.h" />
</ItemGroup>
<ItemGroup>
<Manifest Include="Application.manifest" />
@ -115,8 +120,26 @@
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<!-- Island-support: This generated file implements some activation factories -->
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="App.xaml.cpp">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="CustomComponent.cpp" />
<ClCompile Include="Playground-Composition.cpp" />
<ClCompile Include="YogaXamlPanel.cpp" />
</ItemGroup>
<ItemGroup>
<!-- Island-support: Needed to run Markup Compiler on App.xaml and make the generated files -->
<ApplicationDefinition Include="App.xaml" />
</ItemGroup>
<ItemGroup>
<Midl Include="App.idl">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="YogaXamlPanel.idl"/>
</ItemGroup>
<ItemGroup>
<Natvis Include="$(ReactNativeWindowsDir)Folly\Folly.natvis" />

Просмотреть файл

@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "YogaXamlPanel.h"
#include <winrt/Windows.Foundation.h>
// Needed for latest versions of C++/WinRT
#if __has_include("App.YogaXamlPanel.g.cpp")
#include "App.YogaXamlPanel.g.cpp"
#endif
namespace winrt {
using namespace Windows::UI;
using namespace xaml;
using namespace Windows::Foundation;
} // namespace winrt
namespace winrt::PlaygroundApp::implementation {
const winrt::Windows::UI::Xaml::Interop::TypeName yogaXamlPanelTypeName{
winrt::hstring{L"YogaXamlPanel"},
winrt::Windows::UI::Xaml::Interop::TypeKind::Metadata};
YogaXamlPanel::YogaXamlPanel(std::function<void(winrt::Windows::Foundation::Size size)> &&onMeasured)
: Super(), m_onMeasured(std::move(onMeasured)) {}
winrt::Size YogaXamlPanel::MeasureOverride(winrt::Windows::Foundation::Size availableSize) {
assert(Children().Size() == 1);
auto child = Children().GetAt(0);
child.Measure({std::numeric_limits<float>::max(), std::numeric_limits<float>::max()});
auto desiredSize = child.DesiredSize();
m_onMeasured({desiredSize.Width, desiredSize.Height});
child.Measure(availableSize);
auto desiredSize2 = child.DesiredSize();
return desiredSize2;
}
winrt::Size YogaXamlPanel::ArrangeOverride(winrt::Windows::Foundation::Size finalSize) {
assert(Children().Size() == 1);
auto child = Children().GetAt(0);
child.Arrange(winrt::Windows::Foundation::Rect{0, 0, finalSize.Width, finalSize.Height});
return finalSize;
}
} // namespace winrt::PlaygroundApp::implementation

Просмотреть файл

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#pragma once
#include "App.YogaXamlPanel.g.h"
#include <functional>
namespace winrt::PlaygroundApp::implementation {
//
// YogaXamlPanel is our custom Panel used to bridge yoga and xaml layouts in fabric
//
struct YogaXamlPanel : YogaXamlPanelT<YogaXamlPanel> {
using Super = YogaXamlPanelT<YogaXamlPanel>;
public:
// Constructors
YogaXamlPanel(std::function<void(winrt::Windows::Foundation::Size size)> &&onMeasured);
// Overrides
winrt::Windows::Foundation::Size MeasureOverride(winrt::Windows::Foundation::Size availableSize);
winrt::Windows::Foundation::Size ArrangeOverride(winrt::Windows::Foundation::Size finalSize);
private:
std::function<void(winrt::Windows::Foundation::Size size)> m_onMeasured;
};
} // namespace winrt::PlaygroundApp::implementation

Просмотреть файл

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#ifndef USE_WINUI3
#define XAML_NAMESPACE Windows.UI.Xaml
#else
#define XAML_NAMESPACE Microsoft.UI.Xaml
#endif
namespace PlaygroundApp
{
// Used to notify of layout changes to forward to yoga
[default_interface]
[webhosthidden]
runtimeclass YogaXamlPanel : XAML_NAMESPACE.Controls.Panel
{
}
}

Просмотреть файл

@ -28,11 +28,11 @@
},
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
},
"Microsoft.Build.Tasks.Git": {
@ -56,8 +56,8 @@
},
"Microsoft.Windows.SDK.BuildTools": {
"type": "Transitive",
"resolved": "10.0.22621.1",
"contentHash": "Sp1DkYvg7yxuhamwxv+qFC66KC3paKQpwK8Q1J6XuAh6nzXIInmsDcpJ3szr0XGud4ysXojqwTfGdW01gvZ/0g=="
"resolved": "10.0.22621.756",
"contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA=="
},
"common": {
"type": "Project"
@ -79,7 +79,7 @@
"Folly": "[1.0.0, )",
"Microsoft.JavaScript.Hermes": "[0.1.18, )",
"Microsoft.SourceLink.GitHub": "[1.1.1, )",
"Microsoft.WindowsAppSDK": "[1.4.230913002, )",
"Microsoft.WindowsAppSDK": "[1.5.231202003-experimental1, )",
"ReactCommon": "[1.0.0, )",
"boost": "[1.76.0, )"
}

Просмотреть файл

@ -6,7 +6,7 @@
#include <windows.h>
#pragma push_macro("GetCurrentTime")
// When WINAPI_FAMILY is DESKTOP_APP, windows.h creates a macro for GetCurrentTime, which conflicts with other headers
#undef GetCurrentTime
#include <unknwn.h>
@ -17,4 +17,3 @@
// #include <winrt/ReactNativePicker.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.h>
#pragma pop_macro("GetCurrentTime")

Просмотреть файл

@ -32,11 +32,11 @@
},
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
},
"Microsoft.Build.Tasks.Git": {
@ -51,8 +51,8 @@
},
"Microsoft.Windows.SDK.BuildTools": {
"type": "Transitive",
"resolved": "10.0.22621.1",
"contentHash": "Sp1DkYvg7yxuhamwxv+qFC66KC3paKQpwK8Q1J6XuAh6nzXIInmsDcpJ3szr0XGud4ysXojqwTfGdW01gvZ/0g=="
"resolved": "10.0.22621.756",
"contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA=="
},
"common": {
"type": "Project"
@ -78,77 +78,77 @@
"native,Version=v0.0/win10-arm": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-arm-aot": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-arm64-aot": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x64": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x64-aot": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x86": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x86-aot": {
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.4.230913002, )",
"resolved": "1.4.230913002",
"contentHash": "l+9RshN4TsTuxL0ijFp5smbs3Y07RO7CxKBHNM/RsrsGtWvuk6edITMp4oqL9C3ufEAmpYk3dqOZRSf+sFH4Zg==",
"requested": "[1.5.231202003-experimental1, )",
"resolved": "1.5.231202003-experimental1",
"contentHash": "LAwPjWf2OfJx8NRz6bknPu71Tw85nfr/PkVWgl8Hl2T9uLjk+Ajs4ppQd6+27+M6ILaO5rOSbcv+hCtOo+VAYQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
}

Просмотреть файл

@ -12,6 +12,8 @@
See https://microsoft.github.io/react-native-windows/docs/win10-compat
-->
<PropertyGroup Label="Globals" Condition="'$(MSBuildProjectExtension)' == '.vcxproj'">
<WindowsTargetPlatformVersion Condition="'$(UseWinUI3)'=='true' And ('$(WindowsTargetPlatformVersion)'=='' Or '$(WindowsTargetPlatformVersion)'=='10.0.0.0')">10.0.22000.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)'=='' Or '$(WindowsTargetPlatformVersion)'=='10.0.0.0'">10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion Condition="'$(WindowsTargetPlatformMinVersion)'=='' Or '$(WindowsTargetPlatformMinVersion)'=='10.0.0.0'">10.0.17763.0</WindowsTargetPlatformMinVersion>

Просмотреть файл

@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="WinUI3 versioning">
<!--
Internal versions are located at: https://microsoft.visualstudio.com/DefaultCollection/ProjectReunion/_artifacts/feed/Project.Reunion.nuget.internal/NuGet/Microsoft.WindowsAppSDK/versions
For local testing of internal versions, modify the WinUI3Version, and comment out the addition nuget source in NuGet.Config
-->
<!-- This value is also used by the CLI, see /packages/@react-native-windows/generate-windows -->
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.4.230913002</WinUI3Version>
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.5.231202003-experimental1</WinUI3Version>
</PropertyGroup>
<PropertyGroup Label="WinUI2x versioning">