Skip to content

Commit

Permalink
Merge pull request unoplatform#326 from unoplatform/dev/jela/merge-ma…
Browse files Browse the repository at this point in the history
…ster

merge from master
  • Loading branch information
jeromelaban authored Feb 19, 2024
2 parents c3eeaf8 + 2a88dc4 commit 7194f4c
Show file tree
Hide file tree
Showing 205 changed files with 5,428 additions and 2,279 deletions.
12 changes: 6 additions & 6 deletions License.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# Uno Platform

Copyright (c) Uno Platform Inc.

All rights reserved.

# Apache 2.0 License

Apache License
Expand Down Expand Up @@ -207,3 +201,9 @@ All rights reserved.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

# Uno Platform

Copyright (c) Uno Platform Inc.

All rights reserved.
25 changes: 14 additions & 11 deletions doc/articles/features/windows-storage-pickers.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,19 @@ On some platforms, you can further customize the file-picking experience by util
| Feature | UWP | WebAssembly | Android | iOS | macOS | WPF | GTK |
|-------------------------|------|-------------|---------|-------|-------|-----|-----|
| SuggestedFileName ||||||||
| SuggestedStartLocation || ✔ (1) | 💬 | ✔ (3) ||||
| SuggestedStartLocation || ✔ (1) | 💬 (4) | ✔ (3) ||||
| SettingsIdentifier || ✔ (1) ||||||

*(1) - Only for the native file pickers - see WebAssembly section below*\
*(2) - For FileOpenPicker, VideosLibrary and PicturesLibrary are used to apply `image/*` and `video/*` filters*\
*(3) - PicturesLibrary opens the picture library with the image picker controller*
*(3) - PicturesLibrary opens the picture library with the image picker controller*\
*(4) - See Android section below*

On platforms where the additional features are not supported yet, setting them will not have any effect.

## Uno.WinUI-specific Initialization

If you are using Uno.WinUI (Windows App SDK-based form of Uno Platform), you need to make sure the pickers are initialized for the current window, otherwise the code would fail on Windows. This is done using `WinRT.Interop` and is required for all file and folder pickers. For example, in case of `FileOpenPicker`:
If you are using Uno.WinUI (Windows App SDK-based form of Uno Platform), you need to make sure the pickers are initialized for the current window, otherwise the code would fail on Windows. This is done using `WinRT.Interop` and it is required for all file and folder pickers. For example, in the case of `FileOpenPicker`:

```csharp
var picker = new FileOpenPicker();
Expand Down Expand Up @@ -208,7 +209,7 @@ For iOS and macOS, `UTType` is utilized for the same purpose. Here you can provi
Uno.WinRTFeatureConfiguration.FileTypes.FileTypeToUTTypeMapping.Add(".myextension", "my.custom.UTType");
```

Custom Uniform Type Identifiers must be declared in the `info.plist` of your iOS and macOS application. See a full example of this in [Uniform Type Identifiers Overview from Apple documentation](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_declare/understand_utis_declare.html).
Custom Uniform Type Identifiers must be declared in the `info.plist` of your iOS and macOS applications. See a full example of this in [Uniform Type Identifiers Overview from Apple documentation](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_declare/understand_utis_declare.html).

## WebAssembly

Expand All @@ -226,15 +227,15 @@ The most powerful picker implementation on WebAssembly uses the <a href="https:/

File System Access API pickers allow direct access to the picked files and folders. This means that any modifications the user does to the files are persisted on the target file system.

However, writing to the target file system is limited, so when a write-stream is opened for a file, Uno Platform creates a copy of the file in temporary storage and your changes are applied to this temporary file instead. When your file stream is then flushed, closed, or disposed of, the changes are written to the source file and the temporary file is discarded.
However, writing to the target file system is limited, so when a write-stream is opened for a file, Uno Platform creates a copy of the file in temporary storage, and your changes are applied to this temporary file instead. When your file stream is then flushed, closed, or disposed of, the changes are written to the source file, and the temporary file is discarded.

