diff --git a/content/best-practices/platform-file-split-or-not.md b/content/best-practices/platform-file-split-or-not.md index 658d0ea4..dd43a47d 100644 --- a/content/best-practices/platform-file-split-or-not.md +++ b/content/best-practices/platform-file-split-or-not.md @@ -23,12 +23,13 @@ Using platform files: - `file.ios.ts` - `file.android.ts` +- `file.windows.ts` (when targeting [Windows](/guide/windows/)) The advent of tree shaking and webpack builds does away with quite a bit of worry in this area however there's a few things to consider here. ## Conditional with tree shaking -When speaking of tree shaking ever since NativeScript 7, you've been able to use `__ANDROID__` or `global.isIOS` and anytime those are used as conditional splits in your code, only the applicable code for the platform that's being built would actually end up in your compiled code alleviating a lot of concern here. +When speaking of tree shaking ever since NativeScript 7, you've been able to use `__ANDROID__`, `__WINDOWS__` or `global.isIOS` and anytime those are used as conditional splits in your code, only the applicable code for the platform that's being built would actually end up in your compiled code alleviating a lot of concern here. ## Future maintenance diff --git a/content/configuration/nativescript.md b/content/configuration/nativescript.md index d874585c..750381bd 100644 --- a/content/configuration/nativescript.md +++ b/content/configuration/nativescript.md @@ -37,7 +37,7 @@ export default { id: string = 'com.mycompany.myapp' ``` -Controls the Application ID of your app, this setting can be overridden per platform via [ios.id](#ios-id) and [android.id](#android-id). +Controls the Application ID of your app, this setting can be overridden per platform via [ios.id](#ios-id), [android.id](#android-id) and [windows.id](#windows-id). ### main @@ -163,6 +163,14 @@ ios: Object = {} See [iOS Configuration Reference](#ios-configuration-reference) +### windows + +```ts +windows: Object = {} +``` + +See [Windows Configuration Reference](#windows-configuration-reference) + ### hooks ```ts @@ -508,6 +516,48 @@ ios: { } ``` +## Windows Configuration Reference + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +### windows.id + +```ts +windows.id: string = 'com.mycompany.myapp'; +``` + +Controls the package identity name of your Windows app, this setting overrides the value set in [id](#id). The value is written to the `Name` attribute of the `` element in the generated `Package.appxmanifest`, and the CLI uses it to find, install and remove the app package. + +### windows.sourceProtect + +```ts +windows.sourceProtect: boolean = true; +``` + +When enabled, **release** builds seal the bundled JavaScript into an encrypted `app.nsbundle` instead of shipping it as plain `.js` files. Defaults to `false`. + +This can be overridden per build with `--source-protect` or `--no-source-protect`. The encryption key can be provided with `--source-protect-key-hex ` or the `NS_WINDOWS_BUNDLE_KEY` environment variable. + +```ts +export default { + // ... + windows: { + sourceProtect: true, + }, +} as NativeScriptConfig +``` + +### windows.phoneProductId / windows.phonePublisherId + +```ts +windows.phoneProductId: string = '00000000-0000-0000-0000-000000000000'; +windows.phonePublisherId: string = '00000000-0000-0000-0000-000000000000'; +``` + +Values written to the `mp:PhoneIdentity` element of the generated `Package.appxmanifest`. When `phoneProductId` isn't set (or is empty/all zeros), the CLI generates a stable GUID derived from the app id. Can be overridden with `--phone-product-id` and `--phone-publisher-id`. + ## Hooks Configuration Reference ```ts diff --git a/content/configuration/vite.md b/content/configuration/vite.md index 215be7ae..5bf9cf87 100644 --- a/content/configuration/vite.md +++ b/content/configuration/vite.md @@ -360,7 +360,8 @@ Additional env flags that are passed by the CLI automatically - `--env.android` - `true` when running on Android - `--env.ios` - `true` when running on iOS - `--env.visionos` - `true` when running on visionOS -- `--env.platform=` - for specifying the platform to use. Can be `android`, `ios`, or `visionos`. +- `--env.windows` - `true` when running on Windows +- `--env.platform=` - for specifying the platform to use. Can be `android`, `ios`, `visionos`, or `windows`. - `--env.hmr` - `true` when building with HMR enabled ## Global "magic" variables @@ -397,6 +398,12 @@ We define a few useful globally available variables that you can use to alter lo // we are running on an Apple platform } ``` +- `__WINDOWS__`, `true` when the platform is Windows + ```ts + if (__WINDOWS__) { + // we are running on Windows + } + ``` ::: details The following variables are also defined, but are primarily intended to be used by NativeScript Core internally, or plugins that wish to use these. diff --git a/content/configuration/webpack.md b/content/configuration/webpack.md index d9e79aa1..7ab578ec 100644 --- a/content/configuration/webpack.md +++ b/content/configuration/webpack.md @@ -96,7 +96,9 @@ Additional env flags that are usually passed by the CLI automatically - `--env.nativescriptLibPath` - path to the currently running CLI's library. - `--env.android` - `true` when running on android - `--env.ios` - `true` when running on ios -- `--env.platform=` - for specifying the platform to use. Can be `android` or `ios`, or a custom platform in the future. +- `--env.visionos` - `true` when running on visionOS +- `--env.windows` - `true` when running on Windows +- `--env.platform=` - for specifying the platform to use. Can be `android`, `ios`, `visionos`, `windows`, or a custom platform. - `--env.hmr` - `true` when building with HMR enabled ## Global "magic" variables @@ -121,6 +123,12 @@ We define a few useful globally available variables that you can use to alter lo // we are running on iOS } ``` +- `__WINDOWS__` (also available as `global.isWindows`) - `true` when the platform is Windows + ```ts + if (__WINDOWS__) { + // we are running on Windows + } + ``` ::: details The following variables are also defined, but are primarily intended to be used by NativeScript Core internally, or plugins that wish to use these. diff --git a/content/guide/adding-native-code.md b/content/guide/adding-native-code.md index 3b574e0c..b8ebb299 100644 --- a/content/guide/adding-native-code.md +++ b/content/guide/adding-native-code.md @@ -30,6 +30,7 @@ ns native add java com.company.OtherAwesomeClass 1. You can also manually add native code to [App_Resources](/project-structure/app-resources): - [Adding Java/Kotlin code to an application](/guide/native-code/android) - [Adding ObjectiveC/Swift Code to an application](/guide/native-code/ios) + - [Adding Windows native code (C#, C++/WinRT, Win32) to an application](/guide/native-code/windows) 2. Optionally [generate TypeScript types for the added APIs](/guide/native-code/generate-typings) Additionally, NativeScript also supports Jetpack Compose and SwiftUI through plugins. diff --git a/content/guide/cli-basics.md b/content/guide/cli-basics.md index a271bba2..f86647ff 100644 --- a/content/guide/cli-basics.md +++ b/content/guide/cli-basics.md @@ -57,6 +57,8 @@ Example output: | 3 | iPhone 14 Pro | iOS | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX | Emulator | Connected | Local | ``` +On a Windows host, the local machine is also listed as a `Windows` device, which is the target used by `ns run windows` (see [Developing for Windows](/guide/windows/)). + ## Setting the default package manager To set the default package manager that the CLI uses (unless overridden in [nativescript.config.ts](/project-structure/nativescript-config#cli-packagemanager)): diff --git a/content/guide/debugging.md b/content/guide/debugging.md index 666825f4..bc97abed 100644 --- a/content/guide/debugging.md +++ b/content/guide/debugging.md @@ -5,7 +5,7 @@ contributors: - rigor789 --- -There are multiple ways to debug issues in your apps, starting with the simplest form using `console.logs`. For more complex issues, you may need to use an actual debugger, like Chrome DevTools, XCode developer tools and instruments or the Android Studio developer tools. +There are multiple ways to debug issues in your apps, starting with the simplest form using `console.logs`. For more complex issues, you may need to use an actual debugger, like Chrome DevTools, XCode developer tools and instruments, the Android Studio developer tools or Visual Studio on Windows. ## Console @@ -41,7 +41,7 @@ console.timeEnd('myLabel') To start a Chrome debugging session, run your app in debug mode: ```bash -ns debug android|ios +ns debug android|ios|windows ``` The `ns debug` command builds and deploys the app on a connected device or emulator, in case you have multiple devices available you will need to pick one from a list, or pass in the `--device ` from `ns devices`. @@ -163,3 +163,62 @@ Since NativeScript follows a standard gradle/android application structure, you - [Android Studio: Layout Inspector](https://developer.android.com/studio/debug/layout-inspector) - [Android Studio: view Logcat logs](https://developer.android.com/studio/debug/am-logcat) - [Androud Studio: Debug your app](https://developer.android.com/studio/debug#startdebug) + +## Debugging on Windows + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +### Chrome DevTools + +Start a debug session on the local machine with: + +```bash +ns debug windows +``` + +The command builds, deploys and launches the app with the V8 inspector enabled. Once the inspector is listening, a URL is printed to the console: + +```bash +# NativeScript Debugger started # +To start debugging, open the following URL in Chrome: +devtools://devtools/bundled/inspector.html?ws=127.0.0.1:43000 +``` + +Open the printed URL in Google Chrome to attach to the debugger session. The inspector listens on port `43000` (iOS uses `41000` and Android `42000`), or the next free port if `43000` is taken. + +Alternatively open `chrome://inspect` in Chrome, click **Configure...**, add `127.0.0.1:43000`, and select the app from the **Remote Target** list. Any other client that speaks the Chrome DevTools Protocol can connect to the same address. + +The same options as on the other platforms are supported: + +- `--debug-brk` - pauses on the first line of JavaScript until the debugger connects. The app waits up to 30 seconds for a debugger, then continues. +- `--start` - attaches to an app that is already running with the debugger enabled (started with `ns debug windows`), without restarting it. +- `--timeout` - number of seconds the CLI waits for the inspector to start. Default is 60 seconds. + +`ns run windows` doesn't start the inspector, use `ns debug windows` instead. + +The debugger, console, sources, CPU profiling and memory snapshots are provided by V8's inspector. Network requests made with `@nativescript/core` HTTP APIs are shown in the **Network** tab. + +### Console output + +`ns run windows` and `ns debug windows` stream the app's console output to your terminal. The output is also written to: + +- the debugger output (visible in the Visual Studio **Output** window or [DebugView](https://learn.microsoft.com/sysinternals/downloads/debugview)) +- `%LOCALAPPDATA%\Packages\\LocalState\console.log` + +### Crash logs + +When the app crashes, the runtime writes diagnostic files to the app's `LocalState` folder (`%LOCALAPPDATA%\Packages\\LocalState\`): + +- `nativescript-crash.log` — unhandled JavaScript and XAML errors (also streamed to the terminal) +- `nativescript-panic.log` — internal runtime errors +- `nativescript-veh.log` — fatal native exceptions + +In debug builds, an uncaught JavaScript error during startup shows a **NativeScript Runtime Error** dialog with the error details and the option to copy them or restart the app. + +Some XAML errors terminate the process immediately (for example error `0xC000027B`) without reaching these logs. In that case check **Event Viewer › Windows Logs › Application**, or capture a crash dump with [ProcDump](https://learn.microsoft.com/sysinternals/downloads/procdump). See [Troubleshooting › Windows](/troubleshooting#windows). + +### Debugging native code with Visual Studio + +To debug native (C#, C++ or WinRT) code, run the app with `ns run windows`, then in [Visual Studio](https://visualstudio.microsoft.com/) use **Debug › Attach to Process...**, select your app's process, and choose the **Managed** and/or **Native** code types. You can also open the generated host project in `platforms/windows//` in Visual Studio to browse and set breakpoints in its code. diff --git a/content/guide/extending-classes-and-implementing-interfaces-windows.md b/content/guide/extending-classes-and-implementing-interfaces-windows.md new file mode 100644 index 00000000..6a6fdc46 --- /dev/null +++ b/content/guide/extending-classes-and-implementing-interfaces-windows.md @@ -0,0 +1,88 @@ +--- +title: Extending WinRT classes and implementing interfaces +description: Subclass Windows Runtime classes and implement WinRT interfaces from JavaScript. +contributors: + - triniwiz +--- + +::: warning Experimental +Subclassing and interface implementation on Windows are experimental and more limited than on Android and iOS. For most use cases prefer composition (wrapping native controls, as `@nativescript/core` does), or implement the native part in [C# or C++/WinRT](/guide/native-code/windows) and call it from JavaScript. +::: + +On Windows, extending a native class or implementing a native interface creates a real .NET type behind the scenes. That type forwards the members you override to your JavaScript implementation, while all other members keep their native behavior. + +## Implementing WinRT interfaces + +Use `Object.extend` with an `interfaces` list, and implement the interface members using their WinRT names: + +```ts +const Stringable = Object.extend({ + interfaces: [Windows.Foundation.IStringable], + ToString() { + return 'Hello from JavaScript' + }, +}) + +const instance = new Stringable() +console.log(instance.ToString()) // Hello from JavaScript +``` + +Multiple interfaces can be listed, and all of their members implemented in the same object. + +## Extending WinRT classes + +Call `extend` on the base class and pass the members to override. An optional name can be passed as the first argument: + +```ts +const MyClass = SomeNamespace.SomeUnsealedClass.extend('MyClass', { + init() { + // called after the instance is constructed + }, + SomeVirtualMethod(arg) { + // override + }, +}) + +const instance = new MyClass() +``` + +- Only the members listed in the overrides object are overridden, all other members use the base implementation. +- `init(...args)` is called after the instance is constructed, with the constructor arguments. +- Getters and setters in the overrides object override the corresponding WinRT properties. + +::: warning Sealed classes +Only classes that can be derived from (unsealed, "composable" classes) can be extended. Most WinRT runtime classes, for example `Windows.Data.Json.JsonObject`, are **sealed**. Overrides passed to `extend` on a sealed class have no effect. +::: + +### Using TypeScript classes + +With TypeScript, decorate a class that extends a WinRT class with `@NativeClass()`, and optionally with the `@Interfaces` and `@CSharpProxy` decorators: + +```ts +@NativeClass() +@Interfaces([Windows.Foundation.IStringable]) +@CSharpProxy('MyApp.Native.MyStringable') +class MyStringable extends SomeNamespace.SomeUnsealedClass { + ToString() { + return 'MyStringable' + } +} +``` + +- `@Interfaces([...])` lists the interfaces implemented by the class. +- `@CSharpProxy(name)` sets the full name of the generated .NET type. + +::: tip Note +As on Android and iOS, `@NativeClass()` makes sure the class is compiled in a way the runtime can intercept. See [the NativeClass decorator](/best-practices/native-class). +::: + +## How it works + +At build time the CLI scans your bundled JavaScript for `extend` calls and decorated classes, and generates matching C# proxy types that are compiled into the app. This is similar to the static binding generator used on Android. + +In development builds, types that weren't found at build time are generated at runtime instead. + +## Limitations + +- Sealed classes can't be extended. +- JavaScript overrides are only called on the UI thread, see [Multithreading](/guide/multithreading#windows). diff --git a/content/guide/marshalling/index.md b/content/guide/marshalling/index.md index 12a6c503..c923f249 100644 --- a/content/guide/marshalling/index.md +++ b/content/guide/marshalling/index.md @@ -2,11 +2,12 @@ title: Marshalling in NativeScript --- -Marshalling in NativeScript refers to the conversion of JavaScript data types to native platform language (Swift/Objective C and Kotlin/Java) data types and vice versa. +Marshalling in NativeScript refers to the conversion of JavaScript data types to native platform language (Swift/Objective C, Kotlin/Java and Windows Runtime) data types and vice versa. -The conversion is handled implicitly by the NativeScript iOS and Android runtimes. +The conversion is handled implicitly by the NativeScript iOS, Android and Windows runtimes. For more information about how NativeScript converts data types for each platform, read the following articles: - [iOS Marshalling](/guide/ios-marshalling) -- [Android Marshalling](/guide/android-marshalling) \ No newline at end of file +- [Android Marshalling](/guide/android-marshalling) +- [Windows Marshalling](/guide/windows-marshalling) \ No newline at end of file diff --git a/content/guide/metadata.md b/content/guide/metadata.md index 6474743c..c1c2cc57 100644 --- a/content/guide/metadata.md +++ b/content/guide/metadata.md @@ -133,3 +133,26 @@ if (android.os.Build.VERSION.SDK_INT >= 21) { ## iOS Metadata This is our own custom data format for listing the iOS APIs we are aware of and can handle. It stores the minimal required information and provides a small size and highly efficient read access. iOS supports type introspection to some extent but along with the C APIs embedded all the way in the native APIs we had to store a lot of extra information. The Metadata is pre-generated at compile time from the SDK header files and embedded in the app package (ipa). + +## Windows Metadata + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +Unlike iOS and Android, Windows doesn't need metadata to be generated at build time. The Windows Runtime describes every API in `.winmd` metadata files, which the NativeScript Windows runtime reads on demand while the app is running: + +- The system `Windows.*` APIs are resolved from the metadata that ships with Windows. +- `Microsoft.*` (WinUI 3 and the Windows App SDK) is resolved from the Windows App SDK the app depends on. +- Any other `.winmd` file placed next to the app executable or in the app root is loaded automatically on startup. See [Adding C++/WinRT components](/guide/native-code/windows#adding-c-winrt-components). + +As a result there are no metadata filtering rules on Windows: every WinRT API available on the machine running the app can be called. + +::: tip Inspecting a type +To see what the runtime knows about a type, call `__nsDescribeWinRTType` with its full name. It returns a JSON description of the type's methods and properties: + +```ts +console.log(__nsDescribeWinRTType('Windows.Foundation.Uri')) +``` + +::: diff --git a/content/guide/multithreading.md b/content/guide/multithreading.md index e47f5fc3..cd745ce0 100644 --- a/content/guide/multithreading.md +++ b/content/guide/multithreading.md @@ -360,3 +360,17 @@ There are certain limitations to keep in mind when working with workers: - **No object transferring**. If you are a web developer you may be familiar with the ArrayBuffer and MessagePort transferring support in browsers. Currently, in NativeScript there is no such concept as object transferring. - **Debugging workers is not currently possible.** - **No nested workers support**. We want to hear from the community if this is something we need to support. + +## Windows + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +On Windows, JavaScript runs on the WinUI UI thread, so WinRT and XAML APIs are called directly without any thread marshalling. Each worker runs in its own thread with its own JavaScript runtime and has access to the WinRT APIs (but not to XAML/UI). + +Keep the following in mind: + +- Messages are serialized using the structured clone algorithm, so values such as `Date`, `Map`, `Set`, `ArrayBuffer` and typed arrays can be sent. Native (WinRT) objects can't be sent. +- JavaScript callbacks only run on the thread that created them. If WinRT invokes a callback (event handler, delegate or async completion) on a background thread, it is not delivered to JavaScript. Subscribe to events and await async operations on the thread that uses the results. +- To get results from a worker back to the UI, `postMessage` them to the main thread. `Utils.isMainThread()` tells you whether the current code runs on the UI thread. diff --git a/content/guide/native-code/generate-typings.md b/content/guide/native-code/generate-typings.md index e50af688..ebb6d173 100644 --- a/content/guide/native-code/generate-typings.md +++ b/content/guide/native-code/generate-typings.md @@ -36,10 +36,40 @@ For instance: ns typings android "com.google.android.gms:play-services-tasks" ``` +## Generate types for Windows + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +On a Windows machine, run: + +```bash +ns typings windows +``` + +This generates typings for the `Windows.*` WinRT APIs into `typings/windows/`, one `.d.ts` file per namespace group. If the project hasn't been prepared for Windows yet, the CLI runs `ns prepare windows` first to get the typings generator from `@nativescript/windows`. + +The following options control what is generated: + +| Option | Description | +| ----------------------- | ------------------------------------------------------------------------------------------------------- | +| `--root ` | The root namespace to generate typings for, for example `Microsoft` for WinUI 3. Defaults to `Windows`. | +| `--roots ` | A comma separated list of namespaces, for example `Windows.Foundation,Windows.Storage`. | +| `--input ` | Generate typings for a `.winmd` file (WinRT component) or a `.dll`/`.csproj` (.NET library). | +| `--lib ` | An additional `.winmd`, `.dll`, `.nupkg` or folder used to resolve referenced types. Can be repeated. | +| `--libs ` | A comma separated list of `--lib` paths. | + +For instance, to generate typings for your own [C++/WinRT component](/guide/native-code/windows#adding-c-winrt-components): + +```bash +ns typings windows --input App_Resources/Windows/libs/x64/MyCompany.Native.winmd +``` + ### Custom code 1. Reference the generated types in [references.d.ts](/project-structure/references-d-ts) -2. You can now code against the platform native APIs (_strongly typed_). For various examples on how to interact with native APIs in JavaScript/TypeScript, visit the [Subclassing](/guide/subclassing/), [iOS Marshalling](/guide/ios-marshalling) and [Android Marshalling](/guide/android-marshalling) pages. +2. You can now code against the platform native APIs (_strongly typed_). For various examples on how to interact with native APIs in JavaScript/TypeScript, visit the [Subclassing](/guide/subclassing/), [iOS Marshalling](/guide/ios-marshalling), [Android Marshalling](/guide/android-marshalling) and [Windows Marshalling](/guide/windows-marshalling) pages. ## Additional Resources diff --git a/content/guide/native-code/windows.md b/content/guide/native-code/windows.md new file mode 100644 index 00000000..1204a8d6 --- /dev/null +++ b/content/guide/native-code/windows.md @@ -0,0 +1,229 @@ +--- +title: Adding Windows native code to an application +description: Use .NET libraries, NuGet packages, WinRT components and Win32 DLLs in NativeScript Windows apps. +contributors: + - triniwiz +--- + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +All of the Windows Runtime (`Windows.*`) and WinUI 3 (`Microsoft.*`) APIs are available to your app without any setup. On top of that, you can add: + +- [.NET libraries and NuGet packages](#using-net-libraries) +- [C++/WinRT (or any WinRT) components](#adding-c-winrt-components) +- [Win32 DLLs](#calling-win32-dlls) + +## The Windows host project + +When you build for Windows, the CLI generates a WinUI 3 host project in `platforms/windows//` and builds it with `dotnet build`. You don't edit the generated project directly. Instead, add MSBuild files to `App_Resources/Windows`, which are imported by the host project: + +```bash +App_Resources/ +├─ Windows/ +│ ├─ app.csproj # imported by the host project +│ ├─ before-plugins.props # imported before plugin files +│ ├─ after-plugins.props # imported after plugin files +│ ├─ Package.appxmanifest +│ └─ Assets/ +└─ ... more +``` + +- `app.csproj` is the place for most customizations, such as package references and build properties. It is similar to `app.gradle` on Android. +- `before-plugins.props` and `after-plugins.props` let you set properties before plugins are applied or override values set by plugins. They are similar to `before-plugins.gradle` on Android. + +All three files are optional MSBuild fragments with a `` root element: + +```xml + + + + $(MSBuildThisFileDirectory)app.manifest + + +``` + +::: tip Note +The whole `App_Resources/Windows` folder is copied into the host project, so `$(MSBuildThisFileDirectory)` points at the copied folder. To reference files elsewhere in your project, use `$(MSBuildProjectDirectory)\..\..\..\`, which resolves to your project root. +::: + +## Using .NET libraries + +The Windows runtime hosts .NET in-process, so .NET APIs can be called directly from JavaScript. The base class library is available through the `System` global: + +```ts +const stopwatch = System.Diagnostics.Stopwatch.StartNew() +// ... do some work +stopwatch.Stop() +console.log(`Took ${stopwatch.ElapsedMilliseconds}ms`) + +console.log(System.Environment.MachineName) +``` + +### Adding a NuGet package + +Add a `PackageReference` to `App_Resources/Windows/app.csproj`: + +```xml + + + + + +``` + +Then register the root namespace of the library with the assembly that contains it, and use it from JavaScript: + +```ts +NSWinRT.dotnet.registerNamespace('Newtonsoft', 'Newtonsoft.Json') + +const json = Newtonsoft.Json.JsonConvert.SerializeObject({ hello: 'world' }) +``` + +`registerNamespace(root, assemblyName)` defines a global for the namespace root (`Newtonsoft` above), which resolves types from the given assembly. Assemblies are loaded from the app's output folder, including its `libs` and `plugins` subfolders. + +### Adding your own C# code + +To add your own C# code, create a .NET class library targeting `net10.0` (or `net10.0-windows10.0.xxxxx.0` if it uses WinRT APIs) in your project, for example in `native/windows/MyLibrary`, and reference it from `App_Resources/Windows/app.csproj`: + +```xml + + + + + +``` + +```cs +// native/windows/MyLibrary/Greeter.cs +namespace MyCompany.Native; + +public static class Greeter +{ + public static string Hello(string name) => $"Hello {name} from C#!"; +} +``` + +```ts +NSWinRT.dotnet.registerNamespace('MyCompany', 'MyLibrary') + +console.log(MyCompany.Native.Greeter.Hello('NativeScript')) +// prints: Hello NativeScript from C#! +``` + +### .NET tasks and delegates + +- Convert a returned `Task` to a promise with `NSWinRT.toPromise(task)`. +- Create a .NET delegate (for example a `System.Action`) with `NSWinRT.dotnet.asDelegate('System.Action', fn)`. For WinRT delegates use `NSWinRT.asDelegate` instead, see [Windows Marshalling › Events](/guide/windows-marshalling#events). +- .NET objects are released when they are garbage collected. Call `obj.release()` to release one immediately. + +## Adding C++/WinRT components + +Any WinRT component, for example one written in C++/WinRT, can be used from JavaScript once its metadata (`.winmd`) and implementation (`.dll`) are deployed with the app, and its classes are registered in the app manifest. `@nativescript/core` itself uses this approach for its `NativeScript.Widgets` component. + +::: info Note +Building C++/WinRT components requires [Visual Studio](https://visualstudio.microsoft.com/) with the **Desktop development with C++** workload and the C++/WinRT extension. Build the component for every architecture you ship (`x64`, `arm64`). +::: + +### 1. Deploy the component + +Place the built files in `App_Resources/Windows`, one folder per architecture: + +```bash +App_Resources/ +└─ Windows/ + ├─ app.csproj + └─ libs/ + ├─ x64/ + │ ├─ MyCompany.Native.dll + │ └─ MyCompany.Native.winmd + └─ arm64/ + ├─ MyCompany.Native.dll + └─ MyCompany.Native.winmd +``` + +Copy the files matching the target architecture next to the app executable with a target in `app.csproj`: + +```xml + + + + <_MyNativeFiles Include="$(MSBuildThisFileDirectory)libs\$(Platform)\*.dll;$(MSBuildThisFileDirectory)libs\$(Platform)\*.winmd" /> + + + + +``` + +On startup, the runtime loads every `.winmd` file found next to the executable and in the app root. + +### 2. Register the activatable classes + +Add an `inProcessServer` extension for your classes to `App_Resources/Windows/Package.appxmanifest`: + +```xml + + + + + + MyCompany.Native.dll + + + + + +``` + +### 3. Use it from JavaScript + +The component's namespaces are available as globals, like `Windows` and `Microsoft`: + +```ts +const greeter = new MyCompany.Native.Greeter() +console.log(greeter.Hello('NativeScript')) +``` + +:::tip Note +When using TypeScript, you can [generate typings](/guide/native-code/generate-typings#generate-types-for-windows) from the component's `.winmd`, or declare the root namespace as `any`: + +```ts +declare const MyCompany: any +``` + +::: + +## Calling Win32 DLLs + +Functions exported from Win32 DLLs can be called without any native code using `NSWinRT.win32`: + +```ts +const kernel32 = NSWinRT.win32.define( + 'kernel32.dll', + { GetTickCount64: [] }, + 'u64', +) +console.log(kernel32.GetTickCount64()) +``` + +See [Windows Marshalling › Win32 functions](/guide/windows-marshalling#win32-functions) for the supported types. + +## Plugins + +Plugins provide Windows implementations with `.windows.ts` files. Native Windows files are placed in the plugin's `platforms/windows` folder: + +```bash +my-plugin/ +├─ index.windows.ts +├─ plugin.props # optional, imported by the host project +├─ plugin.targets # optional, imported by the host project +└─ platforms/ + └─ windows/ + ├─ x64/ + └─ arm64/ +``` + +The CLI copies the contents of `platforms/windows` into the host project (under `plugins//`) and imports the plugin's `plugin.props` and `plugin.targets` files. Use them to add package references, copy native files to the output folder or register activatable classes, the same way an app does with `app.csproj`. When a plugin has no `plugin.props`/`plugin.targets`, the CLI generates default ones that copy the plugin's files into `plugins\` in the app output folder. + +See [`@nativescript/core`'s `plugin.targets`](https://github.com/NativeScript/NativeScript/blob/main/packages/core/plugin.targets) for a complete example that deploys a C++/WinRT component and registers its classes. diff --git a/content/guide/publishing/index.md b/content/guide/publishing/index.md index 0c1c33ed..dc0c7283 100644 --- a/content/guide/publishing/index.md +++ b/content/guide/publishing/index.md @@ -9,5 +9,6 @@ breadcrumbs: ## [Publishing to Google Play](/guide/publishing/android-google-play) ## [Publishing to Apple App Store](/guide/publishing/apple-app-store) +## [Publishing to the Microsoft Store (Windows)](/guide/publishing/microsoft-store) ## [Publishing iOS updated using ns publish ios](/guide/publishing/ns-publish) ## [Publishing with Fastlane](https://blog.nativescript.org/automatic-nativescript-app-deployments-with-fastlane/) diff --git a/content/guide/publishing/microsoft-store.md b/content/guide/publishing/microsoft-store.md new file mode 100644 index 00000000..51f261ec --- /dev/null +++ b/content/guide/publishing/microsoft-store.md @@ -0,0 +1,117 @@ +--- +title: Publishing to the Microsoft Store +description: Build signed MSIX packages for sideloading, or upload packages for the Microsoft Store. +category: Publishing +categoryLink: /guide/publishing/ +prev: /guide/publishing/ +next: false +contributors: + - triniwiz +breadcrumbs: + - name: 'Publishing' + href: '/guide/publishing/' + - name: 'Publishing to the Microsoft Store' +--- + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +NativeScript Windows apps are packaged as [MSIX](https://learn.microsoft.com/windows/msix/overview). A release build produces one of: + +| Package | Use | Command | +| ---------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------ | +| `.msix` (signed) | Sideloading, distributing outside of the Store, enterprise | `ns build windows --release --certificate ` | +| `.msixbundle` (signed) | Same as above, as a bundle | `ns build windows --release --certificate --msixbundle` | +| `.msixupload` | Submitting to the Microsoft Store | `ns build windows --release --store-upload` | + +Packages are written to `platforms/windows//AppPackages/`. Use `--copy-to ` to copy the resulting package to a different location. + +## Preparing the app + +### App identity and version + +The package identity, version, display name and publisher are defined in `App_Resources/Windows/Package.appxmanifest`: + +```xml + + + + My App + My Company + Assets\StoreLogo.png + +``` + +- `Name` defaults to your app id ([`id`](/configuration/nativescript#id) or [`windows.id`](/configuration/nativescript#windows-id)). +- `Version` must be a four part version number (`Major.Minor.Build.Revision`). Increase it for every release. +- `Publisher` must match the subject of the certificate used to sign the package. For Store submissions, use the values shown in Partner Center (see below). + +### Icons + +Replace the logos in `App_Resources/Windows/Assets/` with your own. See [App_Resources › Windows](/project-structure/app-resources#windows-specific-resources). + +### Architecture + +Each build targets a single architecture, `x64` by default. Use `--arch` to build for `arm64`: + +```bash +ns build windows --release --store-upload --arch arm64 +``` + +### Protecting your source code + +Optionally, enable [`windows.sourceProtect`](/configuration/nativescript#windows-sourceprotect) (or pass `--source-protect`) to ship your bundled JavaScript encrypted instead of as plain text files. + +## Sideloading (outside of the Store) + +MSIX packages must be signed with a certificate that's trusted on the machine installing the app. + +Sign with a `.pfx` file: + +```bash +ns build windows --release --certificate ./certs/my-app.pfx --certificate-password +``` + +Or with a certificate installed in your certificate store, identified by its thumbprint: + +```bash +ns build windows --release --certificate-thumbprint +``` + +The certificate's subject (for example `CN=My Company`) must match the `Publisher` in `Package.appxmanifest`. See [Create a certificate for package signing](https://learn.microsoft.com/windows/msix/package/create-certificate-package-signing) for how to create a certificate for testing. + +::: warning Unsigned packages +A `--release` build without `--certificate`, `--certificate-thumbprint` or `--store-upload` produces an **unsigned** `.msix`, which can't be installed until it is signed. +::: + +The signed package can be installed by double clicking it, or with PowerShell: + +```powershell +Add-AppxPackage -Path .\MyApp_1.0.0.0_x64.msix +``` + +## Publishing to the Microsoft Store + +### 1. Reserve your app name in Partner Center + +Sign in to [Partner Center](https://partner.microsoft.com/dashboard) with a [Microsoft developer account](https://learn.microsoft.com/windows/apps/publish/partner-center/open-a-developer-account), create a new app and reserve its name. + +Under **Product management › Product identity** you'll find the values for `Package/Identity/Name`, `Package/Identity/Publisher` and `Package/Properties/PublisherDisplayName`. Copy them into the matching attributes in `App_Resources/Windows/Package.appxmanifest`. + +### 2. Build a Store upload package + +```bash +ns build windows --release --store-upload +``` + +This produces an unsigned `.msixupload` package in `platforms/windows//AppPackages/`. You don't need a certificate, the Store signs the package for you. + +### 3. Submit the package + +In Partner Center, create a new submission for your app, upload the `.msixupload` file under **Packages**, fill in the Store listing, and submit it for certification. + +See [Publish your app in the Microsoft Store](https://learn.microsoft.com/windows/apps/publish/) for more details on the submission process. diff --git a/content/guide/running.md b/content/guide/running.md index 9b421cc6..ac5e4a5e 100644 --- a/content/guide/running.md +++ b/content/guide/running.md @@ -14,6 +14,7 @@ To run a project, use the `ns run` command. There's also a `ns debug` command co ```bash ns run android ns run ios +ns run windows # experimental, Windows host only ``` The `run` command runs the app on all connected devices matching the platform. You can control which devices to run on with the following flags: @@ -121,6 +122,34 @@ The app should install and launch on the iOS device. Xcode network devices sometimes get disconnected or have an unreliable connection. We recommend using a wired connection to avoid these occasional issues. ::: +## Running on Windows + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/) for the current status. +::: + +Windows apps run on the local machine, there is no emulator or remote device involved. When running on a Windows host with the [Windows environment set up](/setup/windows#setting-up-windows-for-windows-desktop), the local machine is listed as a `Windows` device: + +```bash +ns devices windows +``` + +To build, install and launch the app: + +```bash +ns run windows +``` + +In debug mode the CLI builds the app with `dotnet build`, registers it as a development package (this requires [Developer Mode](https://learn.microsoft.com/windows/apps/get-started/enable-your-device-for-development) to be enabled) and launches it. Console output from the app is streamed to the terminal. + +Changes to your app are synced to the registered package folder. With the [Vite bundler](/configuration/vite) changes are applied with HMR, with webpack the app is restarted on every change. + +You can pick the target architecture with `--arch`: + +```bash +ns run windows --arch arm64 # defaults to x64 +``` + ## Running on virtual devices ### Android Emulators diff --git a/content/guide/styling.md b/content/guide/styling.md index 7c36e44a..f93dc05a 100644 --- a/content/guide/styling.md +++ b/content/guide/styling.md @@ -157,6 +157,10 @@ There are 4 primary ways to target styles at iOS or Android: /// +::: tip Windows +The same conventions apply to the [Windows platform](/guide/windows/): `.windows.css` stylesheets, ` ... ` markup blocks, `windows:` attributes and `.ns-windows` CSS rules. +::: + The most common and maintainable pattern for managing platform-agnostic and platform-specific styles in NativeScript is with multiple stylesheets and CSS imports. /// flavor plain @@ -598,7 +602,7 @@ To allow for flexible styling and theming, NativeScript provides the following C - `.ns-root` - a class assigned to the application root view - `.ns-modal` - a class assigned to the modal root view -- `.ns-android`, `.ns-ios` - classes that specify the application platform +- `.ns-android`, `.ns-ios`, `.ns-windows` - classes that specify the application platform - `.ns-phone`, `.ns-tablet` - classes that specify the device type - `.ns-portrait`, `.ns-landscape`, `.ns-unknown` - classes that specify the application orientation - `.ns-light`, `.ns-dark` - classes that specify the system appearance. diff --git a/content/guide/subclassing/index.md b/content/guide/subclassing/index.md index d5296e03..a2a17d2e 100644 --- a/content/guide/subclassing/index.md +++ b/content/guide/subclassing/index.md @@ -2,12 +2,13 @@ title: Extending native classes and implementing interfaces in NativeScript --- -In NativeScript, you can extend native classes and implement interfaces for Android, and conform to iOS protocols. +In NativeScript, you can extend native classes and implement interfaces for Android, conform to iOS protocols, and extend WinRT classes and implement WinRT interfaces on Windows. See the following articles for examples: - [Extending Kotlin/Java classes in NativeScript](/guide/extending-classes-and-implementing-interfaces-android#extending-javakotlin-classes-in-nativescript) - [Implementing Kotlin/Java interfaces in NativeScript](/guide/extending-classes-and-implementing-interfaces-android#implementing-java-kotlin-interfaces-in-nativescript) - [Extending Objective-C/Swift classes in NativeScript](/guide/extending-classes-and-conforming-to-protocols-ios.md#extending-ios-classes) - [Conforming to Objective-C/Swift protocols in NativeScript](/guide/extending-classes-and-conforming-to-protocols-ios.md#conforming-to-objective-c-swift-protocols) +- [Extending WinRT classes and implementing WinRT interfaces in NativeScript](/guide/extending-classes-and-implementing-interfaces-windows) diff --git a/content/guide/windows-marshalling.md b/content/guide/windows-marshalling.md new file mode 100644 index 00000000..8cb7182d --- /dev/null +++ b/content/guide/windows-marshalling.md @@ -0,0 +1,320 @@ +--- +title: Windows Marshalling +description: How JavaScript values are converted to and from Windows Runtime (WinRT) types. +contributors: + - triniwiz +--- + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +The NativeScript Windows runtime reads WinRT metadata at runtime and converts values between JavaScript and WinRT automatically. This page describes how the WinRT type system is projected to JavaScript. + +## Namespaces and types + +Every root WinRT namespace is available as a global. `Windows.*` contains the system APIs and `Microsoft.*` contains WinUI 3 and the Windows App SDK: + +```ts +const uri = new Windows.Foundation.Uri('https://nativescript.org/') +const grid = new Microsoft.UI.Xaml.Controls.Grid() +``` + +Namespaces and types are resolved lazily the first time they are accessed. + +::: tip Use `Microsoft.UI.Xaml` +For UI, use the WinUI 3 types in `Microsoft.UI.Xaml.*`. The older `Windows.UI.Xaml.*` (UWP XAML) types can't be used in a WinUI 3 app. Some types such as `Windows.UI.Color` and `Windows.UI.Text.FontStyle` are still used by WinUI 3 and remain in the `Windows.*` namespace. +::: + +## Classes + +### Constructors + +Runtime classes are created with `new`. Constructors with parameters are selected by the number of arguments: + +```ts +const formatter = new Windows.Globalization.NumberFormatting.DecimalFormatter( + ['fr-FR'], + 'FR', +) +``` + +### Properties and methods + +Member names are used exactly as they are declared in WinRT (PascalCase), there is no camelCase aliasing: + +```ts +const uri = new Windows.Foundation.Uri('https://nativescript.org/docs') +console.log(uri.AbsoluteUri, uri.Host) + +const textBlock = new Microsoft.UI.Xaml.Controls.TextBlock() +textBlock.Text = 'Hello' +textBlock.FontSize = 24 +``` + +Static members are accessed on the class: + +```ts +const guid = Windows.Foundation.GuidHelper.CreateNewGuid() +const localSettings = Windows.Storage.ApplicationData.Current.LocalSettings +``` + +A failing call throws a JavaScript `Error` that contains the `HRESULT` returned by WinRT. + +### Overloads + +Overloaded methods are resolved by the number of arguments. When two overloads take the same number of arguments, call the overload by its WinRT overload name (the name shown in the Microsoft documentation under `[Overload]`, for example `CreateColorBrushWithColor`). + +### Type checks + +`instanceof` works against runtime classes as well as the interfaces they implement: + +```ts +uri instanceof Windows.Foundation.Uri // true +uri instanceof Windows.Foundation.IStringable // true +``` + +Objects returned as an interface or as `Object` (`IInspectable`) are resolved to their concrete runtime class, so there is no need to cast or call `QueryInterface`. All members of the class, its interfaces and base classes are available on the returned object. + +## Primitive types + +| WinRT | JavaScript | +| -------------------------------- | ------------------------------------------------------------------ | +| `Boolean` | `boolean` | +| `Int8`, `Int16`, `Int32` | `number` | +| `UInt8`, `UInt16`, `UInt32` | `number` | +| `Int64`, `UInt64` | `number`, or `BigInt` when the value doesn't fit in a safe integer | +| `Single`, `Double` | `number` | +| `String` | `string` | +| Enums | `number` (combine flags with `\|`) | +| `IReference` (nullable value) | the value, or `null` | +| Runtime classes and interfaces | a JavaScript wrapper object, or `null` | + +::: warning Strict strings and booleans +`String` and `Boolean` parameters are not coerced. Passing a number to a `String` parameter (or `null`) throws a `TypeError`. Convert values yourself: + +```ts +textBlock.Text = String(count) +``` + +::: + +### Nullable values (`IReference`) + +Pass a plain JavaScript value, `null` or `undefined` to properties and parameters of type `IReference`. The runtime boxes the value for you: + +```ts +datePicker.SelectedDate = null +``` + +### `Object` (`IInspectable`) values + +When a parameter or property is typed as `Object`, JavaScript strings, numbers and booleans are boxed automatically. To box to a specific WinRT type, use the `interop` helpers: + +```ts +const values = new Windows.Foundation.Collections.PropertySet() +values.Insert('count', interop.uint(3)) +values.Insert('name', 'NativeScript') +``` + +Available helpers: `interop.int`, `interop.uint`, `interop.long`, `interop.ulong`, `interop.short`, `interop.ushort`, `interop.byte`, `interop.float`, `interop.double`, `interop.bool`, `interop.char`, `interop.guid`, `interop.timeSpan` and `interop.dateTime`. + +## Structs + +Structs such as `Windows.Foundation.Point`, `Windows.UI.Color` or `Microsoft.UI.Xaml.Thickness` can be passed as plain objects using the WinRT field names: + +```ts +border.BorderThickness = { Left: 1, Top: 1, Right: 1, Bottom: 1 } +border.Background = new Microsoft.UI.Xaml.Media.SolidColorBrush({ + A: 255, + R: 101, + G: 173, + B: 241, +}) +``` + +Structs returned from WinRT are copies. Changing a field on the returned object does **not** update the native value, assign the struct back instead: + +```ts +const margin = element.Margin +margin.Left = 16 +element.Margin = margin +``` + +### Date and time + +`Windows.Foundation.DateTime` and `Windows.Foundation.TimeSpan` are structs measured in 100-nanosecond ticks, stored in their `UniversalTime` and `Duration` fields. Use the `interop` helpers to convert between a JavaScript `Date` and `DateTime` ticks: + +```ts +// Date -> DateTime +datePicker.SelectedDate = { + UniversalTime: interop.toWinRTDateTimeTicks(new Date()), +} + +// DateTime -> Date +const date = interop.fromWinRTDateTimeTicks( + datePicker.SelectedDate.UniversalTime, +) + +// TimeSpan from milliseconds (1 ms = 10000 ticks) +timePicker.SelectedTime = { Duration: 1000 * 10000 } +``` + +Tick values larger than `Number.MAX_SAFE_INTEGER` are returned as `BigInt`. + +To pass a `DateTime` or `TimeSpan` where WinRT expects an `Object`, box it with `interop.dateTime(date)` or `interop.timeSpan(milliseconds)`. + +::: tip Raw struct bytes +Any struct can also be passed as an `ArrayBuffer` containing its raw (little-endian) memory layout. This is useful as a fallback when a plain object isn't accepted: + +```ts +const buffer = new ArrayBuffer(8) +new DataView(buffer).setBigInt64(0, interop.toWinRTDateTimeTicks(date), true) +datePicker.MinYear = buffer +``` + +::: + +## Collections + +### Arrays + +JavaScript arrays can be passed where WinRT expects an `IIterable`, `IVectorView` or `IVector`: + +```ts +const formatter = + new Windows.Globalization.DateTimeFormatting.DateTimeFormatter('shortdate', [ + 'en-US', + 'de-DE', + ]) +``` + +Collections returned from WinRT are wrapper objects, use their WinRT members to read them: + +```ts +const languages = Windows.System.UserProfile.GlobalizationPreferences.Languages +for (let i = 0; i < languages.Size; i++) { + console.log(languages.GetAt(i)) +} +``` + +Maps (`IMap`, `IPropertySet`) are used through `Insert`, `Lookup`, `HasKey`, `Remove` and `Size`. + +### Byte arrays and buffers + +Parameters of type `UInt8[]` (`byte[]`) accept an `ArrayBuffer`, a typed array or a `DataView` without copying. Methods that fill an array write directly into it: + +```ts +const bytes = new Uint8Array(reader.UnconsumedBufferLength) +reader.ReadBytes(bytes) +``` + +To create an `IBuffer` from bytes, use `CryptographicBuffer`: + +```ts +const buffer = + Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(bytes) +``` + +## Out parameters + +When a method has `out` parameters, omit them. The call returns an array containing the return value followed by each `out` value: + +```ts +const [ok, value] = Windows.Data.Json.JsonValue.TryParse('"hello"') +if (ok) { + console.log(value.GetString()) +} +``` + +## Events + +WinRT events are subscribed to by assigning a handler to the event property, and unsubscribed by assigning `null`: + +```ts +const button = new Microsoft.UI.Xaml.Controls.Button() + +button.Click = NSWinRT.asDelegate( + 'Microsoft.UI.Xaml.RoutedEventHandler', + (sender, args) => { + console.log('clicked') + }, +) + +// unsubscribe +button.Click = null +``` + +Each event holds **one** JavaScript handler per object. Assigning a new handler replaces (and unsubscribes) the previous one. + +A plain function can be assigned when the delegate type is not generic, but we recommend wrapping handlers with `NSWinRT.asDelegate(typeName, fn)`, which always subscribes reliably. For generic delegates such as `TypedEventHandler`, pass the closed generic type name using the backtick arity notation: + +```ts +datePicker.SelectedDateChanged = NSWinRT.asDelegate( + 'Windows.Foundation.TypedEventHandler`2', + (sender, args) => { + console.log('date changed') + }, +) +``` + +::: warning Keep a reference +Keep a reference to handlers you create with `NSWinRT.asDelegate` (for example on your view instance) for as long as the subscription is needed. +::: + +## Async operations + +WinRT async operations (`IAsyncAction`, `IAsyncOperation`) are not promises. Convert them with `NSWinRT.toPromise`: + +```ts +const folder = Windows.Storage.ApplicationData.Current.LocalFolder +const file = await NSWinRT.toPromise( + folder.CreateFileAsync( + 'notes.txt', + Windows.Storage.CreationCollisionOption.ReplaceExisting, + ), +) +await NSWinRT.toPromise(Windows.Storage.FileIO.WriteTextAsync(file, 'Hello')) +``` + +The promise resolves with the operation's result, and rejects if the operation fails or is canceled. An optional timeout can be passed: + +```ts +await NSWinRT.toPromise(operation, { timeoutMs: 10000 }) +``` + +## .NET types + +.NET libraries are available through the `System` global and other registered namespaces. .NET `Task` objects are converted with `NSWinRT.toPromise` as well: + +```ts +const stopwatch = System.Diagnostics.Stopwatch.StartNew() +// ... +stopwatch.Stop() +console.log(stopwatch.ElapsedMilliseconds) +``` + +See [Adding Windows native code](/guide/native-code/windows#using-net-libraries) for using NuGet packages and your own .NET code. + +## Win32 functions + +Exported functions of Win32 DLLs can be called using `NSWinRT.win32`: + +```ts +const user32 = NSWinRT.win32.define( + 'user32.dll', + { MessageBoxW: ['pointer', 'wstr', 'wstr', 'u32'] }, + 'i32', +) +user32.MessageBoxW(null, 'Hello from NativeScript', 'NativeScript', 0) +``` + +Supported types are `void`, `bool`, `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `f32`, `f64`, `pointer`, `wstr` (UTF-16 string) and `str` (ANSI string). + +## Threading + +JavaScript runs on the WinUI UI thread, so WinRT and XAML APIs can be called directly. JavaScript callbacks can only run on that thread: a delegate invoked by WinRT on a background thread is not delivered to JavaScript. See [Multithreading](/guide/multithreading#windows). + +::: danger Don't change the UI during layout +Adding, removing or reparenting XAML elements synchronously inside `CompositionTarget.Rendering`, `LayoutUpdated` or `SizeChanged` handlers crashes the app (error `0xC000027B`). Defer those changes with `setTimeout(() => { ... }, 0)`. +::: diff --git a/content/guide/windows/index.md b/content/guide/windows/index.md new file mode 100644 index 00000000..e890ed40 --- /dev/null +++ b/content/guide/windows/index.md @@ -0,0 +1,162 @@ +--- +title: Developing for Windows +description: Build native Windows desktop apps with NativeScript, WinUI 3 and the Windows App SDK. +contributors: + - triniwiz +--- + +NativeScript can target Windows desktop in addition to Android and iOS. Your app runs on a V8 based runtime that has direct access to the entire [Windows Runtime (WinRT)](https://learn.microsoft.com/windows/uwp/cpp-and-winrt-apis/intro-to-using-cpp-with-winrt) API surface, [WinUI 3](https://learn.microsoft.com/windows/apps/winui/winui3/) (`Microsoft.UI.*`) and .NET libraries. `@nativescript/core` UI components render as native WinUI 3 controls. + +::: warning Experimental +The Windows platform is experimental. APIs, tooling and requirements may change between releases, and some features available on Android and iOS are not implemented yet (see [Known limitations](#known-limitations)). Please report issues on [GitHub](https://github.com/NativeScript/NativeScript/issues) or in [our Community Discord](https://nativescript.org/discord). +::: + +## Requirements + +- A Windows 10 (1809+) or Windows 11 development machine, x64 or arm64. Windows apps can only be built on Windows. +- The .NET 10 SDK and Developer Mode enabled. + +Follow the [Windows setup guide](/setup/windows#setting-up-windows-for-windows-desktop) to prepare your environment. + +## Adding Windows to a project + +The Windows runtime is distributed as the [`@nativescript/windows`](https://www.npmjs.com/package/@nativescript/windows) package. While the platform is in preview, add it using the `beta` tag: + +```bash +ns platform add windows@beta +``` + +This adds `@nativescript/windows` to the `devDependencies` of your `package.json`. You can also install it directly: + +```bash +npm install --save-dev @nativescript/windows@beta +``` + +The CLI creates a WinUI 3 host project in `platforms/windows//` the first time you prepare, build or run the app for Windows. + +::: tip +Windows support requires a version of `@nativescript/core` that includes the Windows implementation. Make sure your project uses the latest `@nativescript/core` and `@nativescript/webpack` or `@nativescript/vite`. +::: + +## Running the app + +```bash +ns run windows +``` + +The app is built, registered on the local machine and launched. Console output is streamed to your terminal, and file changes are synced to the running app. With the [Vite bundler](/configuration/vite) changes are applied using HMR; with webpack the app restarts on each change. + +See [Running on Windows](/guide/running#running-on-windows) and [Debugging on Windows](/guide/debugging#debugging-on-windows) for more details. + +## Writing platform-specific code + +Windows follows the same conventions as the other platforms. + +### Platform files + +Files ending in `.windows.ts` (also `.windows.js`, `.windows.css`, `.windows.scss`, ...) are only included in Windows builds: + +``` +my-component/ +├── index.android.ts +├── index.ios.ts +└── index.windows.ts +``` + +::: warning Note +Windows builds only pick up `.windows.*` files, they never fall back to `.ios.*` or `.android.*`. If a module has platform files, add a `.windows.*` variant (or a shared file without a platform suffix). +::: + +### Platform conditionals + +The `__WINDOWS__` global is replaced at build time, so the code for other platforms is removed from the bundle: + +```ts +if (__WINDOWS__) { + // Windows only +} +``` + +At runtime you can also check `Device.os`, or import `isWindows`: + +```ts +import { Device } from '@nativescript/core' +import { isWindows } from '@nativescript/core/platform' + +console.log(Device.os) // 'Windows' +console.log(isWindows) // true +``` + +### Platform specific markup and CSS + +```xml + + + + +``` + +```css +.ns-windows .title { + font-size: 24; +} +``` + +## Accessing native APIs + +All WinRT namespaces are available as globals, `Windows.*` for the system APIs and `Microsoft.*` for WinUI 3 and the Windows App SDK. Member names are used exactly as documented by Microsoft (PascalCase): + +```ts +const uri = new Windows.Foundation.Uri('https://nativescript.org') +console.log(uri.Host) // nativescript.org + +const settings = Windows.Storage.ApplicationData.Current.LocalSettings +``` + +Every `@nativescript/core` view exposes the underlying WinUI 3 control through `nativeView`: + +```ts +import { Button } from '@nativescript/core' + +const button = new Button() +const native = button.nativeView as Microsoft.UI.Xaml.Controls.Button +``` + +The application wrapper is available as `Application.windows`, and `Application.windows.getNativeApplication()` returns the `Microsoft.UI.Xaml.Application` instance. + +Read [Windows Marshalling](/guide/windows-marshalling) to learn how JavaScript values are converted to WinRT types, how to subscribe to events and how to await async operations. + +## App resources + +Windows specific resources (app manifest, logos, splash screen) live in `App_Resources/Windows`. See [App_Resources › Windows](/project-structure/app-resources#windows-specific-resources). + +Custom fonts placed in `src/fonts` work the same way as on the other platforms. + +## Using plugins + +Plugins written purely in JavaScript/TypeScript on top of `@nativescript/core` generally work on Windows. Plugins with native code need a Windows implementation (`.windows.ts` files and, optionally, native Windows code in `platforms/windows`). See [Adding Windows native code](/guide/native-code/windows#plugins). + +## Publishing + +Release builds produce MSIX packages for sideloading or for the Microsoft Store. See [Publishing to the Microsoft Store](/guide/publishing/microsoft-store). + +## Known limitations + +The following are not implemented on Windows yet: + +- Accessibility properties (`accessible`, `accessibilityLabel`, ...) +- Pan, pinch, rotation and swipe gestures (`tap`, `doubleTap`, `longPress` and `touch` are supported) +- `isEnabled`, `isUserInteractionEnabled` and `z-index` +- Multiple windows (`Application.openWindow`) +- `font://` image sources and Image `tintColor` +- 3D transforms (`rotateX`, `rotateY`, `perspective`), `background-repeat: space | round`, and `cubicBezier` animation curves (they fall back to linear) +- `returnKeyType`, `autocorrect` and `autofillType` on TextField and TextView +- TabView tab color properties + +Some behaviors differ from mobile: + +- `Screen.mainScreen` reports the size of the app **window**, not the monitor, and `Device.deviceType` reports `Tablet` or `Phone` based on the window size. +- Size qualifiers (for example `page.minWH600.xml`) are re-evaluated when the window is resized. +- `Alt + Left` and the mouse back button navigate back in a `Frame`. diff --git a/content/index.md b/content/index.md index 9ad08e39..b03e2b05 100644 --- a/content/index.md +++ b/content/index.md @@ -16,6 +16,7 @@ Some popular use cases: - Augmenting JavaScript projects with platform API capabilities - AndroidTV and Watch development - watchOS development +- Windows desktop development (experimental, see [Developing for Windows](/guide/windows/)) - Learning native platforms through JavaScript understanding - Exploring platform API documentation by trying APIs [directly from a web browser](https://preview.nativescript.org/) without requiring a platform development machine setup. diff --git a/content/project-structure/app-resources.md b/content/project-structure/app-resources.md index 52629bd0..3926b38b 100644 --- a/content/project-structure/app-resources.md +++ b/content/project-structure/app-resources.md @@ -5,7 +5,7 @@ contributors: - NathanWalker --- -The App_Resources folder contains platform-specific resources of the application (icons, configuration files, native code, etc.). An application that supports both Android and iOS would therefore contain a subfolder for each platform. +The App_Resources folder contains platform-specific resources of the application (icons, configuration files, native code, etc.). An application that supports both Android and iOS would therefore contain a subfolder for each platform (and a `Windows` subfolder when [targeting Windows](/guide/windows/)). This page serves as a quick reference to understand how most settings in App_Resources affect the behavior and the look of a NativeScript app. @@ -211,3 +211,133 @@ For a list of available entitlements refer to [Apple's Entitlements documentatio ### Adding ObjectiveC/Swift Code to an application See [Adding ObjectiveC/Swift Code to an application](/guide/native-code/ios). + +## Windows specific resources + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +```bash +App_Resources/ +├─ Windows/ +│ ├─ Package.appxmanifest # package identity, display name, logos, capabilities +│ ├─ app.manifest # Win32 application manifest (DPI awareness) +│ ├─ app.csproj # MSBuild customizations (package references, properties) +│ ├─ before-plugins.props # optional, imported before plugins +│ ├─ after-plugins.props # optional, imported after plugins +│ └─ Assets/ # logos and splash screen images +└─ ... more +``` + +All files are optional, the Windows host project provides defaults. New projects created from the official templates include an [`App_Resources/Windows`](https://github.com/NativeScript/nativescript-app-templates/tree/main/shared-mobile/App_Resources/Windows) folder that you can copy into existing projects. + +### Package.appxmanifest + +The [package manifest](https://learn.microsoft.com/uwp/schemas/appxpackage/appx-package-manifest) defines the app's identity, display name, logos, capabilities and dependencies. Values from `App_Resources/Windows/Package.appxmanifest` are merged into the host project's manifest, with your values taking precedence. The `__APP_IDENTIFIER__` and `__PROJECT_NAME__` tokens are replaced with your app id and project name. + +```xml + + + + + Your app name + My Company + Assets\StoreLogo.png + + + + + + + + + + + + + + + + +``` + +::: warning Note +Keep the `Application` `Id="App"` and the `runFullTrust` capability, the CLI relies on them to launch the app. +::: + +### Windows app display name + +Set `AppDisplayName` (and optionally `AppDescription`) in `App_Resources/Windows/app.csproj`: + +```xml + + + My App + My Windows App, built with NativeScript. + + +``` + +The display name is applied to both the package (``) and the app tile, Start menu and taskbar (``) of the generated manifest. It defaults to the project name. + +### Capabilities + +Declare the [capabilities](https://learn.microsoft.com/windows/uwp/packaging/app-capability-declarations) your app needs (for example `webcam`, `microphone` or `location`) in the `` element of `Package.appxmanifest`. + +### Logos and splash screen + +Images in `App_Resources/Windows/Assets/` are copied into the app package and referenced from `Package.appxmanifest`. Provide the standard MSIX sizes (`Square44x44Logo`, `Square150x150Logo`, `Wide310x150Logo`, `StoreLogo`, `SplashScreen`, ...) with [scale variants](https://learn.microsoft.com/windows/apps/design/style/iconography/app-icon-construction) such as `Square150x150Logo.scale-200.png`. + +To use different files, or to change the splash screen background color (`#65ADF1` by default), set the corresponding properties in `App_Resources/Windows/app.csproj`: + +```xml + + + #FFFFFF + Assets\SplashScreen.png + Assets\Square150x150Logo.png + Assets\Square44x44Logo.png + Assets\Wide310x150Logo.png + Assets\StoreLogo.png + Assets\LockScreenLogo.png + + +``` + +Images in `Assets/` can also be used from your app with `res://` URLs, for example `res://icon` loads `Assets/icon.png`. + +### DPI awareness (app.manifest) + +To render crisp text on high-DPI displays, the app must declare Per-Monitor V2 DPI awareness in an `app.manifest`: + +```xml + + + + + + true/PM + PerMonitorV2 + + + +``` + +And reference it from `App_Resources/Windows/app.csproj`: + +```xml + + + $(MSBuildThisFileDirectory)app.manifest + + +``` + +### Adding native code to a Windows application + +See [Adding Windows native code](/guide/native-code/windows). diff --git a/content/setup/index.md b/content/setup/index.md index 1b9a9c69..c3831b9a 100644 --- a/content/setup/index.md +++ b/content/setup/index.md @@ -12,14 +12,20 @@ contributors: Select the guide relevant to your development machine and follow the steps carefully to get a clean working environment ready. -| Operating System | Android | iOS | -| ---------------- | ------------------------------------------------ | ----------------------------------------------------------------------- | -| Windows | :white_check_mark: [Setup Guide](/setup/windows) | :x: Unsupported | -| macOS | :white_check_mark: [Setup Guide](/setup/macos) | :white_check_mark: [Setup Guide](/setup/macos#setting-up-macos-for-ios) | -| Linux | :white_check_mark: [Setup Guide](/setup/linux) | :x: Unsupported | +| Operating System | Android | iOS | Windows | +| ---------------- | ------------------------------------------------ | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| Windows | :white_check_mark: [Setup Guide](/setup/windows) | :x: Unsupported | :construction: [Setup Guide](/setup/windows#setting-up-windows-for-windows-desktop) (experimental) | +| macOS | :white_check_mark: [Setup Guide](/setup/macos) | :white_check_mark: [Setup Guide](/setup/macos#setting-up-macos-for-ios) | :x: Unsupported | +| Linux | :white_check_mark: [Setup Guide](/setup/linux) | :x: Unsupported | :x: Unsupported | :::warning A note about iOS on unsupported systems A Mac is required to build projects that use native iOS code. Simpler apps can be tested using [NativeScript Preview](https://preview.nativescript.org). ::: + +:::warning A note about Windows on unsupported systems + +A Windows 10 (1809+) or Windows 11 machine is required to build projects for the Windows desktop target. The Windows platform is currently experimental, see [Developing for Windows](/guide/windows/). + +::: diff --git a/content/setup/windows.md b/content/setup/windows.md index e7a06ded..0ce63324 100644 --- a/content/setup/windows.md +++ b/content/setup/windows.md @@ -217,6 +217,83 @@ If any of the above failed, we recommend asking in [our Community Discord](https ::: +## Setting up Windows for Windows desktop + +::: warning Experimental +The Windows platform is experimental. APIs, tooling and requirements may change between releases. See [Developing for Windows](/guide/windows/) for the current status. +::: + +NativeScript can build native Windows desktop apps using [WinUI 3](https://learn.microsoft.com/windows/apps/winui/winui3/) and the [Windows App SDK](https://learn.microsoft.com/windows/apps/windows-app-sdk/). Apps are packaged as MSIX and run on the local machine. + +You will need: + +- Windows 10 version 1809 (build 17763) or newer, or Windows 11 — x64 or arm64 +- Node — see [Installing Node](#installing-node) above +- The .NET 10 SDK +- Developer Mode enabled +- The NativeScript CLI + +### Installing the .NET SDK + +The Windows app host is a .NET project that is built with `dotnet build`. Install the **.NET 10 SDK** using one of the following methods: + +::: code-group + +```bash [winget] +winget install Microsoft.DotNet.SDK.10 +``` + +```text [Installer] +https://dotnet.microsoft.com/download/dotnet/10.0 +``` + +::: + +Open a new terminal and verify a 10.x SDK is listed: + +```bash +dotnet --list-sdks +``` + +::: tip Visual Studio is optional +Visual Studio is **not** required to build and run NativeScript Windows apps. You only need [Visual Studio](https://visualstudio.microsoft.com/) (with the **Desktop development with C++** workload and a Windows SDK) if you want to author your own [C++/WinRT components](/guide/native-code/windows#adding-c-winrt-components). +::: + +### Enabling Developer Mode + +During development the CLI registers your app directly from its build output, which requires Developer Mode. + +- **Windows 11**: open **Settings › System › For developers** and turn on **Developer Mode**. +- **Windows 10**: open **Settings › Update & Security › For developers** and select **Developer mode**. + +See [Enable your device for development](https://learn.microsoft.com/windows/apps/get-started/enable-your-device-for-development) for more details. + +### Installing the NativeScript CLI + +If you haven't already, install the NativeScript CLI globally: + +```bash +npm install -g nativescript +``` + +### Verifying the environment + +Open a new terminal and run: + +```bash +ns doctor windows +``` + +`ns doctor windows` checks that a .NET SDK 10 or newer is installed and that Developer Mode is enabled. If you see **No issues were detected** your environment is ready. + +Your machine should also be listed as a `Windows` device: + +```bash +ns devices windows +``` + +You're now ready to [add the Windows platform to a project](/guide/windows/#adding-windows-to-a-project). + ## Setting up Windows for iOS :::danger :x: Unsupported diff --git a/content/sidebar.ts b/content/sidebar.ts index ac2cd10e..2ccb9a91 100644 --- a/content/sidebar.ts +++ b/content/sidebar.ts @@ -240,6 +240,19 @@ export default [ }, ] }, + { + text: 'Developing for Windows', + items: [ + { + text: 'Developing for Windows', + link: '/guide/windows/', + }, + { + text: 'Publishing to the Microsoft Store', + link: '/guide/publishing/microsoft-store', + }, + ] + }, { text: 'Agentic Coding', items: [ @@ -268,6 +281,10 @@ export default [ text: 'Adding ObjectiveC/Swift Code', link: '/guide/native-code/ios', }, + { + text: 'Adding Windows Code', + link: '/guide/native-code/windows', + }, { text: 'Generating TypeScript types', link: '/guide/native-code/generate-typings', @@ -286,6 +303,10 @@ export default [ text: 'iOS', link: '/guide/extending-classes-and-conforming-to-protocols-ios', }, + { + text: 'Windows', + link: '/guide/extending-classes-and-implementing-interfaces-windows', + }, ], }, { @@ -336,6 +357,10 @@ export default [ text: 'Android Marshalling', link: '/guide/android-marshalling', }, + { + text: 'Windows Marshalling', + link: '/guide/windows-marshalling', + }, ], }, { diff --git a/content/troubleshooting.md b/content/troubleshooting.md index 7da0d794..ae544f1d 100644 --- a/content/troubleshooting.md +++ b/content/troubleshooting.md @@ -212,3 +212,49 @@ The above can be ignored by adding the following to your `tsconfig.json`: ::: + +## Windows + +::: warning Experimental +The Windows platform is experimental. See [Developing for Windows](/guide/windows/). +::: + +### Deployment fails with 0x80073CFF + +During development, the CLI registers the app from its build output, which requires Developer Mode. Enable it in **Settings › System › For developers** (Windows 11) or **Settings › Update & Security › For developers** (Windows 10), then run the app again. See [Enabling Developer Mode](/setup/windows#enabling-developer-mode). + +### The app doesn't start after `ns run windows` + +If the app was installed but nothing happens when it's launched, its development registration may be stale (for example after the `platforms` folder was deleted). Remove the package and run the app again: + +```powershell +Get-AppxPackage -Name | Remove-AppxPackage +``` + +`` is the [`id`](/configuration/nativescript#id) (or [`windows.id`](/configuration/nativescript#windows-id)) from your `nativescript.config.ts`. + +### Release package fails to install with 0x800B0100 + +The `.msix` package isn't signed. Build it with `--certificate ` or `--certificate-thumbprint `, and make sure the certificate is trusted on the machine. See [Publishing to the Microsoft Store › Sideloading](/guide/publishing/microsoft-store#sideloading-outside-of-the-store). + +### Text looks blurry on high-DPI displays + +The app is missing a DPI aware `app.manifest`. Add one to `App_Resources/Windows` as described in [App_Resources › DPI awareness](/project-structure/app-resources#dpi-awareness-app-manifest). + +### The app closes without an error (0xC000027B) + +Some XAML errors terminate the process immediately, before any JavaScript or runtime error handler runs. The most common cause is changing the XAML tree (adding, removing or reparenting elements) synchronously inside a layout or rendering callback, such as `CompositionTarget.Rendering`, `LayoutUpdated` or `SizeChanged`. Defer such changes with `setTimeout(() => { ... }, 0)`. + +To find the cause, check the crash logs described in [Debugging › Crash logs](/guide/debugging#crash-logs), look for the error in **Event Viewer › Windows Logs › Application**, or capture a crash dump with [ProcDump](https://learn.microsoft.com/sysinternals/downloads/procdump): + +```bash +procdump -e -ma -w .exe +``` + +### TypeError: Invalid FFI String type, expected String + +WinRT `String` parameters and properties only accept JavaScript strings. Convert the value first, for example `textBlock.Text = String(value)`. See [Windows Marshalling › Primitive types](/guide/windows-marshalling#primitive-types). + +### Build fails because a file is in use + +A running instance of the app can lock files in `platforms/windows`. Close the app (or run `ns clean`, which stops running instances of the app) and build again. diff --git a/content/ui/action-bar.md b/content/ui/action-bar.md index ef767e5c..626acf15 100644 --- a/content/ui/action-bar.md +++ b/content/ui/action-bar.md @@ -348,13 +348,16 @@ See [R.drawable](https://developer.android.com/reference/android/R.drawable.html - Android: [android.widget.Toolbar](https://developer.android.com/reference/android/widget/Toolbar.html) - iOS: [UINavigationBar](https://developer.apple.com/documentation/uikit/uinavigationbar?language=objc) +- Windows: rendered by the parent Frame's navigation bar, a [Microsoft.UI.Xaml.Controls.Grid](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid) containing the title and action items ### ActionItem - Android: [android.widget.Toolbar](https://developer.android.com/reference/android/widget/Toolbar.html) - iOS: [UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem?language=objca) +- Windows: [Microsoft.UI.Xaml.Controls.Button](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.button) ### NavigationButton - Android: [android.widget.Toolbar](https://developer.android.com/reference/android/widget/Toolbar.html) - iOS: [UINavigationItem](https://developer.apple.com/documentation/uikit/uinavigationitem?language=objca) +- Windows: [Microsoft.UI.Xaml.Controls.Button](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.button) diff --git a/content/ui/activity-indicator.md b/content/ui/activity-indicator.md index e9e6ad26..2f6f910e 100644 --- a/content/ui/activity-indicator.md +++ b/content/ui/activity-indicator.md @@ -99,3 +99,4 @@ See [EventData](/api/interface/EventData). - Android: [`android.widget.ProgressBar` (indeterminate = true)](https://developer.android.com/reference/android/widget/ProgressBar.html) - iOS: [`UIActivityIndicatorView`](https://developer.apple.com/documentation/uikit/uiactivityindicatorview) +- Windows: [`Microsoft.UI.Xaml.Controls.ProgressRing`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.progressring) diff --git a/content/ui/button.md b/content/ui/button.md index 23bf433c..bc4ad474 100644 --- a/content/ui/button.md +++ b/content/ui/button.md @@ -121,3 +121,4 @@ See [TapGestureEventData](/api/interface/TapGestureEventData). - Android: [`android.widget.Button`](https://developer.android.com/reference/android/widget/Button.html) - iOS: [`UIButton`](https://developer.apple.com/documentation/uikit/uibutton) +- Windows: [`Microsoft.UI.Xaml.Controls.Button`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.button) diff --git a/content/ui/date-picker.md b/content/ui/date-picker.md index 052e2c57..09e194e4 100644 --- a/content/ui/date-picker.md +++ b/content/ui/date-picker.md @@ -201,3 +201,4 @@ See [PropertyChangeData](/api/interface/PropertyChangeData). - Android: [`android.widget.DatePicker`](https://developer.android.com/reference/android/widget/DatePicker.html) - iOS: [`UIDatePicker`](https://developer.apple.com/documentation/uikit/uidatepicker) +- Windows: [`Microsoft.UI.Xaml.Controls.DatePicker`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.datepicker) diff --git a/content/ui/dialogs.md b/content/ui/dialogs.md index 8aa0c104..e398ac06 100644 --- a/content/ui/dialogs.md +++ b/content/ui/dialogs.md @@ -291,3 +291,4 @@ See [login()](/api/#login). - Android: [android.app.AlertDialog.Builder](https://developer.android.com/reference/android/app/AlertDialog.Builder) - iOS: [UIAlertController](https://developer.apple.com/documentation/uikit/uialertcontroller) +- Windows: [`Microsoft.UI.Xaml.Controls.Primitives.Popup`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.popup) (an in-window overlay) diff --git a/content/ui/frame.md b/content/ui/frame.md index 6c719b7b..87ed6053 100644 --- a/content/ui/frame.md +++ b/content/ui/frame.md @@ -371,3 +371,4 @@ If set to `true`, it clears the navigation history backstack. - Android: [`org.nativescript.widgets.ContentLayout`](https://github.com/NativeScript/tns-core-modules-widgets/blob/master/android/widgets/src/main/java/org/nativescript/widgets/ContentLayout.java) - iOS: [`UINavigationController`](https://developer.apple.com/documentation/uikit/uinavigationcontroller) +- Windows: [`Microsoft.UI.Xaml.Controls.Grid`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid) (hosts the navigation bar and the current page) diff --git a/content/ui/html-view.md b/content/ui/html-view.md index 77cbcc7e..417e1408 100644 --- a/content/ui/html-view.md +++ b/content/ui/html-view.md @@ -88,3 +88,4 @@ For additional inherited properties, refer to the [API Reference](/api/class/Htm - Android: [`android.widget.TextView`](https://developer.android.com/reference/android/widget/TextView.html) - iOS: [`UITextView`](https://developer.apple.com/documentation/uikit/uitextview) +- Windows: [`Microsoft.UI.Xaml.Controls.RichTextBlock`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.richtextblock) (supports a subset of HTML: `p`, `br`, `b`/`strong`, `i`/`em`, `u`, `a`, `span`) diff --git a/content/ui/image.md b/content/ui/image.md index 0770d1ba..bfbcc470 100644 --- a/content/ui/image.md +++ b/content/ui/image.md @@ -308,3 +308,4 @@ For additional inherited properties, refer to the [API Reference](/api/class/Ima - Android: [`android.widget.ImageView`](https://developer.android.com/reference/android/widget/ImageView) - iOS: [`UIImageView`](https://developer.apple.com/documentation/uikit/uiimageview) +- Windows: [`Microsoft.UI.Xaml.Controls.Image`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.image) diff --git a/content/ui/label.md b/content/ui/label.md index 5019c7d1..94626de9 100644 --- a/content/ui/label.md +++ b/content/ui/label.md @@ -191,3 +191,4 @@ Emitted when the label text is changed. --> - Android: [`android.widget.TextView`](https://developer.android.com/reference/android/widget/TextView.html) - iOS: [`UILabel`](https://developer.apple.com/documentation/uikit/uilabel) +- Windows: [`Microsoft.UI.Xaml.Controls.TextBlock`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textblock) diff --git a/content/ui/list-picker.md b/content/ui/list-picker.md index f8a16dd8..5ba514e5 100644 --- a/content/ui/list-picker.md +++ b/content/ui/list-picker.md @@ -95,3 +95,4 @@ Emitted when the currently selected item (index) changes. - Android: [`android.widget.NumberPicker`](https://developer.android.com/reference/android/widget/NumberPicker.html) - iOS: [`UIPickerView`](https://developer.apple.com/documentation/uikit/uipickerview) +- Windows: [`Microsoft.UI.Xaml.Controls.ComboBox`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.combobox) diff --git a/content/ui/list-view.md b/content/ui/list-view.md index a0677dea..721c2662 100644 --- a/content/ui/list-view.md +++ b/content/ui/list-view.md @@ -384,3 +384,4 @@ See `SearchEventData` in the API reference for the shape of the event. - Android: [`android.widget.ListView`](https://developer.android.com/reference/android/widget/ListView.html) - iOS: [`UITableView`](https://developer.apple.com/documentation/uikit/uitableview) +- Windows: [`Microsoft.UI.Xaml.Controls.ListView`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview) diff --git a/content/ui/page.md b/content/ui/page.md index 02e94a9a..00fcd2e5 100644 --- a/content/ui/page.md +++ b/content/ui/page.md @@ -454,3 +454,4 @@ See also: [enableEdgeToEdge](/core/utils#enableedgetoedge). - Android: [`org.nativescript.widgets.GridLayout`](https://github.com/NativeScript/NativeScript/blob/master/packages/ui-mobile-base/android/widgets/src/main/java/org/nativescript/widgets/GridLayout.java) - iOS: [`UIViewController`](https://developer.apple.com/documentation/uikit/uiviewcontroller) +- Windows: [`Microsoft.UI.Xaml.Controls.Grid`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid) diff --git a/content/ui/progress.md b/content/ui/progress.md index fabf04a0..025c7b61 100644 --- a/content/ui/progress.md +++ b/content/ui/progress.md @@ -96,3 +96,4 @@ For additional inherited properties, refer to the [API Reference](/api/class/Pro - Android: [`android.widget.ProgressBar` (indeterminate = false)](https://developer.android.com/reference/android/widget/ProgressBar.html) - iOS: [`UIProgressView`](https://developer.apple.com/documentation/uikit/uiprogressview) +- Windows: [`Microsoft.UI.Xaml.Controls.ProgressBar`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.progressbar) diff --git a/content/ui/scroll-view.md b/content/ui/scroll-view.md index 7a89f824..178f34d7 100644 --- a/content/ui/scroll-view.md +++ b/content/ui/scroll-view.md @@ -160,3 +160,4 @@ See [ScrollEventData](/api/interface/ScrollEventData). - Android: [`android.view`](https://developer.android.com/reference/android/view/View.html) - iOS: [`UIScrollView`](https://developer.apple.com/documentation/uikit/uiscrollview) +- Windows: [`Microsoft.UI.Xaml.Controls.ScrollViewer`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.scrollviewer) diff --git a/content/ui/search-bar.md b/content/ui/search-bar.md index bd2f880b..4601b533 100644 --- a/content/ui/search-bar.md +++ b/content/ui/search-bar.md @@ -139,3 +139,4 @@ Emitted when the search input is cleared through the **✗** button in the i - Android: [`android.widget.SearchView`](https://developer.android.com/reference/android/widget/SearchView.html) - iOS: [`UISearchBar`](https://developer.apple.com/documentation/uikit/uisearchbar) +- Windows: [`Microsoft.UI.Xaml.Controls.AutoSuggestBox`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.autosuggestbox) diff --git a/content/ui/segmented-bar.md b/content/ui/segmented-bar.md index 087ad071..9e23f0f4 100644 --- a/content/ui/segmented-bar.md +++ b/content/ui/segmented-bar.md @@ -121,3 +121,4 @@ Emitted when an item in the SegmentedBar is tapped. - Android: [`android.widget.TabHost`](https://developer.android.com/reference/android/widget/TabHost.html) - iOS: [`UISegmentedControl`](https://developer.apple.com/documentation/uikit/uisegmentedcontrol) +- Windows: [`Microsoft.UI.Xaml.Controls.StackPanel`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.stackpanel) of [`Microsoft.UI.Xaml.Controls.Primitives.ToggleButton`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.togglebutton) diff --git a/content/ui/slider.md b/content/ui/slider.md index 17613532..7298fa5c 100644 --- a/content/ui/slider.md +++ b/content/ui/slider.md @@ -99,3 +99,4 @@ See [PropertyChangeData](/api/interface/PropertyChangeData). - Android: [`android.widget.SeekBar`](https://developer.android.com/reference/android/widget/SeekBar.html) - iOS: [`UISlider`](https://developer.apple.com/documentation/uikit/uislider) +- Windows: [`Microsoft.UI.Xaml.Controls.Slider`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.slider) diff --git a/content/ui/split-view.md b/content/ui/split-view.md index aafe20fd..6cde33f5 100644 --- a/content/ui/split-view.md +++ b/content/ui/split-view.md @@ -220,3 +220,4 @@ Emitted whenever the inspector column changes visibility. Payload contains a `da ## Native component - iOS: [`UISplitViewController`](https://developer.apple.com/documentation/uikit/uisplitviewcontroller) +- Windows: [`Microsoft.UI.Xaml.Controls.Grid`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid) (columns for the primary, supplementary and secondary views) diff --git a/content/ui/switch.md b/content/ui/switch.md index 22d0d188..e0c951b6 100644 --- a/content/ui/switch.md +++ b/content/ui/switch.md @@ -103,3 +103,4 @@ See [PropertyChangeData](/api/interface/PropertyChangeData). - Android: [`android.widget.Switch`](https://developer.android.com/reference/android/widget/Switch.html) - iOS: [`UISwitch`](https://developer.apple.com/documentation/uikit/uiswitch) +- Windows: [`Microsoft.UI.Xaml.Controls.ToggleSwitch`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.toggleswitch) diff --git a/content/ui/tab-view.md b/content/ui/tab-view.md index b5839d75..a50648ee 100644 --- a/content/ui/tab-view.md +++ b/content/ui/tab-view.md @@ -295,3 +295,4 @@ tabView.iosBottomAccessory = accessory - Android: [`androidx.viewpager.widget.ViewPager`](https://developer.android.com/reference/androidx/viewpager/widget/ViewPager) - iOS: [`UITabBarController`](https://developer.apple.com/documentation/uikit/uitabbarcontroller) +- Windows: [`Microsoft.UI.Xaml.Controls.Grid`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid) (a tab strip of buttons above the content area) diff --git a/content/ui/text-field.md b/content/ui/text-field.md index bd3f6e07..f7956619 100644 --- a/content/ui/text-field.md +++ b/content/ui/text-field.md @@ -244,3 +244,4 @@ Emitted when the TextField loses focus. - Android: [`android.widget.EditText`](https://developer.android.com/reference/android/widget/EditText.html) - iOS: [`UITextField`](https://developer.apple.com/documentation/uikit/uitextfield) +- Windows: [`Microsoft.UI.Xaml.Controls.TextBox`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textbox) ([`Microsoft.UI.Xaml.Controls.PasswordBox`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.passwordbox) when `secure` is `true`) diff --git a/content/ui/text-view.md b/content/ui/text-view.md index 9ae677be..8e781175 100644 --- a/content/ui/text-view.md +++ b/content/ui/text-view.md @@ -264,3 +264,4 @@ Emitted when the TextView loses focus. - Android: [`android.widget.EditText`](https://developer.android.com/reference/android/widget/EditText.html) - iOS: [`UITextView`](https://developer.apple.com/documentation/uikit/uitextview) +- Windows: [`Microsoft.UI.Xaml.Controls.TextBox`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textbox) (multiline) diff --git a/content/ui/time-picker.md b/content/ui/time-picker.md index c85f0b27..886c1cfa 100644 --- a/content/ui/time-picker.md +++ b/content/ui/time-picker.md @@ -143,3 +143,4 @@ Emitted when the selected time changes. - Android: [`android.widget.TimePicker`](https://developer.android.com/reference/android/widget/TimePicker) - iOS: [`UIDatePicker`](https://developer.apple.com/documentation/uikit/uidatepicker) +- Windows: [`Microsoft.UI.Xaml.Controls.TimePicker`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.timepicker) diff --git a/content/ui/web-view.md b/content/ui/web-view.md index c906ca2f..6a3c63ed 100644 --- a/content/ui/web-view.md +++ b/content/ui/web-view.md @@ -180,3 +180,4 @@ See [LoadEventData](/api/interface/LoadEventData). - Android: [`android.webkit.WebView`](https://developer.android.com/reference/android/webkit/WebView) - iOS: [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview) +- Windows: [`Microsoft.UI.Xaml.Controls.WebView2`](https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.webview2)