|
...
|
...
|
@@ -10,11 +10,14 @@ import '../widgets/app_review_prompt_dialog.dart'; |
|
|
|
class AppReviewPromptLogic {
|
|
|
|
AppReviewPromptLogic({
|
|
|
|
required LocalStorage storage,
|
|
|
|
required int Function() userIdProvider,
|
|
|
|
PlatformHostApi? platformHostApi,
|
|
|
|
}) : _storage = storage,
|
|
|
|
_userIdProvider = userIdProvider,
|
|
|
|
_platformHostApi = platformHostApi ?? PlatformHostApi();
|
|
|
|
|
|
|
|
final LocalStorage _storage;
|
|
|
|
final int Function() _userIdProvider;
|
|
|
|
final PlatformHostApi _platformHostApi;
|
|
|
|
|
|
|
|
bool _isShowing = false;
|
|
...
|
...
|
@@ -25,9 +28,10 @@ class AppReviewPromptLogic { |
|
|
|
bool canShowPrompt(BuildContext context) {
|
|
|
|
if (_isShowing || !context.mounted) return false;
|
|
|
|
|
|
|
|
final userId = _currentUserId;
|
|
|
|
if (userId == null) return false;
|
|
|
|
final now = DateTime.now();
|
|
|
|
final nextShowAt = _storage.appReviewPromptNextShowAt;
|
|
|
|
return nextShowAt == null || !now.isBefore(nextShowAt);
|
|
|
|
return _canShowAt(userId, now);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> maybeShowPrompt(BuildContext context) async {
|
|
...
|
...
|
@@ -59,6 +63,42 @@ class AppReviewPromptLogic { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Records a qualified sleep-report view. The prompt is deliberately shown
|
|
|
|
/// only on the next app launch after the user reaches the home page.
|
|
|
|
Future<void> recordPromptEligibility() async {
|
|
|
|
final userId = _currentUserId;
|
|
|
|
if (userId == null) return;
|
|
|
|
|
|
|
|
final now = DateTime.now();
|
|
|
|
if (!_canShowAt(userId, now)) return;
|
|
|
|
|
|
|
|
if (_storage.hasAppReviewPromptPending(userId)) return;
|
|
|
|
|
|
|
|
await _storage.setAppReviewPromptPending(userId);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consumes a pending qualified view when the app next enters its home page.
|
|
|
|
Future<void> maybeShowPendingPrompt(BuildContext context) async {
|
|
|
|
if (_isShowing || !context.mounted) return;
|
|
|
|
|
|
|
|
final userId = _currentUserId;
|
|
|
|
if (userId == null) return;
|
|
|
|
|
|
|
|
if (!_storage.hasAppReviewPromptPending(userId)) return;
|
|
|
|
|
|
|
|
final now = DateTime.now();
|
|
|
|
if (!_canShowAt(userId, now)) {
|
|
|
|
await _storage.clearAppReviewPromptPending(userId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear before presenting so a recreated home page cannot show it twice.
|
|
|
|
await _storage.clearAppReviewPromptPending(userId);
|
|
|
|
if (context.mounted) {
|
|
|
|
await maybeShowPrompt(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _requestAppReview() async {
|
|
|
|
if (kIsWeb || defaultTargetPlatform != TargetPlatform.iOS) return;
|
|
|
|
|
|
...
|
...
|
@@ -83,6 +123,21 @@ class AppReviewPromptLogic { |
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _coolDown(Duration duration) {
|
|
|
|
return _storage.setAppReviewPromptNextShowAt(DateTime.now().add(duration));
|
|
|
|
final userId = _currentUserId;
|
|
|
|
if (userId == null) return Future.value();
|
|
|
|
return _storage.setAppReviewPromptNextShowAt(
|
|
|
|
userId,
|
|
|
|
DateTime.now().add(duration),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
int? get _currentUserId {
|
|
|
|
final userId = _userIdProvider();
|
|
|
|
return userId > 0 ? userId : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool _canShowAt(int userId, DateTime now) {
|
|
|
|
final nextShowAt = _storage.appReviewPromptNextShowAt(userId);
|
|
|
|
return nextShowAt == null || !now.isBefore(nextShowAt);
|
|
|
|
}
|
|
|
|
} |
...
|
...
|
|