### Download/upload pickers

In case the **File System Access API** is not available in the browser, Uno Platform also offers a fallback to "download" and "upload" experiences.

For the upload picker, the browser triggers a file picker dialog and Uno Platform then copies the selected files into temporary storage of the app. The `StorageFile` instance you receive is private for your application and the changes are not reflected in the original file. To save the changes, you need to trigger the "download picker".

For the download picker, the experience requires the use of [`CachedFileManager`](https://learn.microsoft.com/uwp/api/Windows.Storage.CachedFileManager). Triggering `PickSaveFileAsync` does not actually show the download picker to the user. Instead, only a temporary file is created to allow you to write any content. Afterwards, calling `CompleteUpdatesAsync` opens the download dialog which allows the user to save the file.
For the download picker, the experience requires the use of [`CachedFileManager`](https://learn.microsoft.com/uwp/api/Windows.Storage.CachedFileManager). Triggering `PickSaveFileAsync` does not actually show the download picker to the user. Instead, only a temporary file is created to allow you to write any content. Afterward, calling `CompleteUpdatesAsync` opens the download dialog, which allows the user to save the file.

The `CachedFileManager` class works transparently with both the **Download picker** and the **File System Access API**, which means you can write a single snippet of code that handles both scenarios correctly:

Expand Down Expand Up @@ -338,19 +339,21 @@ Browsers generally treat file opening/saving operations as sensitive operations,
SecurityError: Failed to execute 'showSaveFilePicker' on 'Window': Must be handling a user gesture to show a file picker.
```

This generally means that the Uno file picking APIs have been invoked without an explicit user interaction, or have been rescheduled from the original user interaction callback (e.g. using `DispatcherQueue.TryRun()` inside a `Button.Click` handler to open a picker).
This generally means that the Uno file picking APIs have been invoked without explicit user interaction or have been rescheduled from the original user interaction callback (e.g., using `DispatcherQueue.TryRun()` inside a `Button.Click` handler to open a picker).

## Android

Files picked from file pickers on Android are provided by the *Storage Access Framework API*. Due to its limitations, it is not possible to write to existing file in-place. Instead, Uno Platform creates a copy of the file in temporary storage and your changes are applied to this temporary file instead. When your file stream is then flushed, closed, or disposed of, the changes are written to the source file and the temporary file is discarded.
Files picked from file pickers on Android are provided by the *Storage Access Framework API*. Due to its limitations, it is not possible to write to existing file in-place. Instead, Uno Platform creates a copy of the file in temporary storage and your changes are applied to this temporary file instead. When your file stream is then flushed, closed, or disposed of, the changes are written to the source file, and the temporary file is discarded.

The `FileSavePicker` API which uses `ACTION_CREATE_DOCUMENT` on Android has various limitations. To allow for the best possible compatibility across different Android versions, you should always add your file type extension to `FileTypeChoices`, and if possible provide only one such file type. In addition, if the `SuggestedFileName` or the user-typed file name matches an existing file, the resulting file will be renamed with `(1)` in the name, e.g. `test.txt` will become `test (1).txt` and the existing file will not be overwritten. However, if the user explicitly taps an existing file in the file browser, the system will show a dialog allowing the app to overwrite the existing file. This inconsistent behavior is caused by Android itself, so there is unfortunately no way to work around it from our side. See [this issue](https://issuetracker.google.com/issues/37136466) for more information.
The `SuggestedStartLocation` property has no effect on certain Android devices, and the file picker will always open in the root directory of the internal storage. When using VideosLibrary or PicturesLibrary locations, the file picker will open the picture library with the image picker controller. Still, for those devices that do not support it, it will open the root directory of the internal storage and suggest all the applications that can handle file types.

The `FileSavePicker` API, which uses `ACTION_CREATE_DOCUMENT` on Android, has various limitations. To allow for the best possible compatibility across different Android versions, you should always add your file type extension to `FileTypeChoices`, and, if possible, provide only one such file type. In addition, if the `SuggestedFileName` or the user-typed file name matches an existing file, the resulting file will be renamed with `(1)` in the name, e.g., `test.txt` will become `test (1).txt` and the existing file will not be overwritten. However, if the user explicitly taps an existing file in the file browser, the system will show a dialog allowing the app to overwrite the existing file. This inconsistent behavior is caused by Android itself, so there is, unfortunately, no way to work around it from our side. See [this issue](https://issuetracker.google.com/issues/37136466) for more information.

## iOS

iOS does not offer a built-in `FileSavePicker` experience. Luckily it is possible to implement this functionality for example using a combination of a `FolderPicker` and `ContentDialog`.
iOS does not offer a built-in `FileSavePicker` experience. Luckily, it is possible to implement this functionality, for example, using a combination of a `FolderPicker` and `ContentDialog`.

To provide your own custom implementation, create a class that implements the `IFileSavePickerExtension` which is only available on iOS. This class must have a `public` constructor with a `object` parameter. This will actually be an instance of `FileSavePicker` when invoked later. Then implement the `PickSaveFileAsync` method:
To provide your own custom implementation, create a class that implements the `IFileSavePickerExtension`, which is only available on iOS. This class must have a `public` constructor with an `object` parameter. This will actually be an instance of `FileSavePicker` when invoked later. Then implement the `PickSaveFileAsync` method:

```csharp
#if __IOS__
Expand Down
26 changes: 21 additions & 5 deletions doc/articles/upgrading-nuget-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,28 @@ It typically looks similar to this:
```

> [!IMPORTANT]
> At this time the NuGet Manager in Visual Studio 2022 does not parse or manage Sdks provided by NuGet. If you would like to see this feature added, please be sure to provide your [feedback or upvote this issue](https://github.com/NuGet/Home/issues/13127).
> In Visual Studio 2022, once the Uno Version is updated, you'll need to close and reopen the solution or restart Visual Studio for the change to take effect.
>
> At this time, the NuGet package Manager does not parse or manage Sdks provided by NuGet. If you would like to see this feature added, please be sure to provide your [feedback or upvote this issue](https://github.com/NuGet/Home/issues/13127).
To update the version, pick the latest stable build from the [Uno.WinUI](https://www.nuget.org/packages/Uno.WinUI) package with either:
To find the version to update to, pick the latest stable build from the [Uno.WinUI](https://www.nuget.org/packages/Uno.WinUI) package with either:

- [Uno.WinUI in Nuget Package Explorer](https://nuget.info)
- When using Visual Studio 2022, use the NuGet Package Manager
- Use [`dotnet outdated`](https://github.com/dotnet-outdated/dotnet-outdated):
- Install the tool using:

```dotnetcli
dotnet tool install --global dotnet-outdated-tool
```

- Then, at the root of the solution, run the tool with:

```dotnetcli
dotnet outdated
```

- When available, the tool will provide the versions which can be updated.
- [Uno.WinUI in Nuget Package Explorer](https://nuget.info/packages/Uno.WinUI)
- [Uno.WinUI in nuget.org](https://www.nuget.org/packages/Uno.WinUI)
- The latest Uno.WinUI package in the Visual Studio 2022 NuGet Package Manager.

Once the version has been chosen, change the `global.json` line with `"Uno.Sdk"` to use the newer version of Uno Platform.
Once the version has been chosen, change the `global.json` line with `"Uno.Sdk"` to use the newer version of Uno Platform. If you're running Visual Studio 2022, make sure to close/reopen the solution or restart the IDE.
2 changes: 1 addition & 1 deletion doc/import_external_docs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $external_docs = @{
"uno.wasm.bootstrap" = "5ef2048d98df307c738186a5339eedcc4665be72"
"uno.themes" = "6ce3ce8b0f61a7a017893541e1dd901ab04c906e"
"uno.toolkit.ui" = "d7eaf4b923b81e5386a5ceb0aff4ae4014239ffa"
"uno.check" = "251e61153ef936748520ecbaa99e45e10970bab1"
"uno.check" = "0350ba1b78ee7488d88f093e8f92cc4d9cb055f5"
"uno.xamlmerge.task" = "7e8ffef206e87dfea90c53805c45e93a7d8c0b46"
"figma-docs" = "0e204b21d437478d89845b6b0edb212c3f482cbc"
"uno.resizetizer" = "3eec4aad0b7b3480ec6c2a121911ffde844fc4f8"
Expand Down
2 changes: 1 addition & 1 deletion src/AddIns/Uno.UI.MediaPlayer.Skia.Gtk/VideoView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ struct Native
/// </summary>
public VideoView()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
if (OperatingSystem.IsLinux())
{
#pragma warning disable CA1806 // Do not ignore method results
Native.XInitThreads();
Expand Down
4 changes: 2 additions & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>

<Import Project="$(SolutionDir)\crosstargeting_override.props" Condition="exists('$(SolutionDir)\crosstargeting_override.props')" />
<Import Project="crosstargeting_override.props" Condition="exists('crosstargeting_override.props')" />

<PropertyGroup>
<DebugType>portable</DebugType>
Expand Down Expand Up @@ -73,7 +73,7 @@
</PropertyGroup>

<PropertyGroup>
<MicrosoftNetCompilersToolsetVersion>4.8.0</MicrosoftNetCompilersToolsetVersion>
<MicrosoftNetCompilersToolsetVersion>4.9.0-3.final</MicrosoftNetCompilersToolsetVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
7 changes: 5 additions & 2 deletions src/SamplesApp/SamplesApp.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ override void OnLaunched(LaunchActivatedEventArgs e)

HandleLaunchArguments(e);

if (SampleControl.Presentation.SampleChooserViewModel.Instance.CurrentSelectedSample is null)
if (SampleControl.Presentation.SampleChooserViewModel.Instance is { } vm && vm.CurrentSelectedSample is null)
{
SampleControl.Presentation.SampleChooserViewModel.Instance.SetSelectedSample(CancellationToken.None, "Playground", "Playground");
vm.SetSelectedSample(CancellationToken.None, "Playground", "Playground");
}

Console.WriteLine("Done loading " + sw.Elapsed);
Expand Down Expand Up @@ -525,7 +525,10 @@ static void ParseCommandLineFeatureFlags()
}
}

#pragma warning disable SYSLIB1045
var regex = new Regex(@"^--FeatureConfiguration\.(\w+\.\w+)=(.+)$");
#pragma warning restore SYSLIB1045

foreach (var arg in commandLineArgs.Skip(1))
{
var match = regex.Match(arg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<_XcodeBuildArgs Condition="'$(Configuration)'=='Debug'">build-for-testing -scheme UnoNativeMac</_XcodeBuildArgs>
</PropertyGroup>

<Target Name="BuildUnoNativeMac" BeforeTargets="Compile">
<Target Name="BuildUnoNativeMac" BeforeTargets="Compile" Condition="$([MSBuild]::IsOsPlatform('OSX'))">
<Exec Command="$(MSBuildThisFileDirectory)../../Uno.UI.Runtime.Skia.MacOS/UnoNativeMac/build.sh $(_XcodeBuildArgs)" WorkingDirectory="$(MSBuildThisFileDirectory)../../Uno.UI.Runtime.Skia.MacOS/UnoNativeMac/" />
<Copy
SourceFiles="$(MSBuildThisFileDirectory)../../Uno.UI.Runtime.Skia.MacOS/UnoNativeMac/build/$(Configuration)/libUnoNativeMac.dylib"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static SampleControlUITestBase()
private static void TryInitializeSkiaSharpLoader()
{
if (AppInitializer.GetLocalPlatform() == Platform.Browser
&& !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
&& !OperatingSystem.IsWindows())
{
#if DEBUG
Console.WriteLine("Initializing SkiaSharp loader");
Expand Down
Loading

0 comments on commit 7194f4c

Please sign in to comment.