GithubHelp home page GithubHelp logo

skyost / ratemyapp Goto Github PK

View Code? Open in Web Editor NEW
261.0 6.0 102.0 682 KB

This plugin allows to kindly ask users to rate your app if custom conditions are met (eg. install time, number of launches, etc...).

Home Page: https://pub.dev/packages/rate_my_app

License: MIT License

Objective-C 0.06% Dart 77.05% Ruby 6.28% Kotlin 10.52% Swift 6.08%
flutter flutter-plugins flutter-plugin app-rating rating

ratemyapp's Introduction

Rate my app !

This plugin allows to kindly ask users to rate your app if custom conditions are met (eg. install time, number of launches, etc...). You can even add your own conditions.

Rate my app is really inspired by Android-Rate.

How to use

Installation

It's important that your bundle identifier (in your Info.plist) match the App ID on iTunes Connect and the package identifier (in your build.gradle) match your App ID on Google Play. If for any reason it doesn't match please go to the Using custom identifiers section.

How it works

Rate my app default constructor takes two main parameters (see Example for more info) :

  • minDays Minimum elapsed days since the first app launch.
  • minLaunches Minimum app launches count.

If everything above is verified, the method shouldOpenDialog will return true (false otherwise). Then you should call showRateDialog which is going to show a native rating dialog, if supported, or a custom rating prompt dialog.

If you prefer, you can call showStarRateDialog which will more or less do the same, but is able to fallback on a dialog containing a star rating bar. It allows you to take custom actions based on the rating (for example if the user puts less than 3 stars then open your app bugs report page or something like this and if he puts more ask him to rate your app on the store page). Still, you have to be careful with these practises (see this paragraph on App Radar).

Screenshots

On Android
showRateDialog method with ignoreNative set to true.
On iOS
showRateDialog and showStarRateDialog methods with ignoreNative set to false.

Using it in your code

Code snippets

// In this snippet, I'm giving a value to all parameters.
// Please note that not all are required (those that are required are marked with the @required annotation).

RateMyApp rateMyApp = RateMyApp(
  preferencesPrefix: 'rateMyApp_',
  minDays: 7,
  minLaunches: 10,
  remindDays: 7,
  remindLaunches: 10,
  googlePlayIdentifier: 'fr.skyost.example',
  appStoreIdentifier: '1491556149',
);

rateMyApp.init().then((_) {
  if (rateMyApp.shouldOpenDialog) {
    rateMyApp.showRateDialog(
      context,
      title: 'Rate this app', // The dialog title.
      message: 'If you like this app, please take a little bit of your time to review it !\nIt really helps us and it shouldn\'t take you more than one minute.', // The dialog message.
      rateButton: 'RATE', // The dialog "rate" button text.
      noButton: 'NO THANKS', // The dialog "no" button text.
      laterButton: 'MAYBE LATER', // The dialog "later" button text.
      listener: (button) { // The button click listener (useful if you want to cancel the click event).
        switch(button) {
          case RateMyAppDialogButton.rate:
            print('Clicked on "Rate".');
            break;
          case RateMyAppDialogButton.later:
            print('Clicked on "Later".');
            break;
          case RateMyAppDialogButton.no:
            print('Clicked on "No".');
            break;
        }
        
        return true; // Return false if you want to cancel the click event.
      },
      ignoreNativeDialog: Platform.isAndroid, // Set to false if you want to show the Apple's native app rating dialog on iOS or Google's native app rating dialog (depends on the current Platform).
      dialogStyle: const DialogStyle(), // Custom dialog styles.
      onDismissed: () => rateMyApp.callEvent(RateMyAppEventType.laterButtonPressed), // Called when the user dismissed the dialog (either by taping outside or by pressing the "back" button).
      // contentBuilder: (context, defaultContent) => content, // This one allows you to change the default dialog content.
      // actionsBuilder: (context) => [], // This one allows you to use your own buttons. 
    );
    
    // Or if you prefer to show a star rating bar (powered by `flutter_rating_bar`) :
    
    rateMyApp.showStarRateDialog(
      context,
      title: 'Rate this app', // The dialog title.
      message: 'You like this app ? Then take a little bit of your time to leave a rating :', // The dialog message.
      // contentBuilder: (context, defaultContent) => content, // This one allows you to change the default dialog content.
      actionsBuilder: (context, stars) { // Triggered when the user updates the star rating.
        return [ // Return a list of actions (that will be shown at the bottom of the dialog).
          FlatButton(
            child: Text('OK'),
            onPressed: () async {
              print('Thanks for the ' + (stars == null ? '0' : stars.round().toString()) + ' star(s) !');
              // You can handle the result as you want (for instance if the user puts 1 star then open your contact page, if he puts more then open the store page, etc...).
              // This allows to mimic the behavior of the default "Rate" button. See "Advanced > Broadcasting events" for more information :
              await rateMyApp.callEvent(RateMyAppEventType.rateButtonPressed);
              Navigator.pop<RateMyAppDialogButton>(context, RateMyAppDialogButton.rate);
            },
          ),
        ];
      },
      ignoreNativeDialog: Platform.isAndroid, // Set to false if you want to show the Apple's native app rating dialog on iOS or Google's native app rating dialog (depends on the current Platform).
      dialogStyle: const DialogStyle( // Custom dialog styles.
        titleAlign: TextAlign.center,
        messageAlign: TextAlign.center,
        messagePadding: EdgeInsets.only(bottom: 20),
      ),
      starRatingOptions: const StarRatingOptions(), // Custom star bar rating options.
      onDismissed: () => rateMyApp.callEvent(RateMyAppEventType.laterButtonPressed), // Called when the user dismissed the dialog (either by taping outside or by pressing the "back" button).
    );
  }
});

