| File: Share\Share.shared.cs | Web Access |
| Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials) |
#nullable enable using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Maui.Graphics; using Microsoft.Maui.Storage; namespace Microsoft.Maui.ApplicationModel.DataTransfer { /// <summary> /// The Share API enables an application to share data such as text and web links to other applications on the device. /// </summary> public interface IShare { /// <summary> /// Show the operating systems user interface to share text. /// </summary> /// <param name="request">A <see cref="ShareTextRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> Task RequestAsync(ShareTextRequest request); /// <summary> /// Show the operating system's user interface to share a single file. /// </summary> /// <param name="request">A <see cref="ShareFileRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> Task RequestAsync(ShareFileRequest request); /// <summary> /// Show the operating system's user interface to share multiple files. /// </summary> /// <param name="request">A <see cref="ShareMultipleFilesRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> Task RequestAsync(ShareMultipleFilesRequest request); } /// <summary> /// The Share API enables an application to share data such as text and web links to other applications on the device. /// </summary> public static partial class Share { /// <summary> /// Show the operating system's user interface to share text. /// </summary> /// <param name="text">The text to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(string text) => Current.RequestAsync(text); /// <summary> /// Show the operating system's user interface to share text. /// </summary> /// <param name="text">The text to share.</param> /// <param name="title">The title to display on the operating system share dialog.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(string text, string title) => Current.RequestAsync(text, title); /// <summary> /// Show the operating system's user interface to share text. /// </summary> /// <param name="request">A <see cref="ShareTextRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(ShareTextRequest request) => Current.RequestAsync(request); /// <summary> /// Show the operating system's user interface to share a single file. /// </summary> /// <param name="request">A <see cref="ShareFileRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(ShareFileRequest request) => Current.RequestAsync(request); /// <summary> /// Show the operating system's user interface to share multiple files. /// </summary> /// <param name="request">A <see cref="ShareMultipleFilesRequest"/> object containing the details of the data to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(ShareMultipleFilesRequest request) => Current.RequestAsync(request); static IShare Current => ApplicationModel.DataTransfer.Share.Default; static IShare? defaultImplementation; /// <summary> /// Provides the default implementation for static usage of this API. /// </summary> public static IShare Default => defaultImplementation ??= new ShareImplementation(); internal static void SetDefault(IShare? implementation) => defaultImplementation = implementation; } /// <summary> /// Concrete implementation of the <see cref="IShare"/> APIs. /// </summary> partial class ShareImplementation : IShare { /// <inheritdoc cref="IShare.RequestAsync(ShareTextRequest)"/> /// <exception cref="ArgumentNullException">Thrown when <paramref name="request"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentException">Thrown when <see cref="ShareTextRequest.Text"/> and <see cref="ShareTextRequest.Uri"/> are both <see langword="null"/> or empty.</exception> public Task RequestAsync(ShareTextRequest request) { if (request == null) throw new ArgumentNullException(nameof(request)); if (string.IsNullOrEmpty(request.Text) && string.IsNullOrEmpty(request.Uri)) throw new ArgumentException($"Both the {nameof(request.Text)} and {nameof(request.Uri)} are invalid. Make sure to include at least one of them in the request."); return PlatformRequestAsync(request); } /// <inheritdoc cref="IShare.RequestAsync(ShareFileRequest)"/> /// <exception cref="ArgumentNullException">Thrown when <paramref name="request"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentException">Thrown when <see cref="ShareFileRequest.File"/> is <see langword="null"/>.</exception> public Task RequestAsync(ShareFileRequest request) { if (request == null) throw new ArgumentNullException(nameof(request)); if (request.File == null) throw new ArgumentException(FileNullException(nameof(request.File))); return PlatformRequestAsync(request); } /// <inheritdoc cref="IShare.RequestAsync(ShareMultipleFilesRequest)"/> /// <exception cref="ArgumentNullException">Thrown when <paramref name="request"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentException">Thrown when <see cref="ShareMultipleFilesRequest.Files"/> is <see langword="null"/> or empty or one of the entries in <see cref="ShareMultipleFilesRequest.Files"/> is <see langword="null"/>.</exception> public Task RequestAsync(ShareMultipleFilesRequest request) { if (request == null) throw new ArgumentNullException(nameof(request)); if (!(request.Files?.Count > 0)) throw new ArgumentException(FileNullException(nameof(request.Files))); if (request.Files.Any(file => file == null)) throw new ArgumentException(FileNullException(nameof(request.Files))); return PlatformRequestAsync(request); } static string FileNullException(string file) => $"The {file} parameter in the request files is invalid"; } /// <summary> /// Static class with extension methods for the <see cref="IShare"/> APIs. /// </summary> public static class ShareExtensions { /// <summary> /// Show the operating system's user interface to share text. /// </summary> /// <param name="share">The object this method is invoked on.</param> /// <param name="text">The text to share.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(this IShare share, string text) => share.RequestAsync(new ShareTextRequest(text)); /// <summary> /// Show the operating systems user interface to share text. /// </summary> /// <param name="share">The object this method is invoked on.</param> /// <param name="text">The text to share.</param> /// <param name="title">The title to display on the operating system share dialog.</param> /// <returns>A <see cref="Task"/> object with the current status of the asynchronous operation.</returns> public static Task RequestAsync(this IShare share, string text, string title) => share.RequestAsync(new ShareTextRequest(text, title)); } /// <summary> /// Base class for the different share requests that can be used with the <see cref="IShare"/> API. /// </summary> public abstract class ShareRequestBase { /// <summary> /// Gets or sets the title to use on the operating system's share user interface. /// </summary> public string? Title { get; set; } /// <summary> /// Gets or sets the source rectangle to display the iOS share user interface from. /// </summary> /// <remarks>This functionality is only available on iOS on an iPad.</remarks> public Rect PresentationSourceBounds { get; set; } = Rect.Zero; } /// <summary> /// Represents a request for sharing text with other apps on the device. /// </summary> public class ShareTextRequest : ShareRequestBase { /// <summary> /// Initializes a new instance of the <see cref="ShareTextRequest"/> class. /// </summary> public ShareTextRequest() { } /// <summary> /// Initializes a new instance of the <see cref="ShareTextRequest"/> class with the given text. /// </summary> /// <param name="text">The text to share.</param> public ShareTextRequest(string text) => Text = text; /// <summary> /// Initializes a new instance of the <see cref="ShareTextRequest"/> class with the given text and title. /// </summary> /// <param name="text">The text to share.</param> /// <param name="title">The title to display on the operating systems share dialog.</param> public ShareTextRequest(string text, string title) : this(text) => Title = title; /// <summary> /// Gets or sets the main text or message to share. /// </summary> public string? Text { get; set; } /// <summary> /// Gets or sets the subject that is sometimes used for applications such as mail clients. /// </summary> /// <remarks>The subject is only applicable on Android and for certain apps.</remarks> public string? Subject { get; set; } /// <summary> /// Gets or sets a valid URI to share. /// </summary> /// <remarks>Needs to be a valid URI, else an exception may be thrown when sharing.</remarks> public string? Uri { get; set; } } /// <summary> /// Represents a request for sharing a single file with other apps on the device. /// </summary> public class ShareFileRequest : ShareRequestBase { /// <summary> /// Initializes a new instance of the <see cref="ShareFileRequest"/> class. /// </summary> public ShareFileRequest() { } /// <summary> /// Initializes a new instance of the <see cref="ShareFileRequest"/> class with the given title and file. /// </summary> /// <param name="title">The title to display on the operating systems share dialog.</param> /// <param name="file">The file to share.</param> public ShareFileRequest(string title, ShareFile file) { Title = title; File = file; } /// <summary> /// Initializes a new instance of the <see cref="ShareFileRequest"/> class with the given title and file. /// </summary> /// <param name="title">The title to display on the operating systems share dialog.</param> /// <param name="file">The file to share.</param> public ShareFileRequest(string title, FileBase file) { Title = title; File = new ShareFile(file); } /// <summary> /// Initializes a new instance of the <see cref="ShareFileRequest"/> class with the given file. /// </summary> /// <param name="file">The file to share.</param> public ShareFileRequest(ShareFile file) => File = file; /// <summary> /// Initializes a new instance of the <see cref="ShareFileRequest"/> class with the given file. /// </summary> /// <param name="file">The file to share.</param> public ShareFileRequest(FileBase file) => File = new ShareFile(file); /// <summary> /// Gets or sets the file to share. /// </summary> public ShareFile? File { get; set; } } /// <summary> /// Represents a request for sharing multiple files with other apps on the device. /// </summary> public class ShareMultipleFilesRequest : ShareRequestBase { /// <summary> /// Initializes a new instance of the <see cref="ShareMultipleFilesRequest"/> class. /// </summary> public ShareMultipleFilesRequest() { } /// <summary> /// Initializes a new instance of the <see cref="ShareMultipleFilesRequest"/> class with the given files. /// </summary> /// <param name="files">A collection of files to share.</param> public ShareMultipleFilesRequest(IEnumerable<ShareFile> files) => Files = files.ToList(); /// <summary> /// Initializes a new instance of the <see cref="ShareMultipleFilesRequest"/> class with the given files. /// </summary> /// <param name="files">A collection of files to share.</param> public ShareMultipleFilesRequest(IEnumerable<FileBase> files) : this(ConvertList(files)) { } /// <summary> /// Initializes a new instance of the <see cref="ShareMultipleFilesRequest"/> class with the given title and files. /// </summary> /// <param name="title">The title to display on the operating systems share dialog.</param> /// <param name="files">A collection of files to share.</param> public ShareMultipleFilesRequest(string title, IEnumerable<ShareFile> files) : this(files) => Title = title; /// <summary> /// Initializes a new instance of the <see cref="ShareMultipleFilesRequest"/> class with the given title and files. /// </summary> /// <param name="title">The title to display on the operating systems share dialog.</param> /// <param name="files">A collection of files to share.</param> public ShareMultipleFilesRequest(string title, IEnumerable<FileBase> files) : this(title, ConvertList(files)) { } /// <summary> /// Gets or sets the files to share. /// </summary> public List<ShareFile>? Files { get; set; } = new List<ShareFile>(); /// <summary> /// Convert a single file share request into a multi-file share request. /// </summary> /// <param name="request">The <see cref="ShareFileRequest"/> object to convert into a <see cref="ShareMultipleFilesRequest"/> object.</param> public static explicit operator ShareMultipleFilesRequest(ShareFileRequest request) => new ShareMultipleFilesRequest { Title = request.Title, Files = new List<ShareFile> { request.File! }, PresentationSourceBounds = request.PresentationSourceBounds }; static IEnumerable<ShareFile> ConvertList(IEnumerable<FileBase> files) => files?.Select(file => new ShareFile(file)) ?? Array.Empty<ShareFile>(); } /// <summary> /// A representation of a file that can be used with the <see cref="IShare"/> API. /// </summary> public class ShareFile : FileBase { /// <summary> /// Initializes a new instance of the <see cref="ShareFile"/> class with the given file path. /// </summary> /// <param name="fullPath">The full path to the file represented by this object.</param> public ShareFile(string fullPath) : base(fullPath) { } /// <summary> /// Initializes a new instance of the <see cref="ShareFile"/> class with the given file path and content type. /// </summary> /// <param name="fullPath">The full path to the file represented by this object.</param> /// <param name="contentType">Explicit content type (MIME type) of the file (eg: <c>image/png</c>).</param> public ShareFile(string fullPath, string contentType) : base(fullPath, contentType) { } /// <summary> /// Initializes a new instance of the <see cref="ShareFile"/> class from the given <see cref="FileBase"/> object. /// </summary> /// <param name="file">A <see cref="FileBase"/> object that will be wrapped in a <see cref="ShareFile"/> object.</param> public ShareFile(FileBase file) : base(file) { } } }