Skip to content

Commit 430c74b

Browse files
stevewhimsbgursahaniMike Battistamcleanbyronandrewleader
authored
PR to master from uwp-migration... (#1990)
* test test * Update toc.yml * Update toc.yml * Update benefits.md * test * Fixed a typo. * Update dwritecore.md * Update dwritecore.md * Create PhotoLabConversion.zip * first draft of cppwinrt case study (#1826) * first draft of cppwinrt case study * fixing suggestions * Update case-study-1.md * some edits to the case studies (#1840) * some edits to the case studies * couple more tweaks * adding alternative folder names (#1850) * move files into new folders (#1852) * updating TOC (#1853) * some review changes (#1854) * some refactoring (#1856) * some refactoring * more updates * just fixing TOC (#1857) * more refactoring (#1861) * more refactoring and new items (#1864) * adding more content (#1868) * Stwhi uwp migration/adding items 4 (#1871) * cppwinrt-only section * more items * more items/updates, and port -> migrate (#1874) * more items/updates, and port -> migrate * correcting build issues * correcting build issues 2 * correcting build issues 3 * correcting build issues 4 * last updates for the week (#1877) * more edits, additions, etc. (#1884) * more edits, additions, etc. * fixing url * more items (#1889) * UWP migration updates (aleader) (#1890) * A few fixups * Added some feature table mappings * More content * Merge * Update what-is-supported.md * another item (#1892) * another round of updates (#1893) * renaming Migration guide titles (#1894) * more items (#1895) * more items * fixing build suggestions * fixing build suggestion * more items (#1896) * last of the new items for the time being (#1900) * last of the new items for the time being * fixing build issues * experimenting with anchors * fixing build issue * Add * Create uwp-migration-msal-graph.md * Update feature-mapping-table.md * Minor UWP migration updates (#1904) * Updates to what is supported * Update what-is-supported.md * Update what-is-supported.md * Update api-mapping-table.md * Update overall-migration-strategy.md * Update case-study-1.md * Update * Update case-study-1.md * Update case-study-1.md * Update case-study-1.md * Update case-study-1.md * Acrylic brush item (#1919) * first half of copy-editing (#1924) * Update mrtcore.md * Update feature-mapping-table.md * Stwhi uwp migration/adding items 17 (#1927) * edit passes, improvements, etc. * build issues * copy-editing and rewriting (#1935) * Update feature-mapping-table.md * Adding warning for D2D support * Adding brief sentence for DWriteCore value prop * Update uwp-migration-msal-graph.md * Add and Edit Adding notifcations.md and changes to applifecycle.md * actioning feedback (#1952) * copy-editing (#1957) * copy-editing * assigning topics to myself * more updates as per email (#1959) * more entries to the API mapping table (#1964) * more entries to the API mapping table * build warnings * index (#1965) * Update case-study-1.md * Adding line for Win2D to feature mapping table * Add TaskbarManager to unsupported APIs * Fix absolute link * Update overall-migration-strategy.md * windowing guide (#1976) * windowing topic complete for now (#1978) * working around table rendering issues (#1979) * removed retry value. Added HTTP post example (#1980) * removed retry value. Added HTTP post example * fixed wording on retries * updating API mappings (#1982) * updating API mappings * fixing table * Delete uwp-migration-msal-graph.md Co-authored-by: Bhavya Gursahani <[email protected]> Co-authored-by: Mike Battista <[email protected]> Co-authored-by: Bhavya Gursahani <[email protected]> Co-authored-by: McLean Schofield <[email protected]> Co-authored-by: Andrew Leader <[email protected]> Co-authored-by: AdamBrMSFT <[email protected]> Co-authored-by: Duncan MacMichael <[email protected]> Co-authored-by: Nicu Parente <[email protected]>
1 parent cb8bbd0 commit 430c74b

17 files changed

+2273
-0
lines changed

hub/apps/toc.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,42 @@
8989
href: windows-app-sdk/notifications/push/push-quickstart.md
9090
- name: "Troubleshooting"
9191
href: windows-app-sdk/notifications/push/troubleshooting.md
92+
- name: Migrate to the Windows App SDK
93+
items:
94+
- name: "Index of migration topics"
95+
href: windows-app-sdk/migrate-to-windows-app-sdk/migrate-to-windows-app-sdk-ovw.md
96+
- name: "Overall migration strategy"
97+
href: windows-app-sdk/migrate-to-windows-app-sdk/overall-migration-strategy.md
98+
- name: "Mapping UWP features to Windows App SDK"
99+
href: windows-app-sdk/migrate-to-windows-app-sdk/feature-mapping-table.md
100+
- name: "What's supported"
101+
href: windows-app-sdk/migrate-to-windows-app-sdk/what-is-supported.md
102+
- name: "Mapping UWP APIs to Windows App SDK"
103+
href: windows-app-sdk/migrate-to-windows-app-sdk/api-mapping-table.md
104+
- name: "Feature area guides"
105+
items:
106+
- name: "Overview of feature area guides"
107+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/feature-area-guides-ovw.md
108+
- name: "Windows UI Library (WinUI) migration"
109+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/winui3.md
110+
- name: "Windowing functionality migration"
111+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/windowing.md
112+
- name: "Application lifecycle functionality migration"
113+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/applifecycle.md
114+
- name: "Notifications migration"
115+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/notifications.md
116+
- name: "DirectWrite to DWriteCore migration"
117+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/dwritecore.md
118+
- name: "MRT to MRTCore migration"
119+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/mrtcore.md
120+
- name: "Threading functionality migration"
121+
href: windows-app-sdk/migrate-to-windows-app-sdk/guides/threading.md
122+
- name: "Case study 1—PhotoLab (C#)"
123+
href: windows-app-sdk/migrate-to-windows-app-sdk/case-study-1.md
124+
- name: "Case study 2—Photo Editor (C++/WinRT)"
125+
href: windows-app-sdk/migrate-to-windows-app-sdk/case-study-2.md
126+
- name: "Additional migration guidance"
127+
href: windows-app-sdk/migrate-to-windows-app-sdk/misc-info.md
92128
- name: Windows UI Library (WinUI)
93129
items:
94130
- name: "Overview"

hub/apps/windows-app-sdk/migrate-to-windows-app-sdk/api-mapping-table.md

Lines changed: 106 additions & 0 deletions
Large diffs are not rendered by default.

hub/apps/windows-app-sdk/migrate-to-windows-app-sdk/case-study-1.md

Lines changed: 312 additions & 0 deletions
Large diffs are not rendered by default.

hub/apps/windows-app-sdk/migrate-to-windows-app-sdk/case-study-2.md

Lines changed: 343 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: Mapping UWP features to the Windows App SDK
3+
description: This topic compares major feature areas in the different forms in which they appear in UWP and in the Windows App SDK.
4+
ms.topic: article
5+
ms.date: 10/01/2021
6+
keywords: Windows, App, SDK, migrate, migrating, migration, port, porting, mapping, mappings, uwp
7+
ms.author: stwhi
8+
author: stevewhims
9+
ms.localizationpriority: medium
10+
---
11+
12+
# Mapping UWP features to the Windows App SDK
13+
14+
This topic compares major feature areas in the different forms in which they appear in UWP and in the Windows App SDK. The content in this migration guide supports moving from UWP XAML to Windows App SDK XAML&mdash;moving to a different UI framework, such as Windows Presentation Foundation (WPF), is outside of the scope of this guidance.
15+
16+
| Feature | UWP | Windows App SDK (packaged apps) | Migration notes |
17+
| - | - | - | - |
18+
| Packaging | MSIX<br/>App has identity | MSIX<br/>App has identity | UWP apps migrating to the Windows App SDK should stay on MSIX to ensure trusted clean install and uninstall experience, as well as access to all APIs, including those that require identity. |
19+
| Container | App container:<br/>- security = LowIL<br/>- file system access is brokered<br/>- no registry access | MSIX Container:<br/>- security = MediumIL<br/>- file system access same as user, AppData writes virtualized<br/>- HKCU registry writes virtualized | Moving to a higher integrity level with the Windows App SDK allows your app to have greater functionality. However, be aware of virtualization if you want to expand the capabilities of your migrated application to write to HKCU or AppData. |
20+
| Activation and instancing | Package identity + CoreApplication activation, single-instanced by default | Package identity, Main/WinMain + Windows App SDK activation, multi-instanced by default | Ensure your application can handle multi-instance behavior, or use [**AppInstance**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance) to manage your instances. |
21+
| Lifecycle-managed | Suspend/resume | Power/State notifications | You can use Power/State change notifications to reduce system load. |
22+
| Background tasks | InProc and OOP background tasks | Inproc COM and OOP background tasks | You can continue to use your OOP background tasks. If the app requires communication to your main process, then evaluate your IPC mechanism, as the OOP background task is running in LowIL, and your Windows App SDK main process is running in MediumIL.<br/>Any inproc background tasks need to be migrated to COM background tasks&mdash;see [Create and register a winmain COM background task](/windows/uwp/launch-resume/create-and-register-a-winmain-background-task). |
23+
| Windowing | CoreWindow, AppWindow (preview) | HWND, AppWindow v2 | Windowing behavior has significantly changed in Windows App SDK. See [Windowing functionality migration](guides/windowing.md). |
24+
| Messaging | CoreDispatcher and DispatcherQueue | DispatcherQueue, WndProc | [**DispatcherQueue**](/windows/winui/api/microsoft.ui.dispatching.dispatcherqueue) supports Win32 apps. For additional details on moving from CoreDispatcher to DispatcherQueue see [Threading functionality migration](guides/threading.md). |
25+
| UI Platform| System XAML, WebView, DirectX, and others | WinUI 3, Webview2, DirectX, and others | For more info, see [Windows UI Library (WinUI) migration](guides/winui3.md). |
26+
| Text-rendering | DirectWrite | DWriteCore | Enables applications to access the latest DWrite features downlevel and receive new DWrite updates separate from the OS release schedule. For more info, see [DirectWrite to DWriteCore migration](guides/dwritecore.md). |
27+
| Resources | MRT | MRTCore | For more info, see [MRT to MRTCore migration](guides/mrtcore.md). |
28+
| .NET Runtime | .NET Native / C# 7 | .NET 5+/C# 9 | The Windows App SDK provides access to the modern .NET runtime, and access to new langage features. However, .NET 5 [ReadyToRun compilation](/dotnet/core/deploying/ready-to-run) is not the same as .NET Native, so you should evaluate performance tradeoffs. |
29+
| 2D Graphics | Win2D | Win2D for WinUI 3 | We're currently working on a version of Win2D that works with the Windows App SDK, in progress. See the [documentation](http://microsoft.github.io/Win2D/WinUI3/html/Introduction.htm) for more information. |
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: Application lifecycle functionality migration
3+
description: This topic contains migration guidance in the application lifecycle area.
4+
ms.topic: article
5+
ms.date: 09/20/2021
6+
keywords: Windows, App, SDK, migrate, migrating, migration, port, porting, application lifecycle, applifecycle, application, lifecycle
7+
ms.author: stwhi
8+
author: stevewhims
9+
ms.localizationpriority: medium
10+
dev_langs:
11+
- csharp
12+
- cppwinrt
13+
---
14+
15+
# Application lifecycle functionality migration
16+
17+
This topic contains migration guidance in the application lifecycle area.
18+
19+
## Important APIs
20+
21+
* [**AppInstance**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance) class
22+
* [**Application.OnLaunched**](/windows/winui/api/microsoft.ui.xaml.application.onlaunched) method
23+
* [**AppInstance.GetActivatedEventArgs**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.getactivatedeventargs) method
24+
* [**ExtendedActivationKind**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.extendedactivationkind) enum
25+
26+
## Single-instanced apps
27+
28+
Universal Windows Platform (UWP) apps are single-instanced by default (you can opt in to support multiple instances&mdash;see [Create a multi-instance UWP app](/windows/uwp/launch-resume/multi-instance-uwp)).
29+
30+
So the way a single-instanced UWP app behaves is that the second (and subsequent) time you launch, your current instance is activated. Let's say for example that in your UWP app you've implemented the file type association feature. If from File Explorer you open a file (of the type for which the app has registered a file type association)&mdash;and your app is already running&mdash;then that already-running instance is activated.
31+
32+
Windows App SDK (WinUI 3) apps, on the other hand, are multi-instanced by default. So, by default, the second (and subsequent) time you launch a Windows App SDK (WinUI 3) app, a new instance of the app is launched. If for example a Windows App SDK (WinUI 3) app implements file type association, and from File Explorer you open a file (of the right type) while that app is already running, then by default a new instance of the app is launched.
33+
34+
If you want your Windows App SDK (WinUI 3) app to be single-instanced like your UWP app is, then you can override the default behavior described above. You can do that in the [**Application.OnLaunched**](/windows/winui/api/microsoft.ui.xaml.application.onlaunched) method of your **App** class.
35+
36+
> [!NOTE]
37+
> Adding the code shown below to **Application.OnLaunched** can simplify your app. However, a lot depends on what else your app is doing. If you're going to end up redirecting, and then terminating the current instance, then you'll want to avoid doing any throwaway work (or even work that needs explicitly undoing). In cases like that, **Application.OnLaunched** might be too late, and you might prefer to do the work in your app's **main** function (or equivalent).
38+
39+
In **OnLaunched**, use [**AppInstance.FindOrRegisterForKey**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.findorregisterforkey) and [**AppInstance.IsCurrent**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.iscurrent) to determine whether the current instance is the main instance. If it isn't, then call [**AppInstance.RedirectActivationToAsync**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.redirectactivationtoasync) to redirect activation to the already-running main instance, and then exit from the current instance (without creating nor activating its main window).
40+
41+
For more info, see [App instancing in AppLifecycle](/windows/apps/windows-app-sdk/applifecycle/applifecycle-instancing).
42+
43+
```csharp
44+
// App.xaml.cs in a Windows App SDK (WinUI 3) app
45+
...
46+
protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
47+
{
48+
// If this is the first instance launched, then register it as the "main" instance.
49+
// If this isn't the first instance launched, then "main" will already be registered,
50+
// so retrieve it.
51+
var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("main");
52+
53+
// If the instance that's executing the OnLaunched handler right now
54+
// isn't the "main" instance.
55+
if (!mainInstance.IsCurrent)
56+
{
57+
// Redirect the activation (and args) to the "main" instance, and exit.
58+
var activatedEventArgs =
59+
Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
60+
await mainInstance.RedirectActivationToAsync(activatedEventArgs);
61+
System.Diagnostics.Process.GetCurrentProcess().Kill();
62+
return;
63+
}
64+
65+
m_window = new MainWindow();
66+
m_window.Activate();
67+
}
68+
```
69+
70+
```cppwinrt
71+
// pch.h in a Windows App SDK (WinUI 3) app
72+
...
73+
#include <winrt/Microsoft.Windows.AppLifecycle.h>
74+
...
75+
76+
// App.xaml.h
77+
...
78+
struct App : AppT<App>
79+
{
80+
...
81+
winrt::fire_and_forget OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);
82+
...
83+
}
84+
85+
// App.xaml.cpp
86+
...
87+
using namespace winrt;
88+
using namespace Microsoft::Windows::AppLifecycle;
89+
...
90+
winrt::fire_and_forget App::OnLaunched(LaunchActivatedEventArgs const&)
91+
{
92+
// If this is the first instance launched, then register it as the "main" instance.
93+
// If this isn't the first instance launched, then "main" will already be registered,
94+
// so retrieve it.
95+
auto mainInstance{ AppInstance::FindOrRegisterForKey(L"main") };
96+
97+
// If the instance that's executing the OnLaunched handler right now
98+
// isn't the "main" instance.
99+
if (!mainInstance.IsCurrent())
100+
{
101+
// Redirect the activation (and args) to the "main" instance, and exit.
102+
auto activatedEventArgs{ AppInstance::GetCurrent().GetActivatedEventArgs() };
103+
co_await mainInstance.RedirectActivationToAsync(activatedEventArgs);
104+
::ExitProcess(0);
105+
co_return;
106+
}
107+
108+
window = make<MainWindow>();
109+
window.Activate();
110+
}
111+
```
112+
113+
Alternatively, you can call [**AppInstance.GetInstances**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.getinstances) to retrieve a collection of running [**AppInstance**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance) objects. If the number of elements in that collection is greater than 1, then your main instance is already running, and you should redirect to that.
114+
115+
## File type association
116+
117+
In a Windows App SDK project, to specify the extension point for a file type association, you make the same settings in your `Package.appxmanifest` file as you would for a UWP project. Here are those settings.
118+
119+
Open `Package.appxmanifest`. In **Declarations**, choose **File Type Associations**, and click **Add**. Set the following properties.
120+
121+
**Display name**: MyFile
122+
**Name**: myfile
123+
**File type**: .myf
124+
125+
To register the file type association, build the app, launch it, and close it.
126+
127+
The difference comes in the imperative code. In a UWP app, you implement **App::OnFileActivated** in order to handle file activation. But in a Windows App SDK app, you write code in **App::OnLaunched** to check the extended activation kind ([**ExtendedActivationKind**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.extendedactivationkind)) of the activated event args ([**AppInstance.GetActivatedEventArgs**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.getactivatedeventargs)), and see whether the activation is a file activation.
128+
129+
> [!NOTE]
130+
> Don't use the [**Microsoft.UI.Xaml.LaunchActivatedEventArgs**](/windows/winui/api/microsoft.ui.xaml.launchactivatedeventargs) object passed to **App::OnLaunched** to determine the activation kind, because it reports "Launch" unconditionally.
131+
132+
If your app has navigation, then you'll already have navigation code in **App::OnLaunched**, and you might want to re-use that logic. For more info, see [Do I need to implement page navigation?](winui3.md#do-i-need-to-implement-page-navigation).
133+
134+
```csharp
135+
// App.xaml.cs in a Windows App SDK app
136+
...
137+
using Microsoft.Windows.AppLifecycle;
138+
...
139+
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
140+
{
141+
var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
142+
if (activatedEventArgs.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.File)
143+
{
144+
...
145+
}
146+
...
147+
}
148+
```
149+
150+
```cppwinrt
151+
// pch.h in a Windows App SDK app
152+
...
153+
#include <winrt/Microsoft.Windows.AppLifecycle.h>
154+
155+
// App.xaml.cpp
156+
...
157+
using namespace Microsoft::Windows::AppLifecycle;
158+
...
159+
void App::OnLaunched(LaunchActivatedEventArgs const&)
160+
{
161+
auto activatedEventArgs{ AppInstance::GetCurrent().GetActivatedEventArgs() };
162+
if (activatedEventArgs.Kind() == ExtendedActivationKind::File)
163+
{
164+
...
165+
}
166+
...
167+
}
168+
```
169+
170+
## OnActivated, OnBackgroundActivated, and other activation-handling methods
171+
172+
In a UWP app, to override the various means by which your app can be activated, you can override corresponding methods on your **App** class, such as **OnFileActivated**, **OnSearchActivated**, or the more general **OnActivated**.
173+
174+
In a Windows App SDK app, in **App.OnLaunched** (or in fact at any time) you can call ([**AppInstance.GetActivatedEventArgs**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.appinstance.getactivatedeventargs)) to retrieve the activated event args, and check them to determine how the app was activated.
175+
176+
See the [File type association](#file-type-association) section above for more details and a code example. You can apply the same technique for any activation kind specified by the [**ExtendedActivationKind**](/windows/windows-app-sdk/api/winrt/microsoft.windows.applifecycle.extendedactivationkind) enum.
177+
178+
## Related topics
179+
180+
* [App instancing in AppLifecycle](/windows/apps/windows-app-sdk/applifecycle/applifecycle-instancing)
181+
* [Do I need to implement page navigation?](winui3.md#do-i-need-to-implement-page-navigation)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: DirectWrite to DWriteCore migration
3+
description: DWriteCore is the [Windows App SDK](/windows/apps/windows-app-sdk/) implementation of [DirectWrite](/windows/win32/directwrite/direct-write-portal).
4+
ms.topic: article
5+
ms.date: 09/16/2021
6+
keywords: Windows, App, SDK, migrate, migrating, migration, port, porting, DirectWrite, DWriteCore
7+
ms.author: stwhi
8+
author: stevewhims
9+
ms.localizationpriority: medium
10+
---
11+
12+
# DirectWrite to DWriteCore migration
13+
14+
DWriteCore is the [Windows App SDK](/windows/apps/windows-app-sdk/) implementation of [DirectWrite](/windows/win32/directwrite/direct-write-portal). For more info, see [DWriteCore overview](/windows/win32/directwrite/dwritecore-overview).
15+
16+
## API differences between DirectWrite and DWriteCore
17+
18+
Nearly all DirectWrite APIs remain unchanged in DWriteCore. There are a few differences, as described in [APIs that are new, or different, for DWriteCore](/windows/win32/directwrite/dwritecore-overview#apis-that-are-new-or-different-for-dwritecore).
19+
20+
As you'll see in that topic, DWriteCore has a more locked-down factory type, and has the ability to retrieve pixel data without using GDI.
21+
22+
## Migration guidance
23+
24+
The only change necessary when moving from DirectWrite to DWriteCore is to include the `dwrite_core.h` header file. For more info, and code examples, see [Programming with DWriteCore](/windows/win32/directwrite/dwritecore-overview#programming-with-dwritecore).
25+
26+
>[!WARNING]
27+
> DWriteCore does not currently support hardware-accelerated text rendering with Direct2D (D2D). It supports software text rendering only. This prevents apps that require D2D support from adopting DWriteCore at this time.
28+
29+
## The DWriteCoreGallery sample app
30+
31+
Also see the [DWriteCoreGallery](https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/TextRendering) sample app project, which demonstrates the DWriteCore API surface.
32+
33+
## Related topics
34+
35+
* [DWriteCore overview](/windows/win32/directwrite/dwritecore-overview)
36+
* [DWriteCoreGallery](https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/TextRendering) sample app
37+
* [DirectWrite](/windows/win32/directwrite/direct-write-portal)
38+
* [Windows App SDK](/windows/apps/windows-app-sdk/)

0 commit comments

Comments
 (0)