Minimal Example

Below is the minimal code example. This will be for the basic minimal working of this plugin. The code below will launch a simple message popup after the defined minimal days/minimal launches along with the default buttons : Rate, Maybe later and Cancel, with their default behavior.

Place this in your main widget state :

RateMyApp rateMyApp = RateMyApp(
  preferencesPrefix: 'rateMyApp_',
  minDays: 0, // Show rate popup on first day of install.
  minLaunches: 5, // Show rate popup after 5 launches of app after minDays is passed.
);

@override
void initState() {
  super.initState();

  WidgetsBinding.instance.addPostFrameCallback((_) async {
    await rateMyApp.init();
    if (mounted && rateMyApp.shouldOpenDialog) {  
      rateMyApp.showRateDialog(context);
    }
  });
}

If you want a more complete example, please check this one on Github.
You can also follow the tutorial of Marcus Ng on YouTube (for a replacement of doNotOpenAgain, see Broadcasting events).

Advanced

Where to initialize Rate My App

You should be careful on where you initialize Rate My App in your project. But thankfully, there's a widget that helps you getting through all of this without any trouble : RateMyAppBuilder. Here's an example :

// The builder should be initialized exactly one time during the app lifecycle.
// So place it where you want but it should respect that condition.

RateMyAppBuilder(
  builder: (context) => MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Rate my app !'),
      ),
      body: Center(child: Text('This is my beautiful app !')),
    ),
  ),
  onInitialized: (context, rateMyApp) {
    // Called when Rate my app has been initialized.
    // See the example project on Github for more info.
  },
);

You can totally choose to not use it and to initialize Rate my app in your main() method. This is up to you !

Using custom identifiers

It's possible to use custom store identifiers ! Just pass the following parameters during the plugin initialization :

  • googlePlayIdentifier Your Google Play identifier (usually a package name).
  • appStoreIdentifier Your App Store identifier (usually numbers).

Using custom conditions

A condition is something required to be met in order for the shouldOpenDialog method to return true. Rate my app comes with three default conditions :

  • MinimumDaysCondition Allows to set a minimum elapsed days since the first app launch before showing the dialog.
  • MinimumAppLaunchesCondition Allows to set a minimum app launches count since the first app launch before showing the dialog.
  • DoNotOpenAgainCondition Allows to prevent the dialog from being opened (when the user clicks on the No button for example).

You can easily create your custom conditions ! All you have to do is to extend the Condition class. There are five methods to implement :

  • readFromPreferences You should read your condition values from the provided shared preferences here.
  • saveToPreferences You should save your condition values to the provided shared preferences here.
  • reset You should reset your condition values here.
  • isMet Whether this condition is met.
  • onEventOccurred When an event occurs in the plugin lifecycle. This is usually here that you can update your condition values. Please note that you're not obligated to override this one (although this is recommended).

You can have an easy example of it by checking the source code of DoNotOpenAgainCondition.

Then you can add your custom condition to Rate my app by using the constructor customConditions (or by calling rateMyApp.conditions.add before initialization).

Broadcasting events

As said in the previous section, the shouldOpenDialog method depends on conditions.

For example, when you click on the No button, this event will be triggered and the condition DoNotOpenAgainCondition will react to it and will stop being met and thus the shouldOpenDialog will return false.

You may want to broadcast events in order to mimic the behaviour of the No button for example. This can be done either by using the RateMyAppNoButton or you can directly call callEvent from your current RateMyApp instance in your button onTap callback.

Here are what events default conditions are listening to :

  • MinimumDaysCondition : Later button press.
  • MinimumAppLaunchesCondition : Rate my app initialization, Later button press.
  • DoNotOpenAgainCondition : Rate button press, No button press.

For example, starting from version 0.5.0, the getter/setter doNotOpenAgain has been removed. You must trigger the DoNotOpenAgainCondition either by calling a Rate button press event or a No button press event (see Example on Github).

Contributions

You have a lot of options to contribute to this project ! You can :

Dependencies

This library depends on shared_preferences (to store its state) and flutter_rating_bar (for showRateDialog).

ratemyapp's People

Contributors

acoutts avatar daadu avatar danielmessi13 avatar denchikby avatar farazk86 avatar laennart avatar lohanbodevan avatar marianoarga avatar sadeesha-sath avatar salehhub avatar skyost avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ratemyapp's Issues

Updated pods, add use_frameworks! getting warning: 'requestReview' is only available on iOS 10.3 or newer

Describe the bug
I upgraded pods and updated to latest, I updated to 10.3 deployment target, but still received this error

To Reproduce
Steps to reproduce the behavior:
Clean project, pod update, fails to compile due to below error. Add use_frameworks! to your podfile.

Expected behavior
Should be able to build, and should be able to compile with use_frameworks! This seems to be related to outdated syntax

Xcode build done.                                           161.7s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **


