-
Notifications
You must be signed in to change notification settings - Fork 425
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6445 from frenzibyte/ios-document-browser
Implement system-provided file selection display on iOS
- Loading branch information
Showing
11 changed files
with
285 additions
and
62 deletions.
There are no files selected for viewing
30 changes: 29 additions & 1 deletion
30
osu.Framework.Tests/Visual/UserInterface/TestSceneFileSelector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,46 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using System.IO; | ||
using osu.Framework.Allocation; | ||
using osu.Framework.Graphics; | ||
using osu.Framework.Graphics.Sprites; | ||
using osu.Framework.Graphics.Textures; | ||
using osu.Framework.Graphics.UserInterface; | ||
using osu.Framework.IO.Stores; | ||
using osu.Framework.Platform; | ||
|
||
namespace osu.Framework.Tests.Visual.UserInterface | ||
{ | ||
public partial class TestSceneFileSelector : FrameworkTestScene | ||
{ | ||
private BasicFileSelector selector = null!; | ||
|
||
[Resolved] | ||
private GameHost host { get; set; } = null!; | ||
|
||
[BackgroundDependencyLoader] | ||
private void load() | ||
{ | ||
Add(new BasicFileSelector { RelativeSizeAxes = Axes.Both }); | ||
Add(selector = new BasicFileSelector(null, new[] { ".png", ".jpg", ".jpeg" }) { RelativeSizeAxes = Axes.Both }); | ||
} | ||
|
||
protected override void LoadComplete() | ||
{ | ||
base.LoadComplete(); | ||
|
||
selector.CurrentFile.BindValueChanged(f => | ||
{ | ||
using var resources = new StorageBackedResourceStore(host.GetStorage(f.NewValue.Directory!.FullName)); | ||
using var store = new TextureStore(host.Renderer, host.CreateTextureLoaderStore(resources)); | ||
|
||
Add(new Sprite | ||
{ | ||
FillMode = FillMode.Fit, | ||
RelativeSizeAxes = Axes.Both, | ||
Texture = store.Get(Path.GetFileName(f.NewValue.FullName)), | ||
}); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using osu.Framework.Platform; | ||
using UIKit; | ||
|
||
namespace osu.Framework.iOS | ||
{ | ||
/// <summary> | ||
/// Interface representation of the game window on the iOS platform. | ||
/// </summary> | ||
public interface IIOSWindow : IWindow | ||
{ | ||
/// <summary> | ||
/// The underlying <see cref="UIWindow"/> associated to this window. | ||
/// </summary> | ||
UIWindow UIWindow { get; } | ||
|
||
/// <summary> | ||
/// The <see cref="UIViewController"/> presenting this window's content. | ||
/// </summary> | ||
UIViewController ViewController { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Runtime.Versioning; | ||
using Foundation; | ||
using osu.Framework.Platform; | ||
using UIKit; | ||
using UniformTypeIdentifiers; | ||
|
||
namespace osu.Framework.iOS | ||
{ | ||
[SupportedOSPlatform("ios14.0")] | ||
public class IOSFileSelector : UIDocumentPickerDelegate, ISystemFileSelector | ||
{ | ||
public event Action<FileInfo>? Selected; | ||
|
||
private readonly IIOSWindow window; | ||
|
||
private readonly UIDocumentPickerViewController documentPicker; | ||
|
||
public IOSFileSelector(IIOSWindow window, string[] allowedExtensions) | ||
{ | ||
this.window = window; | ||
|
||
UTType[] utTypes; | ||
|
||
if (allowedExtensions.Length == 0) | ||
utTypes = new[] { UTTypes.Data }; | ||
else | ||
{ | ||
utTypes = new UTType[allowedExtensions.Length]; | ||
|
||
for (int i = 0; i < allowedExtensions.Length; i++) | ||
{ | ||
string extension = allowedExtensions[i]; | ||
|
||
var type = UTType.CreateFromExtension(extension.Replace(".", string.Empty)); | ||
if (type == null) | ||
throw new InvalidOperationException($"System failed to recognise extension \"{extension}\" while preparing the file selector.\n"); | ||
|
||
utTypes[i] = type; | ||
} | ||
} | ||
|
||
// files must be provided as copies, as they may be originally located in places that cannot be accessed freely (aka. iCloud Drive). | ||
// we can acquire access to those files via startAccessingSecurityScopedResource but we must know when the game has finished using them. | ||
// todo: refactor FileSelector/DirectorySelector to be aware when the game finished using a file/directory. | ||
documentPicker = new UIDocumentPickerViewController(utTypes, true); | ||
documentPicker.Delegate = this; | ||
} | ||
|
||
public void Present() | ||
{ | ||
UIApplication.SharedApplication.InvokeOnMainThread(() => | ||
{ | ||
window.ViewController.PresentViewController(documentPicker, true, null); | ||
}); | ||
} | ||
|
||
public override void DidPickDocument(UIDocumentPickerViewController controller, NSUrl url) | ||
=> Selected?.Invoke(new FileInfo(url.Path!)); | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
documentPicker.Dispose(); | ||
base.Dispose(disposing); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.