✨ In app rating
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -42,6 +44,27 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
||||
|
||||
final Completer _bootCompleter = Completer();
|
||||
|
||||
void _requestRating() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.containsKey('first_boot_time')) {
|
||||
final rawTime = prefs.getString('first_boot_time');
|
||||
final time = DateTime.tryParse(rawTime ?? '');
|
||||
if (time != null &&
|
||||
time.isBefore(DateTime.now().subtract(const Duration(days: 3)))) {
|
||||
final inAppReview = InAppReview.instance;
|
||||
if (prefs.getBool('rating_requested') == true) return;
|
||||
if (await inAppReview.isAvailable()) {
|
||||
await inAppReview.requestReview();
|
||||
prefs.setBool('rating_requested', true);
|
||||
} else {
|
||||
log('Unable request app review, unavailable');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prefs.setString('first_boot_time', DateTime.now().toIso8601String());
|
||||
}
|
||||
}
|
||||
|
||||
void _updateNow(String localVersionString, String remoteVersionString) {
|
||||
context
|
||||
.showConfirmDialog(
|
||||
@@ -226,6 +249,9 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
||||
super.initState();
|
||||
_runPeriods();
|
||||
_checkForUpdate();
|
||||
_bootCompleter.future.then((_) {
|
||||
_requestRating();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
@@ -27,6 +27,8 @@ abstract class PlatformInfo {
|
||||
|
||||
static bool get canCacheImage => isAndroid || isIOS || isMacOS;
|
||||
|
||||
static bool get canRateTheApp => isIOS || isMacOS;
|
||||
|
||||
static bool get canRecord => (isMobile || isMacOS);
|
||||
|
||||
static bool get canPushNotification => isAndroid || isIOS || isMacOS;
|
||||
@@ -38,4 +40,4 @@ abstract class PlatformInfo {
|
||||
} catch (_) {}
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:solian/widgets/sized_container.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
@@ -52,8 +54,8 @@ class AboutScreen extends StatelessWidget {
|
||||
CenteredContainer(
|
||||
maxWidth: 280,
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
TextButton(
|
||||
@@ -92,6 +94,13 @@ class AboutScreen extends StatelessWidget {
|
||||
launchUrlString('https://solsynth.dev/terms');
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
style: denseButtonStyle,
|
||||
child: Text('serviceStatus'.tr),
|
||||
onPressed: () {
|
||||
launchUrlString('https://status.solsynth.dev');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -103,6 +112,34 @@ class AboutScreen extends StatelessWidget {
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
FutureBuilder(
|
||||
future: SharedPreferences.getInstance(),
|
||||
builder: (context, snapshot) {
|
||||
const textStyle = TextStyle(
|
||||
fontWeight: FontWeight.w300,
|
||||
fontSize: 12,
|
||||
);
|
||||
if (!snapshot.hasData ||
|
||||
!snapshot.data!.containsKey('first_boot_time')) {
|
||||
return Text(
|
||||
'firstBootTime'.trParams({'time': 'unknown'.tr}),
|
||||
style: textStyle,
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
'firstBootTime'.trParams({
|
||||
'time': DateFormat('yyyy-MM-dd').format(
|
||||
DateTime.tryParse(
|
||||
snapshot.data!.getString('first_boot_time')!,
|
||||
)?.toLocal() ??
|
||||
DateTime.now(),
|
||||
),
|
||||
}),
|
||||
style: textStyle,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:in_app_review/in_app_review.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:solian/exceptions/request.dart';
|
||||
@@ -205,6 +206,21 @@ class _SettingScreenState extends State<SettingScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
if (PlatformInfo.canRateTheApp)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.star),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||
title: Text('rateTheApp'.tr),
|
||||
subtitle: Text('rateTheAppDesc'.tr),
|
||||
onTap: () {
|
||||
final inAppReview = InAppReview.instance;
|
||||
|
||||
inAppReview.openStoreListing(
|
||||
appStoreId: '6499032345',
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.info_outline),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
|
Reference in New Issue
Block a user