Skip to content

Commit

Permalink
Refactoring MediaPicker on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
dimonovdd authored Apr 27, 2021
1 parent bb1982d commit 8e2013f
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 185 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
using System.IO;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Xamarin.MediaGallery
{
public interface IMediaFile
public interface IMediaFile : IDisposable
{
string FileName { get; }
string FileNameWithoutExtension { get; }

string Extension { get; }

string ContentType { get; }

MediaFileType? Type { get; }

Task<Stream> OpenReadAsync();
}
}
}
14 changes: 10 additions & 4 deletions MediaGallery/MediaFile/MediaFile.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@

namespace Xamarin.MediaGallery
{
public partial class MediaFile
internal partial class MediaFile
{
readonly Uri uri;

internal MediaFile(string fileName, Uri uri)
{
FileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
Extension = Path.GetExtension(fileName)?.TrimStart('.');
Extension = Path.GetExtension(fileName);
ContentType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(Extension);
openReadAsync =
() => Task.FromResult(Platform.AppActivity.ContentResolver.OpenInputStream(uri));
this.uri = uri;
}

Task<Stream> PlatformOpenReadAsync()
=> Task.FromResult(Platform.AppActivity.ContentResolver.OpenInputStream(uri));

void PlatformDispose() { }
}
}
71 changes: 63 additions & 8 deletions MediaGallery/MediaFile/MediaFile.ios.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,75 @@
using System;
using System.IO;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Foundation;
using MobileCoreServices;
using UIKit;

namespace Xamarin.MediaGallery
{
public partial class MediaFile
internal partial class MediaFile
{
internal static MediaFile Create(string fileName, Func<Task<Stream>> openReadAsync, string typeId, string extension = null)
protected virtual Task<Stream> PlatformOpenReadAsync()
=> Task.FromResult<Stream>(null);

protected virtual void PlatformDispose() { }

protected string GetExtension(string identifier)
=> UTType.CopyAllTags(identifier, UTType.TagClassFilenameExtension)?.FirstOrDefault();

protected string GetMIMEType(string identifier)
=> UTType.CopyAllTags(identifier, UTType.TagClassMIMEType)?.FirstOrDefault();
}

internal class PHPickerFile : MediaFile
{
readonly string identifier;
NSItemProvider provider;

internal PHPickerFile(NSItemProvider provider)
{
this.provider = provider;
FileNameWithoutExtension = provider?.SuggestedName;
identifier = provider?.RegisteredTypeIdentifiers?.FirstOrDefault();

if (string.IsNullOrWhiteSpace(identifier))
return;

Extension = GetExtension(identifier);
ContentType = GetMIMEType(identifier);
}

protected override async Task<Stream> PlatformOpenReadAsync()
=> (await provider?.LoadDataRepresentationAsync(identifier))?.AsStream();

protected override void PlatformDispose()
{
typeId ??= UTType.CreatePreferredIdentifier(UTType.TagClassFilenameExtension, extension, null);
extension ??= UTType.CopyAllTags(typeId, UTType.TagClassFilenameExtension)?.FirstOrDefault();
var mimeType = UTType.CopyAllTags(typeId, UTType.TagClassMIMEType).FirstOrDefault();
provider?.Dispose();
provider = null;
base.PlatformDispose();
}
}

internal class UIDocumentFile : MediaFile
{
UIDocument document;

return new MediaFile(fileName, extension, mimeType, openReadAsync);
internal UIDocumentFile(NSUrl assetUrl)
{
document = new UIDocument(assetUrl);
Extension = document.FileUrl.PathExtension;
ContentType = GetMIMEType(document.FileType);
FileNameWithoutExtension = document.LocalizedName;
}

protected override Task<Stream> PlatformOpenReadAsync()
=> Task.FromResult<Stream>(File.OpenRead(document.FileUrl.Path));

protected override void PlatformDispose()
{
document?.Dispose();
document = null;
base.PlatformDispose();
}
}
}
14 changes: 14 additions & 0 deletions MediaGallery/MediaFile/MediaFile.netstandard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.IO;
using System.Threading.Tasks;