Xcode's output:
↳
    /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:15:30: warning: 'requestReview' is only available on iOS 10.3 or newer [-Wunguarded-availability]
        [SKStoreReviewController requestReview];
                                 ^~~~~~~~~~~~~~
    In module 'StoreKit' imported from /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:2:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/System/Library/Frameworks/StoreKit.framework/Headers/SKStoreReviewController.h:22:1: note: 'requestReview' has been marked as being introduced in iOS 10.3 here, but the deployment target is iOS 8.0.0
    + (void)requestReview API_AVAILABLE(ios(10.3), macos(10.14)) __TVOS_PROHIBITED;
    ^
    /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:15:30: note: enclose 'requestReview' in an @available check to silence this warning
        [SKStoreReviewController requestReview];
                                 ^~~~~~~~~~~~~~
    /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:15:6: warning: 'SKStoreReviewController' is only available on iOS 10.3 or newer [-Wunguarded-availability]
        [SKStoreReviewController requestReview];
         ^~~~~~~~~~~~~~~~~~~~~~~
    In module 'StoreKit' imported from /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:2:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/System/Library/Frameworks/StoreKit.framework/Headers/SKStoreReviewController.h:14:85: note: 'SKStoreReviewController' has been marked as being introduced in iOS 10.3 here, but the deployment target is iOS 8.0.0
    SK_EXTERN_CLASS API_AVAILABLE(ios(10.3), macos(10.14)) __TVOS_PROHIBITED @interface SKStoreReviewController : NSObject
                                                                                        ^
    /Users/kevin/.pub-cache/hosted/pub.dartlang.org/rate_my_app-0.6.0+2/ios/Classes/RateMyAppPlugin.m:15:6: note: enclose 'SKStoreReviewController' in an @available check to silence this warning
        [SKStoreReviewController requestReview];

[UPDATE]
Looks like it was all related to this:
flutter/flutter#35670

Broken dependency smooth star rating

The parameter onRatingChanged on SmoothStarRating is removed in one of the new versions. This causes a compilation error on line 272 in dialogs.dart. A workaround is to change the version of smooth_star_rating from ^1.0.4+2 to 1.0.4+2 in the pubspec.

Possibility to further customize the dialog

Hi, i was wondering if there is any change some changes could be made to the Dialog structure:
The AlertDialog ButtonRow widget, is a row, which contains a padding, what is not exanded so it's always going to shrink around the action buttons, forcing them to align the right., would be nice to have the possibility to have some control over the buttons as well.

Cheers!

David

Suggestion to call dialog on Android with checks


    public static void rateApp(Context context) {
        if (context == null) {
            return;
        }

        try {
            Intent rateIntent = rateIntentForUrl(context, "market://details");
            context.startActivity(rateIntent);
        } catch (ActivityNotFoundException e) {
            Intent rateIntent = rateIntentForUrl(context, "https://play.google.com/store/apps/details");
            context.startActivity(rateIntent);
        }
    }

    private static Intent rateIntentForUrl(Context context, String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format("%s?id=%s", url, context.getPackageName())));
        int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;

        if (Build.VERSION.SDK_INT >= 21) {
            flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
        } else {
            //noinspection deprecation
            flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
        }

        intent.addFlags(flags);
        return intent;
    }

IOS linking error: -lrate_my_app

Hi!
I have an IOS specific linking error, while building from XCode.
"ld: library not found for -lrate_my_app"
Do you have any idea? I ran flutter pub get, as well as pod install/upgrade/whatever.

Use Custom button in show rate dialog not working

I used normal rate dialog from your example

this line that u comment out
// actionsBuilder: (_) => [], // This one allows you to use your own buttons.

when I custom my own button, it show dialog but when click rate or maybe later it doesn't go to store or even print Clicked on "Rate" or anything it just dissapear. is that a bug?

this is my custom button code

actionsBuilder: (_) => [
FlatButton(
child: Text(
'Maybe Later',
style: TextStyle(
color: Colors.grey[300],
fontFamily: 'NunitoExtraBold',
fontSize: 15,
),
),
onPressed: () async {
await _rateMyApp.callEvent(RateMyAppEventType.laterButtonPressed);
Navigator.pop(
context, RateMyAppDialogButton.later);
},
),
FlatButton(
child: Text(
'Rate Now',
style: TextStyle(
color: Color.fromRGBO(0, 121, 113, 1.00),
fontFamily: 'NunitoExtraBold',
fontSize: 15,
),
),
onPressed: () async {
await _rateMyApp.callEvent(RateMyAppEventType.rateButtonPressed);
Navigator.pop(
context, RateMyAppDialogButton.rate);
},
),
],

Android UI glitch - right overflow

Android UI glitch - right overflow

Device - Moto G 2nd Gen
Android - 6.0

