Skip to content

Rate Reminder implementation #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open

Conversation

pritam-bs
Copy link

  • Both default and custom configuration strategies
  • Documentation for Rate Reminder usage
  • Example for Rate Reminder
  • Some clean-up in Message and Version-Control
  • Fix the template for enabling the test mode

- Both default and custom configuration strategies
- Documentation for Rate Reminder usage
- Example for Rate Reminder
- Some clean-up in Message and Version-Control
- Fix the template for enabling the test mode
Comment on lines +181 to +186
final rateReminderResponse = await http.get(
Uri.parse(
'$_baseUrl/notify/rate_reminder_v2?guid=${appInfoData.guid}',
),
headers: mutableHeaders,
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember @BucekJiri said that we don't have to fetch anything from the API except for app open, @pritam-bs can't we get the info here from app open response since we already fetched this information?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open app API does not provide the rate reminder information.
https://nstack-io.github.io/docs/docs/features/rate-reminder.html?sidebarScroll=0


final result = json.decode(rateReminderResponse.body);

if (rateReminderResponse.statusCode == 445) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very specific error code, are there any error codes we should handle?

Shouldn't all 4xx status codes be handled?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log message mainly informs the developer how many points must be triggered before the app can show the rate reminder alert.
the other errors will be logged in the catch block.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pritam-bs can we then add a comment right in the code for future generations?

@@ -8,6 +10,14 @@ typedef OnVersionUpdateNotification = void Function(
NStackVersionUpdate? updateInfo,
)?;

typedef OnRateReminder = void Function(
NStackRateReminder? rateReminderInfo,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be nullable, when onRateReminder we should expect the info to never be null.

Same for NStackRateReminderAnswer? rateReminderAnswer,

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the method in the type def itself should not be nullable, for example:

typedef OnRateReminderAnswered = void Function(
  NStackRateReminderAnswer rateReminderAnswer,
);

Then in the class you can make it nullable:

  final OnRateReminder? onRateReminder;
  final OnRateReminderAnswered? onRateReminderAnswered;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NStackRateReminder is nullable for the onRateReminder callback when the points are less than the certain threshold set in the console, and the devs can make a conditional check if needed.
But NStackRateReminderAnswer should not be nullable; I will fix that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pritam-bs if we recieve null from BE should we display the reminder? If we should not display it then we should not call the callback in the first place and it can be nun nullable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention was to enable developers to check the NStackRateReminder value and decide whether to do anything when it is null. Anyway, change it to not nullable.

- Remane Localization for Rate Reminder
- method in the type def made not nullable
@pritam-bs pritam-bs requested a review from hassan-saleh-ml May 14, 2024 12:41
Comment on lines 13 to 19
typedef OnRateReminder = void Function(
NStackRateReminder? rateReminderInfo,
);

typedef OnRateReminderAnswered = void Function(
NStackRateReminderAnswer rateReminderAnswer,
);
Copy link
Contributor

@nivisi nivisi May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On another topic for typedefs. There is no written naming convention available (based on a quick research I just did), but usually these callbacks must be named differently. Here are a few examples from the Flutter repo (see below).

I recommend to follow these rules:

Suggested change
typedef OnRateReminder = void Function(
NStackRateReminder? rateReminderInfo,
);
typedef OnRateReminderAnswered = void Function(
NStackRateReminderAnswer rateReminderAnswer,
);
typedef RateReminderCallback = void Function(
NStackRateReminder data,
);
typedef RateReminderAnswerCallback = void Function(
NStackRateReminderAnswer answer,
);

Examples

(see more here)

typedef ValueGetter<T> = T Function();

/// Signature for callbacks that filter an iterable.
typedef IterableFilter<T> = Iterable<T> Function(Iterable<T> input);

/// Signature of callbacks that have no arguments and return no data, but that
/// return a [Future] to indicate when their work is complete.
///
/// See also:
///
///  * [VoidCallback], a synchronous version of this signature.
///  * [AsyncValueGetter], a signature for asynchronous getters.
///  * [AsyncValueSetter], a signature for asynchronous setters.
typedef AsyncCallback = Future<void> Function();

/// Signature for callbacks that report that a value has been set and return a
/// [Future] that completes when the value has been saved.
///
/// See also:
///
///  * [ValueSetter], a synchronous version of this signature.
///  * [AsyncValueGetter], the getter equivalent of this signature.
typedef AsyncValueSetter<T> = Future<void> Function(T value);
typedef GestureDragEndCallback = void Function(DragEndDetails details);

/// Signature for when the pointer that previously triggered a
/// [GestureDragDownCallback] did not complete.
///
/// Used by [DragGestureRecognizer.onCancel].
typedef GestureDragCancelCallback = void Function();

/// Signature for a function that builds a [VelocityTracker].
///
/// Used by [DragGestureRecognizer.velocityTrackerBuilder].
typedef GestureVelocityTrackerBuilder = VelocityTracker Function(PointerEvent event);

'If onRateReminder is null, then onAnswered must not be null.',
);

final Widget? child;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put child widgets last in the property list. Again, this is a convention that majority of Flutter widgets follow (and we do follow it as well). Same for the constructor parameter list

There's a related rule for this: https://dart.dev/tools/linter-rules/sort_child_properties_last

this.onAnswered,
}) : assert(
onRateReminder != null || onAnswered != null,
'If onRateReminder is null, then onAnswered must not be null.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'If onRateReminder is null, then onAnswered must not be null.',
'Either onRateReminder or onAnswered must be provided.',

Comment on lines 20 to 21
final void Function(NStackRateReminder?)? onRateReminder;
final void Function(NStackRateReminderAnswer)? onAnswered;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use our typedefs here

Comment on lines 32 to 40
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) async {
final rateReminderInfo =
await context.nstack.rateReminders.getRateReminderInfo(
defaultLocale: Localizations.localeOf(context),
);
_onRateReminder(rateReminderInfo);
},
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a post frame callback in didChangeDependencies, it's only required in initState.

Although are we sure this needs to be done in didChangeDependencies? It might get executed quite frequently here

rateReminder.localization?.laterBtn ?? _laterButtonTitleFallback,
);

Future<void> buttonAction(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this out of the build method

Comment on lines 258 to 265
bool? testMode,
}) : super(
key: key,
child: child,
platformOverride: platformOverride,
onComplete: onComplete,
config: config,
testMode: testMode ?? false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool? testMode,
}) : super(
key: key,
child: child,
platformOverride: platformOverride,
onComplete: onComplete,
config: config,
testMode: testMode ?? false,
bool testMode = false,
}) : super(
key: key,
child: child,
platformOverride: platformOverride,
onComplete: onComplete,
config: config,
testMode: testMode,

Comment on lines 24 to 27
State<StatefulWidget> createState() => _NStackRateReminderWidgetSate();
}

class _NStackRateReminderWidgetSate extends State<NStackRateReminderWidget> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
State<StatefulWidget> createState() => _NStackRateReminderWidgetSate();
}
class _NStackRateReminderWidgetSate extends State<NStackRateReminderWidget> {
State<StatefulWidget> createState() => _NStackRateReminderWidgetState();
}
class _NStackRateReminderWidgetState extends State<NStackRateReminderWidget> {

@pritam-bs pritam-bs requested a review from nivisi May 17, 2024 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants