From 672148de5feecbd721c28b6d39cefc20046d10aa Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Thu, 23 Sep 2021 22:42:20 +0200 Subject: [PATCH] feat: In-app rating request on iOS # Conflicts: # src/Uno.UWP/Generated/3.0.0.0/Windows.Services.Store/StoreRateAndReviewResult.cs # src/Uno.UWP/Generated/3.0.0.0/Windows.Services.Store/StoreRateAndReviewStatus.cs # src/Uno.UWP/Services/Store/StoreContext.cs # src/Uno.UWP/Services/Store/StoreContext.iOS.cs --- src/Uno.UWP/Services/Store/StoreContext.cs | 36 +++++++++++++------ .../Services/Store/StoreContext.iOS.cs | 23 ++++++++++++ .../Store/StoreRateAndReviewResult.cs | 28 +++++++++++++++ .../Store/StoreRateAndReviewStatus.cs | 28 +++++++++++++++ 4 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 src/Uno.UWP/Services/Store/StoreRateAndReviewResult.cs create mode 100644 src/Uno.UWP/Services/Store/StoreRateAndReviewStatus.cs diff --git a/src/Uno.UWP/Services/Store/StoreContext.cs b/src/Uno.UWP/Services/Store/StoreContext.cs index 2f7abf0b9fdd..49b5001232c3 100644 --- a/src/Uno.UWP/Services/Store/StoreContext.cs +++ b/src/Uno.UWP/Services/Store/StoreContext.cs @@ -1,20 +1,34 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Windows.Foundation; +using Windows.Foundation; namespace Windows.Services.Store { public sealed partial class StoreContext { - private StoreContext() { } - - public static StoreContext GetDefault() + private StoreContext() { - return new StoreContext(); } + + /// + /// Gets a StoreContext object that can be used to access + /// and manage store-related data for the current + /// user in the context of the current app. + /// + /// An object that you can use to access and manage + /// store-related data for the current user. + public static StoreContext GetDefault() => new StoreContext(); + + /// + /// Requests the user to rate and review the app. This method will + /// display the UI for the user to select a store rating and add + /// an optional store review for the product. + /// + /// Store rate and review result. + /// + /// On iOS and macOS, it is not possible to know whether the user + /// actually rated the app or whether the system allowed the dialog + /// to be displayed. + /// + public IAsyncOperation RequestRateAndReviewAppAsync() => + AsyncOperation.FromTask(ct => RequestRateAndReviewAppTaskAsync(ct)); } } diff --git a/src/Uno.UWP/Services/Store/StoreContext.iOS.cs b/src/Uno.UWP/Services/Store/StoreContext.iOS.cs index ec15b1810298..e11bc847e123 100644 --- a/src/Uno.UWP/Services/Store/StoreContext.iOS.cs +++ b/src/Uno.UWP/Services/Store/StoreContext.iOS.cs @@ -7,6 +7,12 @@ using Uno.Foundation.Logging; using Foundation; +using System.Threading.Tasks; +using System.Threading; +using Windows.System; +using Windows.UI.Core; +using CoreFoundation; +using StoreKit; namespace Windows.Services.Store { @@ -56,5 +62,22 @@ public IAsyncOperation GetStoreProductForCurrentAppAsync() [GeneratedRegex("trackId[^0-9]*([0-9]*)")] private static partial Regex TrackParser(); + + private async Task RequestRateAndReviewAppTaskAsync(CancellationToken cancellationToken) + { + try + { + await CoreDispatcher.Main.RunAsync(CoreDispatcherPriority.Normal, (cancellationToken) => + { + SKStoreReviewController.RequestReview(UIApplication.SharedApplication.KeyWindow.WindowScene); + }); + + return new StoreRateAndReviewResult(StoreRateAndReviewStatus.Succeeded); + } + catch (Exception ex) + { + return new StoreRateAndReviewResult(StoreRateAndReviewStatus.Error, ex); + } + } } } diff --git a/src/Uno.UWP/Services/Store/StoreRateAndReviewResult.cs b/src/Uno.UWP/Services/Store/StoreRateAndReviewResult.cs new file mode 100644 index 000000000000..7ab9473a2d15 --- /dev/null +++ b/src/Uno.UWP/Services/Store/StoreRateAndReviewResult.cs @@ -0,0 +1,28 @@ +#nullable enable + +using System; + +namespace Windows.Services.Store +{ + /// + /// Provides response data for a request to rate and review the product. + /// + public partial class StoreRateAndReviewResult + { + internal StoreRateAndReviewResult(StoreRateAndReviewStatus status, Exception? extendedError = null) + { + Status = status; + ExtendedError = extendedError; + } + + /// + /// Gets the status for the rate and review request for the product. + /// + public StoreRateAndReviewStatus Status { get; } + + /// + /// Gets the error code for the request, if the operation encountered an error. + /// + public Exception? ExtendedError { get; } + } +} diff --git a/src/Uno.UWP/Services/Store/StoreRateAndReviewStatus.cs b/src/Uno.UWP/Services/Store/StoreRateAndReviewStatus.cs new file mode 100644 index 000000000000..e863b4ab5080 --- /dev/null +++ b/src/Uno.UWP/Services/Store/StoreRateAndReviewStatus.cs @@ -0,0 +1,28 @@ +namespace Windows.Services.Store +{ + /// + /// Gets the result status for the rate and review request for the product. + /// + public enum StoreRateAndReviewStatus + { + /// + /// The request was successful. + /// + Succeeded, + + /// + /// The request was canceled by the user. + /// + CanceledByUser, + + /// + /// The request encountered a network error. + /// + NetworkError, + + /// + /// The request encountered an error. + /// + Error, + } +}