I/flutter (10171): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (10171): The following message was thrown during layout: I/flutter (10171): A RenderFlex overflowed by 1.00 pixels on the right. E/FA (10171): Missing google_app_id. Firebase Analytics disabled. See https://goo.gl/NAOOOI I/flutter (10171): The overflowing RenderFlex has an orientation of Axis.horizontal. I/flutter (10171): The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and I/flutter (10171): black striped pattern. This is usually caused by the contents being too big for the RenderFlex. I/flutter (10171): Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the I/flutter (10171): RenderFlex to fit within the available space instead of being sized to their natural size. I/flutter (10171): This is considered an error condition because it indicates that there is content that cannot be I/flutter (10171): seen. If the content is legitimately bigger than the available space, consider clipping it with a I/flutter (10171): ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, I/flutter (10171): like a ListView. I/flutter (10171): The specific RenderFlex in question is: I/flutter (10171): RenderFlex#0db86 relayoutBoundary=up8 OVERFLOWING I/flutter (10171): creator: Row ← Padding ← ButtonBar ← ButtonTheme ← Column ← IntrinsicWidth ← DefaultTextStyle ← I/flutter (10171): AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#cd0b1 ink renderer] ← I/flutter (10171): NotificationListener<LayoutChangedNotification> ← CustomPaint ← _ShapeBorderPaint ← ⋯ I/flutter (10171): parentData: offset=Offset(4.0, 8.0) (can use size) I/flutter (10171): constraints: BoxConstraints(w=272.0, 0.0<=h<=Infinity) I/flutter (10171): size: Size(272.0, 48.0) I/flutter (10171): direction: horizontal I/flutter (10171): mainAxisAlignment: end I/flutter (10171): mainAxisSize: max I/flutter (10171): crossAxisAlignment: center I/flutter (10171): textDirection: ltr I/flutter (10171): verticalDirection: down I/flutter (10171): ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤ I/flutter (10171): ════════════════════════════════════════════════════════════════════════════════════════════════════

device-2019-05-20-080917

where to input customized parameters in the example project?

Additional context
This may sound stupid, but in the example with the RateMyAppBuilder(), I couldn't find a place to input/ replace my own parameters e.g. googlePlayIdentifier.
I tried to do a global search in these files, but it only pointed to README.md and core.dart

Button text black not visible dark theme (Android)

Hello!

I use a dark theme (inside ThemeData = brightness: Brightness.dark) on my app and the title and message properties are looking good since they are white. However the rateButton, noButton and laterButton text is black, which the dialog is aswell because of the dark theme, which makes them not visible.

I can't see anyway to change the text color unfortunately, or just handle the dark theme somehow.

Would be great if the showRateDialog could handle flutter dark theme aswell, thanks!

How can i translate?

On ios how can i change enjoy appname? and below tap a star rate it on the app store text.

sample code throws an error

hello, your sample code throws an error

{
	"resource": "/E:/Flutter/Nicolas Zein/Projects/Zandu/zandu-wholesale-mobileclient-enduser-0003/lib/utils/app_rating.dart",
	"owner": "dart",
	"code": "missing_function_parameters",
	"severity": 8,
	"message": "Functions must have an explicit list of parameters.\nTry adding a parameter list.",
	"source": "dart",
	"startLineNumber": 16,
	"startColumn": 1,
	"endLineNumber": 16,
	"endColumn": 11,
	"tags": []
}

also this:

{
	"resource": "/E:/Flutter/Nicolas Zein/Projects/Zandu/zandu-wholesale-mobileclient-enduser-0003/lib/utils/app_rating.dart",
	"owner": "dart",
	"code": "expected_executable",
	"severity": 8,
	"message": "Expected a method, getter, setter or operator declaration.\nThis appears to be incomplete code. Try removing it or completing it.",
	"source": "dart",
	"startLineNumber": 16,
	"startColumn": 11,
	"endLineNumber": 16,
	"endColumn": 12,
	"tags": []
}

Shared preferences required to use library

Describe the bug
I've just installed this library and running my app i get an exception

The getter 'millisecondsSinceEpoch' was called on null.
Receiver: null
Tried calling: millisecondsSinceEpoch

It looks like the library is assuming certain keys exist in the shared preferences but there is no instruction to create them and they don't seem to be in the example app

To Reproduce
Steps to reproduce the behavior:
Include the library in an app
Initialise with recommended settings

RateMyApp rateMyApp = RateMyApp(
    preferencesPrefix: 'rateMyApp_',
    minDays: 7,
    minLaunches: 10,
    remindDays: 7,
    remindLaunches: 10,
    googlePlayIdentifier: 'app.namespace',
    appStoreIdentifier: 'appid',
  );

Call opendialog if needed

if(rateMyApp.shouldOpenDialog)
      rateMyApp.showStarRateDialog(
        context,
        title: 'Rate this app', // The dialog title.
        message: 'Do you enjoy the app? Please take a little time to leave a rating :', // The dialog message.
        onRatingChanged: (stars) { // Triggered when the user updates the star rating.
          return [ // Return a list of actions (that will be shown at the bottom of the dialog).
            FlatButton(
              child: Text('OK'),
              onPressed: () async {
                print('Thanks for the ' + (stars == null ? '0' : stars.round().toString()) + ' star(s) !');
                if(stars.round() <= 2)
                {

                }
                // You can handle the result as you want (for instance if the user puts 1 star then open your contact page, if he puts more then open the store page, etc...).
                // This allows to mimic the behavior of the default "Rate" button. See "Advanced > Broadcasting events" for more information :
                await rateMyApp.callEvent(RateMyAppEventType.rateButtonPressed);
                Navigator.pop<RateMyAppDialogButton>(context, RateMyAppDialogButton.rate);
              },
            ),
          ];
        },
        ignoreIOS: false, // Set to false if you want to show the native Apple app rating dialog on iOS.
        dialogStyle: DialogStyle( // Custom dialog styles.
          titleAlign: TextAlign.center,
          messageAlign: TextAlign.center,
          messagePadding: EdgeInsets.only(bottom: 20),
        ),
        starRatingOptions: StarRatingOptions(),
        // Custom star bar rating options.
        //I had to comment this out because it doesn't seem to exist
//onDismissed: () => rateMyApp.callEvent(RateMyAppEventType.laterButtonPressed), // Called when the user dismissed the dialog (either by taping outside or by pressing the "back" button).
      );

