diff --git a/lib/constants.dart b/lib/constants.dart index 41d64231a..b33d11dfb 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -25,16 +25,18 @@ const String kSourceCodeFrontend = 'https://github.com/invoiceninja/admin-portal'; const String kSourceCodeFrontendSDK = 'https://pub.dev/packages/invoiceninja'; +const String kAppStoreId = 'com.invoiceninja.app'; +const String kMicrosoftAppStoreId = '9n3f2bbcfdr6'; const String kAppleStoreUrl = 'https://apps.apple.com/us/app/invoice-ninja-v5/id1503970375'; const String kGoogleStoreUrl = - 'https://play.google.com/store/apps/details?id=com.invoiceninja.app'; + 'https://play.google.com/store/apps/details?id=$kAppStoreId'; const String kGoogleFDroidUrl = 'https://f-droid.org/packages/com.invoiceninja.app'; const String kMacOSUrl = 'https://apps.apple.com/app/id1503970375'; const String kLinuxUrl = 'https://snapcraft.io/invoiceninja'; const String kWindowsUrl = - 'https://www.microsoft.com/en-us/p/invoice-ninja/9n3f2bbcfdr6'; + 'https://www.microsoft.com/en-us/p/invoice-ninja/$kMicrosoftAppStoreId'; const String kSlackUrl = 'http://slack.invoiceninja.com'; const String kGitHubUrl = 'https://github.com/invoiceninja'; diff --git a/lib/ui/app/menu_drawer.dart b/lib/ui/app/menu_drawer.dart index 8439813bd..d3ba6514b 100644 --- a/lib/ui/app/menu_drawer.dart +++ b/lib/ui/app/menu_drawer.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:in_app_review/in_app_review.dart'; // Package imports: import 'package:flutter_redux/flutter_redux.dart'; @@ -1379,7 +1380,17 @@ void _showAbout(BuildContext context) async { label: localization.reviewApp.toUpperCase(), iconData: Icons.star, color: Colors.purple, - onPressed: () => launch(getRateAppURL(context)), + onPressed: () { + if (kIsWeb || isLinux()) { + launch(getRateAppURL(context)); + } else { + final InAppReview inAppReview = InAppReview.instance; + inAppReview.openStoreListing( + appStoreId: kAppStoreId, + microsoftStoreId: kMicrosoftAppStoreId, + ); + } + }, ), SizedBox(height: 22), Wrap( diff --git a/lib/ui/app/review_app.dart b/lib/ui/app/review_app.dart index 45490cf63..38d5da839 100644 --- a/lib/ui/app/review_app.dart +++ b/lib/ui/app/review_app.dart @@ -1,5 +1,7 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart'; @@ -7,6 +9,7 @@ import 'package:invoiceninja_flutter/ui/app/menu_drawer.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:in_app_review/in_app_review.dart'; class ReviewApp extends StatefulWidget { const ReviewApp({Key key}) : super(key: key); @@ -18,6 +21,8 @@ class ReviewApp extends StatefulWidget { class _ReviewAppState extends State { bool _likesTheApp; + final InAppReview inAppReview = InAppReview.instance; + @override Widget build(BuildContext context) { final localization = AppLocalization.of(context); @@ -33,7 +38,7 @@ class _ReviewAppState extends State { _likesTheApp == null ? localization.areYouEnjoyingTheApp : _likesTheApp == true - ? localization.wouldYouLeaveAReview + ? localization.wouldYouRateIt : localization.wouldYouTellUsMore, style: Theme.of(context).textTheme.subtitle1, textAlign: TextAlign.center, @@ -42,14 +47,23 @@ class _ReviewAppState extends State { Wrap( children: [ TextButton( - onPressed: () { + onPressed: () async { if (_likesTheApp == null) { setState(() { _likesTheApp = true; }); } else { if (_likesTheApp == true) { - launch(getRateAppURL(context)); + if (await inAppReview.isAvailable()) { + inAppReview.requestReview(); + } else if (kIsWeb || isLinux()) { + launch(getRateAppURL(context)); + } else { + inAppReview.openStoreListing( + appStoreId: kAppStoreId, + microsoftStoreId: kMicrosoftAppStoreId, + ); + } } else { showDialog( context: context, diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 17c9af159..0e6cfd63d 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -19,8 +19,7 @@ mixin LocalizationsProvider on LocaleCodeAware { 'are_you_enjoying_the_app': 'Are you enjoying the app?', 'yes_its_great': 'Yes, it\'s great!', 'not_so_much': 'Not so much', - 'would_you_leave_a_review': - 'Great to hear! Would you like to leave a review?', + 'would_you_rate_it': 'Great to hear! Would you like to rate it?', 'would_you_tell_us_more': 'Sorry to hear it! Would you like to tell us more?', 'sure_happy_to': 'Sure, happy to', @@ -70873,9 +70872,9 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['are_you_enjoying_the_app'] ?? _localizedValues['en']['are_you_enjoying_the_app']; - String get wouldYouLeaveAReview => - _localizedValues[localeCode]['would_you_leave_a_review'] ?? - _localizedValues['en']['would_you_leave_a_review']; + String get wouldYouRateIt => + _localizedValues[localeCode]['would_you_rate_it'] ?? + _localizedValues['en']['would_you_rate_it']; String get wouldYouTellUsMore => _localizedValues[localeCode]['would_you_tell_us_more'] ?? diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index c9ff43176..3700c79e6 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import in_app_review import package_info import package_info_plus_macos import path_provider_macos @@ -15,6 +16,7 @@ import sqflite import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/pubspec.foss.yaml b/pubspec.foss.yaml index 922a2af07..f1132d8e4 100644 --- a/pubspec.foss.yaml +++ b/pubspec.foss.yaml @@ -71,6 +71,7 @@ dependencies: printing: ^5.8.0 image_cropper: ^2.0.2 msal_js: ^2.14.0 + in_app_review: ^2.0.4 # bitsdojo_window: ^0.1.2 # quick_actions: ^0.2.1 # idb_shim: ^1.11.1+1 diff --git a/pubspec.lock b/pubspec.lock index 54ccc873d..25edb3788 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -570,6 +570,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.6.0" + in_app_review: + dependency: "direct main" + description: + name: in_app_review + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + in_app_review_platform_interface: + dependency: transitive + description: + name: in_app_review_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" intl: dependency: "direct main" description: diff --git a/pubspec.next.yaml b/pubspec.next.yaml index dbe8e0e1b..707c3f82b 100644 --- a/pubspec.next.yaml +++ b/pubspec.next.yaml @@ -70,6 +70,7 @@ dependencies: printing: ^5.8.0 image_cropper: ^2.0.2 msal_js: ^2.14.0 + in_app_review: ^2.0.4 # bitsdojo_window: ^0.1.2 # quick_actions: ^0.2.1 # idb_shim: ^1.11.1+1 diff --git a/pubspec.yaml b/pubspec.yaml index 21a6f694e..7586b97ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -71,6 +71,7 @@ dependencies: printing: ^5.8.0 image_cropper: ^2.0.2 msal_js: ^2.14.0 + in_app_review: ^2.0.4 # bitsdojo_window: ^0.1.2 # quick_actions: ^0.2.1 # idb_shim: ^1.11.1+1