[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:
Родитель
1b06c4a6ac
Коммит
1e8b8a0d0f
|
@ -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">
|
||||
|
|
Загрузка…
Ссылка в новой задаче