Expected behavior
Documentation of required shared preference keys and how to populate them
Or have the keys auto generate if the values are missing
The shared preferences library has containsKey so check before using the value and if not found default value it? (sharedPreferences.containsKey(key) ? sharedPreferences.getString(key) : emptyValue;)

Desktop (please complete the following information):

  • OS: Linux Mint 19.3

Smartphone (please complete the following information):

  • Device:Android emulator Pixel 3
  • OS: Android
  • Version 29

I have the following versions installed related to this library

  • Flutter version 1.12.13+hotfix.5
  • rate_my_app: ^0.5.0+3
  • smooth_star_rating: ^1.0.4+2
  • shared_preferences: ^0.5.6+1

Stacktrace

When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1      MinimumDaysCondition.isMet (package:rate_my_app/src/conditions.dart:81:68)
#2      RateMyApp.shouldOpenDialog.<anonymous closure> (package:rate_my_app/src/core.dart:80:80)
#3      ListMixin.firstWhere (dart:collection/list.dart:144:15)
#4      RateMyApp.shouldOpenDialog (package:rate_my_app/src/core.dart:80:43)

Treating dismissed dialog as "later" condition

Is there any option to listen to the dialog being dismissed (by clicking on the black background or using the back button) and tag that as a "later" event? Right now that triggers no event, and on the next call of dialog, it shows it again.

hello sir , i tried to use this plugin , but its not opening the dialog after 3 days or the times I have specified the launches .. it works in production when the if (_rateMyApp.shouldOpenDialog) {

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

shouldOpenDialog is always false. Please help if there is something I am doing wrong.

This is how I am using this plug-in in my flutter app.

`class Home extends StatefulWidget{
HomeState createState() => HomeState();
}

class HomeState extends State with TickerProviderStateMixin{

RateMyApp _rateMyApp = RateMyApp(
minDays: 1,
minLaunches: 2,
remindDays: 1,
remindLaunches: 2,
);

void initState(){
rateMyApp.init().then(() {
if (_rateMyApp.shouldOpenDialog) {
_rateMyApp.showRateDialog(
context,
title: 'Rate this app',
message: 'If you like this app, please take a little bit of your time to review it !\nIt really helps us and it shouldn't take you more than one minute.',
rateButton: 'RATE',
noButton: 'NO THANKS',
laterButton: 'MAYBE LATER',
);
}
});
}

Widget build(BuildContext context){
}

}`

I have displayed the value of _rateMyApp.shouldOpenDialog in a text widget in my UI for testing, and it is always false, which should be true after 2 launches. Because it is always false, the rate-dialog is never appearing. Is there something I am doing wrong?

Dialog only pops up on iOS.

Describe the bug
Dialog doesn't open on emulator or physical android phone.

To Reproduce

import 'package:flutter/material.dart';
import 'package:rate_my_app/rate_my_app.dart';

RateMyApp rateMyApp = RateMyApp(
  preferencesPrefix: 'rateMyApp_',
  minDays: 0,
  minLaunches: 0,
  remindDays: 0,
  remindLaunches: 0,
  appStoreIdentifier: '100000000',
  googlePlayIdentifier: 'com.example.rateMyApp',
);

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  rateMyApp.init().then((_) {
    runApp(TestApp());
  });
}

class TestApp extends StatefulWidget {
  @override
  _TestAppState createState() => _TestAppState();
}