namespace Xamarin.MediaGallery
{
internal partial class MediaFile : IMediaFile
{
Task<Stream> PlatformOpenReadAsync()
=> throw MediaGallery.NotSupportedOrImplementedException;

void PlatformDispose()
=> throw MediaGallery.NotSupportedOrImplementedException;
}
}
31 changes: 14 additions & 17 deletions MediaGallery/MediaFile/MediaFile.shared.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
using System;
using System.IO;
using System.IO;
using System.Threading.Tasks;

namespace Xamarin.MediaGallery
{
public partial class MediaFile : IMediaFile
internal partial class MediaFile : IMediaFile
{
readonly Func<Task<Stream>> openReadAsync;
private string extension;

internal MediaFile(string fileName, string extension, string contentType, Func<Task<Stream>> openReadAsync)
public string FileNameWithoutExtension { get; protected internal set; }

public string Extension
{
FileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
Extension = extension.TrimStart('.');
ContentType = contentType.ToLower();
this.openReadAsync = openReadAsync;
get => extension;
protected internal set
=> extension = value?.TrimStart('.')?.ToLower();
}

public string FileName => $"{FileNameWithoutExtension}.{Extension}";

public string FileNameWithoutExtension { get; }

public string Extension { get; }

public string ContentType { get; }
public string ContentType { get; protected internal set; }

public MediaFileType? Type => ContentType.StartsWith("image")
? MediaFileType.Image
Expand All @@ -31,6 +25,9 @@ internal MediaFile(string fileName, string extension, string contentType, Func<T
: (MediaFileType?)null;

public Task<Stream> OpenReadAsync()
=> openReadAsync?.Invoke();
=> PlatformOpenReadAsync();

public void Dispose()
=> PlatformDispose();
}
}
11 changes: 1 addition & 10 deletions MediaGallery/MediaGallery.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<AssemblyFileVersion>1.0.0.0</AssemblyFileVersion>
<Version>1.0.0.0</Version>
<PackageVersion>1.0.0.0-alpha001</PackageVersion>
<PackageVersion>1.0.0.0-alpha003</PackageVersion>
<Authors>dimonovdd</Authors>
<Owners>dimonovdd</Owners>
<PackageProjectUrl>https://github.com/dimonovdd/Xamarin.MediaGallery</PackageProjectUrl>
Expand Down Expand Up @@ -41,12 +41,6 @@
<Compile Include="**\*.shared.cs" />
<Compile Include="**\*.shared.*.cs" />
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
<Compile Include="MediaFile\IMediaFile.cs">
<SubType></SubType>
</Compile>
<Compile Include="MediaPickResult\MediaPickResult.shared.cs">
<SubType></SubType>
</Compile>
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
<Compile Include="**\*.netstandard.cs" />
Expand All @@ -60,7 +54,4 @@
<Compile Include="**\*.ios.*.cs" />
<Compile Include="**\*.ios.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="MediaPickResult\" />
</ItemGroup>
</Project>
8 changes: 7 additions & 1 deletion MediaGallery/MediaGallery/MediaGallery.ios.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using UIKit;
using System;
using UIKit;
using Xamarin.Essentials;

namespace Xamarin.MediaGallery
{
public static partial class MediaGallery
{
internal static bool HasOSVersion(int major) =>
UIDevice.CurrentDevice.CheckSystemVersion(major, 0);

static UIViewController GetCurrentUIViewController()
=> Platform.GetCurrentUIViewController()
?? throw new InvalidOperationException("Could not find current view controller.");
}
}
2 changes: 1 addition & 1 deletion MediaGallery/MediaGallery/MediaGallery.netstandard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static Task PlatformSaveAsync(MediaFileType type, string filePath)
static Task PlatformSaveAsync(MediaFileType type, Stream fileStream, string fileName)
=> throw NotSupportedOrImplementedException;

static Exception NotSupportedOrImplementedException
internal static Exception NotSupportedOrImplementedException
=> new NotImplementedException("This functionality is not implemented in the portable version of this assembly. " +
"You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.");
}
Expand Down
Loading

0 comments on commit 8e2013f

Please sign in to comment.