Skip to content

Commit

Permalink
Merge pull request #6448 from frenzibyte/ios-export-files
Browse files Browse the repository at this point in the history
Add support for presenting/opening files on iOS
  • Loading branch information
peppy authored Dec 11, 2024
2 parents ebb2b33 + 7c7529d commit f5900ab
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 11 deletions.
61 changes: 61 additions & 0 deletions osu.Framework.iOS/IOSFilePresenter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.IO;
using Foundation;
using UIKit;
using UniformTypeIdentifiers;

namespace osu.Framework.iOS
{
internal class IOSFilePresenter : UIDocumentInteractionControllerDelegate
{
private readonly IOSWindow window;
private readonly UIDocumentInteractionController viewController = new UIDocumentInteractionController();

internal IOSFilePresenter(IOSWindow window)
{
this.window = window;
}

public bool OpenFile(string filename)
{
setupViewController(filename);

if (viewController.PresentPreview(true))
return true;

var gameView = window.UIWindow.RootViewController!.View!;
return viewController.PresentOpenInMenu(gameView.Bounds, gameView, true);
}

public bool PresentFile(string filename)
{
setupViewController(filename);

var gameView = window.UIWindow.RootViewController!.View!;
return viewController.PresentOptionsMenu(gameView.Bounds, gameView, true);
}

private void setupViewController(string filename)
{
var url = NSUrl.FromFilename(filename);

viewController.Url = url;
viewController.Delegate = this;

if (OperatingSystem.IsIOSVersionAtLeast(14))
viewController.Uti = UTType.CreateFromExtension(Path.GetExtension(filename))?.Identifier ?? UTTypes.Data.Identifier;
}

public override UIViewController ViewControllerForPreview(UIDocumentInteractionController controller) => window.UIWindow.RootViewController!;

public override void WillBeginSendingToApplication(UIDocumentInteractionController controller, string? application)
{
// this path is triggered when a user opens the presented document in another application,
// the menu does not dismiss afterward and locks the game indefinitely. dismiss it manually.
viewController.DismissMenu(true);
}
}
}
13 changes: 10 additions & 3 deletions osu.Framework.iOS/IOSGameHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ namespace osu.Framework.iOS
{
public class IOSGameHost : SDLGameHost
{
private IOSFilePresenter presenter = null!;

public IOSGameHost()
: base(string.Empty)
{
}

protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new IOSWindow(preferredSurface, Options.FriendlyGameName);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface)
{
var window = new IOSWindow(preferredSurface, Options.FriendlyGameName);
presenter = new IOSFilePresenter(window);
return window;
}

protected override void SetupConfig(IDictionary<FrameworkSetting, object> defaultOverrides)
{
Expand All @@ -42,9 +49,9 @@ protected override void SetupConfig(IDictionary<FrameworkSetting, object> defaul

public override Storage GetStorage(string path) => new IOSStorage(path, this);

public override bool OpenFileExternally(string filename) => false;
public override bool OpenFileExternally(string filename) => presenter.OpenFile(filename);

public override bool PresentFileExternally(string filename) => false;
public override bool PresentFileExternally(string filename) => presenter.PresentFile(filename);

public override void OpenUrlExternally(string url)
{
Expand Down
18 changes: 10 additions & 8 deletions osu.Framework.iOS/IOSWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ namespace osu.Framework.iOS
{
internal class IOSWindow : SDL3MobileWindow
{
private UIWindow? window;
private UIWindow? uiWindow;

public UIWindow UIWindow => uiWindow!;

public override Size Size
{
Expand All @@ -27,7 +29,7 @@ protected set
{
base.Size = value;

if (window != null)
if (uiWindow != null)
updateSafeArea();
}
}
Expand All @@ -43,7 +45,7 @@ public override void Create()

base.Create();

window = Runtime.GetNSObject<UIWindow>(WindowHandle);
uiWindow = Runtime.GetNSObject<UIWindow>(WindowHandle);
updateSafeArea();
}

Expand Down Expand Up @@ -73,14 +75,14 @@ private static void runFrame(IntPtr userdata)

private void updateSafeArea()
{
Debug.Assert(window != null);
Debug.Assert(uiWindow != null);

SafeAreaPadding.Value = new MarginPadding
{
Top = (float)window.SafeAreaInsets.Top * Scale,
Left = (float)window.SafeAreaInsets.Left * Scale,
Bottom = (float)window.SafeAreaInsets.Bottom * Scale,
Right = (float)window.SafeAreaInsets.Right * Scale,
Top = (float)uiWindow.SafeAreaInsets.Top * Scale,
Left = (float)uiWindow.SafeAreaInsets.Left * Scale,
Bottom = (float)uiWindow.SafeAreaInsets.Bottom * Scale,
Right = (float)uiWindow.SafeAreaInsets.Right * Scale,
};
}
}
Expand Down

0 comments on commit f5900ab

Please sign in to comment.