class _TestAppState extends State<TestApp> {
  @override
  void initState() {
    rateMyApp.init().then((_) {
      if (rateMyApp.shouldOpenDialog) {
        rateMyApp.showRateDialog(
          context,
          title: 'Rate this app',
          message: 'Please rate',
          rateButton: 'RATE',
          noButton: 'NO THANKS',
          laterButton: 'MAYBE LATER',
        );
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Center(child: Text('test')),
      ),
    );
  }
}

Expected behavior
Dialog should open on emulator and physical android phone.

Additional context
I guess it's related to the "Where to initialize Rate My App" section,
I don't fully understand "initialize Rate my app in your main() method".
RateMyAppBuilder() works well to let the dialog show up,
but it's not compatible with it's children layout (namely admob banner ads at bottom and keyboard, but that's a different question).

possibility to set the content of the dialog

I'd like to have the possibility to replace title & message by whatever Widget of my choice

Future showStarRateDialog(
BuildContext context, {
String title,
String message,

Thx.

plugin doesnt seem to work in test flight

Describe the bug
The plugin works in debug mode but doesnt show up in test flight. Might that be because the app has not been published yet ?
To Reproduce
launch app on test flight and open 5 times.

Expected behavior
popup rate dialog box in production and debug modes.

Show rating stars on android or at least an option to hide or show them as in IOS

Is your feature request related to a problem? Please describe.
On Android, the dialog shown is just a text with several buttons.

Describe the solution you'd like
It would be nice to let the user rate the app in this dialog (Show a star rater widget). This way we can decide what to do depending on what should do the user when reviewing it on the store.

For example I would like to make the user send me and email when he is going to rate the app with 3 or less stars.

Describe alternatives you've considered
This is the only lib I like.

Additional context
Not needed

App crashes after compile...cannot even install

Describe the bug
When I integrated this package into my app and tried to run it in debug mode from VS Code, I cannot even install on my Android device. I verified there's something wrong with this package since my app installs properly as soon as I removed this package from pubspec.yaml and associated references.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6] Nokia 7.1
  • OS: [e.g. iOS8.1] Android 9
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Hide No Thanks Button

I want to know if it is possible to hide the "No Thanks" button in the dialog since tapping this button will hide the review dialog forever.

Exception on pressing any button

Describe the bug

when the dialog shows it through exception on pressing any button.

E/flutter (18056): #18 PointerRouter.route package:flutter/…/gestures/pointer_router.dart:101 E/flutter (18056): #19 GestureBinding.handleEvent package:flutter/…/gestures/binding.dart:218 E/flutter (18056): #20 GestureBinding.dispatchEvent package:flutter/…/gestures/binding.dart:198 E/flutter (18056): #21 GestureBinding._handlePointerEvent package:flutter/…/gestures/binding.dart:156 E/flutter (18056): #22 GestureBinding._flushPointerEventQueue package:flutter/…/gestures/binding.dart:102 E/flutter (18056): #23 GestureBinding._handlePointerDataPacket package:flutter/…/gestures/binding.dart:86 E/flutter (18056): #24 _rootRunUnary (dart:async/zone.dart:1138:13) E/flutter (18056): #25 _CustomZone.runUnary (dart:async/zone.dart:1031:19) E/flutter (18056): #26 _CustomZone.runUnaryGuarded (dart:async/zone.dart:933:7) E/flutter (18056): #27 _invoke1 (dart:ui/hooks.dart:273:10) E/flutter (18056): #28 _dispatchPointerDataPacket (dart:ui/hooks.dart:182:5)
To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Localization issue

Can you explain, I am getting this error Unhandled Exception: No MaterialLocalizations found. Already using MaterialApp as root element and also tried the localization, nothing worked.

remindDays not working as expected in MinimumDaysCondition

Describe the bug
The rate dialog may pop up too often not correctly respecting remindDays

To Reproduce
MinimumDaysCondition tracks and uses the baseLaunchDate for checking it in the isMet getter. Let's assume we set the remindDays = 2 and the user interacted with the app last time half year ago. It will save the baseLaunchDate in the shared preferences as a date from about half a year ago. If the user started using the app now and keeps pressing the "Remind Later" button, it will increment the baseLaunchDate by 2 days still keeping the popup dialogs opened immediately for a very long time.

Expected behavior
It's expected that the rate dialog doesn't popup earlier than in the remindDays after being closed last time.

Additional context
I would suggest that the MinimumDaysCondition should be split into two conditions. One, which deals just with minDays, should just use the launch date. The other one, probably called RemindDaysCondition, should use the last dialog close time and should use the remindDays in the isMet getter (not the case at the moment at all)

Dependency bug - wrong pedantic version

Happens on flutter beta channel with version 0.6.0 of RateMyApp

Because every version of flutter_driver from sdk depends on pedantic 1.8.0+1 and rate_my_app >=0.6.0 depends on pedantic ^1.9.0, flutter_driver from sdk is incompatible with rate_my_app >=0.6.0.

I think this should be a pretty simple fix

context is undefined

if (_rateMyApp.shouldOpenDialog) {
_rateMyApp.showRateDialog(
context,
title: 'Rate this app',
message: 'If you like this app, please take a little bit of your time to review it !\nIt really helps us and it shouldn't take you more than one minute.',
rateButton: 'RATE',
noButton: 'NO THANKS',
laterButton: 'MAYBE LATER',
ignoreIOS: false,
dialogStyle: DialogStyle(),
);
if we placed this code in my app then context is not undefined .. i hope you will be understand ..
and your package is very good and helpfull...please solve this problem..

Button click listener

Hello!
There is no button click listener on showRateDialog like in original Android-Rate library.
It's very useful feature to store click statistics.
It would great if you add it, I see it something like that:

enum RateDialogButton {
  rate,
  no,
  later,
}

rateMyApp.showRateDialog(
  onClick: (RateDialogButton button) {
  },
);

Question: `doNotOpenAgain` after clicking the submit button?

This is not a Feature Request nor a Bug.
I was wondering what is the best thing to do after a user clicked on the rate button? He will then be send to the App Store but what should we set doNotOpenAgain? We can't be sure if the user actually submitted a rating but if he did, it would be bad to show the dialog again? Whats the best way to handle this?

[The setter 'doNotOpenAgain isn't defined for the class 'RateMyApp']

Describe the bug
When I attempt to implement .doNotOpenAgain, I get the following error "The setter 'doNotOpenAgain isn't defined for the class 'RateMyApp'".

//RateMyApp Preferences
  RateMyApp _rateMyApp = RateMyApp(
    preferencesPrefix: 'rateMyApp_',
    //Minimum number of days a user has to have the app installed, 3
    minDays: 3,
    //Minimum number of launches before showing prompt, 5
    minLaunches: 5,
    //Number of days before requesting a rating, 7
    remindDays: 7,
    //Number of launches before requesting a rating, 5
    remindLaunches: 5,
);
@override
   void initState() {
   super.initState();
   _rateMyApp.init().then((_){
      //if (_rateMyApp.shouldOpenDialog) {
      _rateMyApp.showStarRateDialog(
        context,
        title: 'Enjoying Liquid',
        message: 'Please leave a rating!',
        onRatingChanged: (stars) {
          return [
            FlatButton(
              onPressed: () {
                if (stars!= null) {
                  _rateMyApp.doNotOpenAgain = true;
                  _rateMyApp.save().then((v) => Navigator.pop(context));
                  if (stars <= 3) {
                    //Navigate to Contact Screen
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (_) => ContactSupportScreen(),
                      ),
                    );
                  } else if (stars >= 4) {
                    print('Leave a Review');
                  }
                } else {
                  Navigator.pop(context);
                }
              }, //onPressed
              child: Text('Ok'),
            ),
          ];
        },
        dialogStyle: DialogStyle(
          titleAlign: TextAlign.center,
          messageAlign: TextAlign.center,
          messagePadding: EdgeInsets.only(bottom: 20.0),
        ),
        starRatingOptions: StarRatingOptions(),
      );
      //}
    });
  }

`

Additional context

  • rate_my_app: ^0.5.0+1

iOS Darkmode Background is white

On iOS is the title and message from the default iOS promt are white. But the background of the promt is also white instead of dark grey.

License - MIT?

Why is this under GPL and not MIT, I guess most commercial apps won't be able to use it because of it. =)

A more modulable condition system

A more modulable condition system would be good I think. For exemple, we could create a class named Condition with the following methods :

  • readFromPreferences Which would read the condition value from the shared preferences (called by RateMyApp when loaded).
  • saveToPreferences Which would save the condition value to the shared preferences (called by RateMyApp when saved).
  • isMet Whether the current condition has been met.
  • Something like listen(rateMyApp) (not sure about this one) Which would attach the RateMyApp instance to the current condition instance, allowing it to be listened. The condition will then update itself based on the kind of event.
  • requiresPreferencesSave Which would trigger an async shared preferences save.

The next step would be to create a set of conditions in the RateMyApp class and add the default one (install time, minimum launches, do not open again ?, ...).

This system will have a lot of benefits but it will mainly allow users to add their own custom conditions without having to override the RateMyApp class.

Conditions always met iOS

Describe the bug
I want to display the message after the user has logged in. Therefore, in the page I wish to display it on, I have added the following code outside of the class.

To Reproduce

RateMyApp _rateMyApp = RateMyApp(
preferencesPrefix: '_rateMyApp',
minDays: 0,
minLaunches: 5,
remindDays: 0,
remindLaunches: 5,
);

String _dateToString(DateTime date) =>
date.day.toString().padLeft(2, '0') +
'/' +
date.month.toString().padLeft(2, '0') +
'/' +
date.year.toString();

then this code inside the stateful widget.

@OverRide
void initState() {
super.initState();

_rateMyApp.init().then((_) {
  print('Minimum days : ' + _rateMyApp.minDays.toString());
  print('Minimum launches : ' + _rateMyApp.minLaunches.toString());
  print('Remind launches : ' + _rateMyApp.remindLaunches.toString());

  print('Base launch : ' + _dateToString(_rateMyApp.baseLaunchDate));
  print('Launches : ' + _rateMyApp.launches.toString());
  print(
      'Do not open again ? ' + (_rateMyApp.doNotOpenAgain ? 'Yes' : 'No'));

  print('Are conditions met ? ' +
      (_rateMyApp.shouldOpenDialog ? 'Yes' : 'No'));

  if (_rateMyApp.shouldOpenDialog) {
    _rateMyApp.showRateDialog(
      context,
      title: 'Rate this app',
      message:
          'If you like this app, please take a little bit of your time to review it !\nIt really helps us and it shouldn\'t take you more than one minute.',
      rateButton: 'RATE',
      noButton: 'NO THANKS',
      laterButton: 'MAYBE LATER',
      ignoreIOS: false,
    );
  }
});

}

Expected behavior

Despite tapping "not now" the message appears on every launch, rather than every 5 after tapping not now, despite the console correctly displaying the values. "Are Conditions Met" always displays "Yes"

Smartphone (please complete the following information):

  • Device: [iPhone6 Plus] running 12.4.1

Version 0.6.0 doesn't work

I use Flutter SDK v1.14.6 (Beta channel)
And I can't use the last version 0.6.0.
Running "flutter pub get" get an error:

Because every version of flutter_driver from sdk depends on pedantic 1.8.0+1 and rate_my_app >=0.6.0 depends on pedantic ^1.9.0, flutter_driver from sdk is incompatible with rate_my_app >=0.6.0.

Does not callback listener code. ANDROID

Added this code to launch rate me dialog but code never reaches listener code so I have no way to check results of users button clicks. btw, I've added this code to initState

rateMyApp.init().then((_) {
  if (rateMyApp.shouldOpenDialog) {
    rateMyApp.showRateDialog(
      context,
      title: 'Rate this app',
      message:
          'If you like this app, please take a little bit of your time to review it !\nIt really helps us and it shouldn\'t take you more than one minute.',
      rateButton: 'RATE',
      noButton: 'NO THANKS',
      laterButton: 'MAYBE LATER',
      listener: (button) {
        switch (button) {
          case RateMyAppDialogButton.rate:
            print('Clicked on "Rate".');
            break;
          case RateMyAppDialogButton.later:
            print('Clicked on "Later".');
            break;
          case RateMyAppDialogButton.no:
            print('Clicked on "No".');
            break;
        }
        return true;
      },
      ignoreIOS: false,
      dialogStyle: DialogStyle(),
    );
  }
});

Rating dialog not working

Hello when i use your star dialog, when i press on ok, nothing happens. Is this normal behavior?

I want to be able to use the star rating so i know what the user thinks of my app from inside the app. Thanks.

Anything needed to code on "OK" button press for rate app

Hi, I just want to know that i am using your showStarRateDialog in my app and i found that code once you click OK button after rating at that time SnackBar will display and popup will disappear. so my questions are below:
(1) The Rating will reflect on Review section of app (Play Store & Appstore) or any code i need to put on "OK" button click.
(2) if any user wants to write some review for app so how can write in this popup? if any feature will come to write review for same.

iOS: incorrect dark theme support

When shown on device using dark theme, dialog's text is drawn according to dark theme, while its background is still belonging to light one. See screenshot attached.

Screenshot 2020-01-09 at 09 32 43

Expected behavior - dialog background should be black.

Tested on simulator:

  • Device: iPhone 11 Pro Max
  • OS: iOS 13.0

iOS requestReview is not checked against remind conditions

Describe the bug
On iOS with the default option ignoreIOS = false, the review dialog is only checked against it min-conditions (minDays & minLaunches). Once this condition is met, the iOS default review dialog will be display every time and it will not verify if the remind-conditions (remindDays & remindLaunches) are met.

To Reproduce
Steps to reproduce the behavior:

  1. Create a project with settings: minDays: 0 & minLaunches: 1
  2. Use remindDays: 31 & remindLaunches: 15 in the same project.
  3. Start the app, the review dialog appears as expected, click on 'later'
  4. Restart the app, the review dialog appears again. This is not expected as the remindConditions are not met.

Expected behavior
I would expect to see the review dialog only after 31 days and 15 launches, not every launch.

Screenshots
/

Smartphone :

  • Device: iPhone6s
  • OS: iOS13.4.1

Additional context
Flutter --version
Flutter 1.17.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f7a6a7906b (4 weeks ago) • 2020-05-12 18:39:00 -0700
Engine • revision 6bc433c6b6
Tools • Dart 2.8.2

Apple is placing some hard limits on the review dialog itself as written here: https://developer.apple.com/documentation/storekit/skstorereviewcontroller/requesting_app_store_reviews

How I think this should be fixed

  1. Ideal there would be a callback from Apple's native app rating dialog making it possible to invoke the callEvent-function in core.dart with the corresponding eventType.
  2. As I have searched for callbacks and I couldn't find any useful information, I would suggest changing the onEventOccurred-fuctions in conditions.dart to not only check for the real eventType but also check for RateMyAppEventType.iOSRequestReview. This would fix it for the MinimumDaysCondition & MinimumAppLaunchesCondition. If I am correct, apple also checks if it can display the review dialog so the DoNotOpenAgainCondition is not useful in this case.
    e.g.:
    change:
    if (eventType == RateMyAppEventType.laterButtonPressed)
    to:
    if (eventType == RateMyAppEventType.laterButtonPressed || eventType == RateMyAppEventType.RateMyAppEventType.iOSRequestReview)

App already rated in iOS

On Android if you already rated the app, click the button simply go to the store to edit existing rating.

On iOS if you already rated the app, click the button simply do nothing.

Is there any function to know app already rated to hide the button?

In case you install the app on new device but already rated on other device, there no valid data to check doNotOpenAgain, minLaunches, minDays...

Thank you.

After 7 days the app is installed i get the rating popup everytime

After 7 days the app is installed i get the rating popup everytime i switch page/open the app

This is my init Code

RateMyApp(
        minDays: 7,
        minLaunches: 10,
        remindDays: 7,
        remindLaunches: 10, 
      ));

This is the way i open the popup:

_rateMyApp.init().then((_) {
      if (_rateMyApp.shouldOpenDialog) {
        _rateMyApp.showStarRateDialog(
          context,
          title: ToTLocalizations.of(context).rateAppTitle,
          message: ToTLocalizations.of(context).rateAppContent,
          ignoreIOS: false,
          starRatingOptions: StarRatingOptions(),
          onRatingChanged: (stars) {
            return [
              RaisedButton(
                padding: EdgeInsets.all(10.0),
...

The expected behavior is that if i click "later" the "baseLaunchDate" should be set to today, and the popup opened again in 7 (remind days) days

I'm running it on IOS 12.4 simulator

The native popup is opened, but as far i can understand there is no management in the plugin for the native form callback up to the dart code and shared preferences.

onRatingChanged doesn't fire when i rate application

Describe the bug
when i rate app(select stars), i think that onRatingChanged will fire and i can understand the user rate and conditionally do something

 _rateMyApp.showStarRateDialog(
      context,
      title: 'Rate this app',
      message: 'You like this app ? Then take a little bit of your time to leave a rating :',
      onRatingChanged: (stars) {
        print('stars - ', stars)
      },
      ignoreIOS: false,
      starRatingOptions: StarRatingOptions(),
    );

but onRatingChanged doesn't fire when i rate application, or this method will fire only after click on submit button(which disabled in developer mode)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.