mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
CW-1000 Background sync improvements (#2142)
* feat: background sync improvements - dev options on ci build cherrypick - add permissions for background sync to AndroidManifestBase - enable desugaring + update java compatibility to 17 - update walletconnect_flutter_v2 - update ens_dart - update nostr_tools - add notification for new transactions found in background - expose more settings from flutter_daemon in UI - remove battery optimization setting when it's already disabled - fix notification permission handling - fix background sync last trigger saving - prevent notifications from being duplicated * potential fix for multiple notifications firing for the same tx * improve logging in background sync * ui improvements to ignore battery optimization popup * feat: logs for bg sync disable decred bgsync * fix: call store() directly to be sure that it is writing the data * chore: rename logs to background sync logs * Update lib/view_model/dashboard/dashboard_view_model.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * chore: remove unused key --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
e6c9cf54fb
commit
02e74b5997
48 changed files with 1373 additions and 68 deletions
|
@ -51,6 +51,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter_daemon/flutter_daemon.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../themes/theme_base.dart';
|
||||
|
@ -180,7 +181,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
isShowThirdYatIntroduction = false;
|
||||
unawaited(isBackgroundSyncEnabled());
|
||||
unawaited(isBatteryOptimizationEnabled());
|
||||
|
||||
unawaited(_loadConstraints());
|
||||
final _wallet = wallet;
|
||||
|
||||
if (_wallet.type == WalletType.monero) {
|
||||
|
@ -536,6 +537,88 @@ abstract class DashboardViewModelBase with Store {
|
|||
return resp;
|
||||
}
|
||||
|
||||
@observable
|
||||
late bool backgroundSyncNotificationsEnabled = sharedPreferences.getBool(PreferencesKey.backgroundSyncNotificationsEnabled) ?? false;
|
||||
|
||||
@action
|
||||
Future<void> setBackgroundSyncNotificationsEnabled(bool value) async {
|
||||
if (!value) {
|
||||
backgroundSyncNotificationsEnabled = false;
|
||||
sharedPreferences.setBool(PreferencesKey.backgroundSyncNotificationsEnabled, false);
|
||||
return;
|
||||
}
|
||||
PermissionStatus permissionStatus = await Permission.notification.status;
|
||||
if (permissionStatus != PermissionStatus.granted) {
|
||||
final resp = await Permission.notification.request();
|
||||
if (resp == PermissionStatus.denied) {
|
||||
throw Exception("Notification permission denied");
|
||||
}
|
||||
}
|
||||
backgroundSyncNotificationsEnabled = value;
|
||||
await sharedPreferences.setBool(PreferencesKey.backgroundSyncNotificationsEnabled, value);
|
||||
}
|
||||
|
||||
|
||||
bool get hasBgsyncNetworkConstraints => Platform.isAndroid;
|
||||
bool get hasBgsyncBatteryNotLowConstraints => Platform.isAndroid;
|
||||
bool get hasBgsyncChargingConstraints => Platform.isAndroid;
|
||||
bool get hasBgsyncDeviceIdleConstraints => Platform.isAndroid;
|
||||
|
||||
@observable
|
||||
bool backgroundSyncNetworkUnmetered = false;
|
||||
|
||||
@observable
|
||||
bool backgroundSyncBatteryNotLow = false;
|
||||
|
||||
@observable
|
||||
bool backgroundSyncCharging = false;
|
||||
|
||||
@observable
|
||||
bool backgroundSyncDeviceIdle = false;
|
||||
|
||||
Future<void> _loadConstraints() async {
|
||||
backgroundSyncNetworkUnmetered = await FlutterDaemon().getNetworkType();
|
||||
backgroundSyncBatteryNotLow = await FlutterDaemon().getBatteryNotLow();
|
||||
backgroundSyncCharging = await FlutterDaemon().getRequiresCharging();
|
||||
backgroundSyncDeviceIdle = await FlutterDaemon().getDeviceIdle();
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setBackgroundSyncNetworkUnmetered(bool value) async {
|
||||
backgroundSyncNetworkUnmetered = value;
|
||||
await FlutterDaemon().setNetworkType(value);
|
||||
if (await isBackgroundSyncEnabled()) {
|
||||
await enableBackgroundSync();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setBackgroundSyncBatteryNotLow(bool value) async {
|
||||
backgroundSyncBatteryNotLow = value;
|
||||
await FlutterDaemon().setBatteryNotLow(value);
|
||||
if (await isBackgroundSyncEnabled()) {
|
||||
await enableBackgroundSync();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setBackgroundSyncCharging(bool value) async {
|
||||
backgroundSyncCharging = value;
|
||||
await FlutterDaemon().setRequiresCharging(value);
|
||||
if (await isBackgroundSyncEnabled()) {
|
||||
await enableBackgroundSync();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> setBackgroundSyncDeviceIdle(bool value) async {
|
||||
backgroundSyncDeviceIdle = value;
|
||||
await FlutterDaemon().setDeviceIdle(value);
|
||||
if (await isBackgroundSyncEnabled()) {
|
||||
await enableBackgroundSync();
|
||||
}
|
||||
}
|
||||
|
||||
bool get hasBatteryOptimization => Platform.isAndroid;
|
||||
|
||||
@observable
|
||||
|
|
44
lib/view_model/dev/background_sync_logs_view_model.dart
Normal file
44
lib/view_model/dev/background_sync_logs_view_model.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter_daemon/flutter_daemon.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'background_sync_logs_view_model.g.dart';
|
||||
class BackgroundSyncLogsViewModel = BackgroundSyncLogsViewModelBase with _$BackgroundSyncLogsViewModel;
|
||||
|
||||
abstract class BackgroundSyncLogsViewModelBase with Store {
|
||||
final FlutterDaemon _daemon = FlutterDaemon();
|
||||
|
||||
@observable
|
||||
LogData? logData;
|
||||
|
||||
@observable
|
||||
bool isLoading = false;
|
||||
|
||||
@observable
|
||||
String? error;
|
||||
|
||||
@computed
|
||||
List<LogEntry> get logs => logData?.logs ?? [];
|
||||
|
||||
@computed
|
||||
List<LogSession> get sessions => logData?.sessions ?? [];
|
||||
|
||||
@action
|
||||
Future<void> loadLogs() async {
|
||||
isLoading = true;
|
||||
error = null;
|
||||
|
||||
try {
|
||||
logData = await _daemon.getLogs();
|
||||
} catch (e) {
|
||||
error = e.toString();
|
||||
} finally {
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> clearLogs() async {
|
||||
await _daemon.clearLogs();
|
||||
await loadLogs();
|
||||
}
|
||||
}
|
92
lib/view_model/dev/shared_preferences.dart
Normal file
92
lib/view_model/dev/shared_preferences.dart
Normal file
|
@ -0,0 +1,92 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
part 'shared_preferences.g.dart';
|
||||
|
||||
class DevSharedPreferences = DevSharedPreferencesBase with _$DevSharedPreferences;
|
||||
|
||||
enum PreferenceType {
|
||||
unknown,
|
||||
string,
|
||||
int,
|
||||
double,
|
||||
bool,
|
||||
listString
|
||||
}
|
||||
|
||||
abstract class DevSharedPreferencesBase with Store {
|
||||
DevSharedPreferencesBase() {
|
||||
SharedPreferences.getInstance().then((value) {
|
||||
sharedPreferences = value;
|
||||
});
|
||||
}
|
||||
|
||||
@observable
|
||||
SharedPreferences? sharedPreferences;
|
||||
|
||||
@computed
|
||||
List<String> get keys => (sharedPreferences?.getKeys().toList()?..sort()) ?? [];
|
||||
|
||||
@action
|
||||
Future<void> delete(String key) async {
|
||||
if (sharedPreferences == null) {
|
||||
return;
|
||||
}
|
||||
await sharedPreferences!.remove(key);
|
||||
}
|
||||
|
||||
dynamic get(String key) {
|
||||
if (sharedPreferences == null) {
|
||||
return null;
|
||||
}
|
||||
return sharedPreferences!.get(key);
|
||||
}
|
||||
|
||||
Future<void> set(String key, PreferenceType type, dynamic value) async {
|
||||
if (sharedPreferences == null) {
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case PreferenceType.string:
|
||||
await sharedPreferences!.setString(key, value as String);
|
||||
break;
|
||||
case PreferenceType.bool:
|
||||
await sharedPreferences!.setBool(key, value as bool);
|
||||
break;
|
||||
case PreferenceType.int:
|
||||
await sharedPreferences!.setInt(key, value as int);
|
||||
break;
|
||||
case PreferenceType.double:
|
||||
await sharedPreferences!.setDouble(key, value as double);
|
||||
break;
|
||||
case PreferenceType.listString:
|
||||
await sharedPreferences!.setStringList(key, List<String>.from(value as Iterable<dynamic>));
|
||||
break;
|
||||
default:
|
||||
throw Exception("Unknown preference type: $type");
|
||||
}
|
||||
}
|
||||
|
||||
PreferenceType getPreferenceType(String key) {
|
||||
if (sharedPreferences == null) {
|
||||
return PreferenceType.unknown;
|
||||
}
|
||||
final value = sharedPreferences!.get(key);
|
||||
if (value is String) {
|
||||
return PreferenceType.string;
|
||||
}
|
||||
if (value is bool) {
|
||||
return PreferenceType.bool;
|
||||
}
|
||||
if (value is int) {
|
||||
return PreferenceType.int;
|
||||
}
|
||||
if (value is double) {
|
||||
return PreferenceType.double;
|
||||
}
|
||||
if (value is List<String>) {
|
||||
return PreferenceType.listString;
|
||||
}
|
||||
return PreferenceType.unknown;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import 'package:cake_wallet/entities/evm_transaction_error_fees_handler.dart';
|
|||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/entities/parsed_address.dart';
|
||||
import 'package:cake_wallet/entities/template.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/transaction_description.dart';
|
||||
import 'package:cake_wallet/entities/wallet_contact.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
|
@ -52,6 +53,7 @@ import 'package:cw_core/wallet_type.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
part 'send_view_model.g.dart';
|
||||
|
||||
|
@ -587,6 +589,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
|||
transactionNote: note,
|
||||
));
|
||||
}
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
await sharedPreferences.setString(PreferencesKey.backgroundSyncLastTrigger(wallet.name), DateTime.now().add(Duration(minutes: 1)).toIso8601String());
|
||||
|
||||
state = TransactionCommitted();
|
||||
} catch (e) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue