Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #150 from MXCzkEVM/bg_feat
Browse files Browse the repository at this point in the history
Bg service status update
  • Loading branch information
reasje authored Jan 17, 2024
2 parents 1c4b46b + 107ff90 commit f1e7583
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 138 deletions.
9 changes: 6 additions & 3 deletions assets/flutter_i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,12 +325,15 @@
"background_fetch_notice_title": "Optimize Your AXS Wallet Experience",
"background_fetch_notice_text": "To ensure peak performance of the AXS Wallet, we recommend keeping the app active in the background and excluding it from battery optimization settings. This helps maintain seamless functionality and uninterrupted access to your wallet.",
"acknowledge": "Acknowledge",
"Background_notifications_service_launched_successfully": "Background notifications service launched successfully.",
"background_notifications_service_launched_successfully": "Background notifications service launched successfully.",
"unable_to_launch_background_notification_service": "Unable to launch background notification service.",
"background_notifications_service_disabled_successfully": "Background notifications service disabled successfully.",
"low_balance": "Low balance",
"expected_transaction_fee": "Expected transaction fee",
"expected_epoch_occur": "Expected epoch occurrence",
"background_notifications_frequency": "Background notifications frequency",
"background_notifications": "Background notifications",
"occurrence": "Occurrence",
"frequency": "Frequency"
"frequency": "Frequency",
"experiencing_issues": "Experiencing issues?",
"background_service_solution": "Try re-enabling the app or check the battery optimization settings."
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'dart:io';
import 'package:datadashwallet/common/common.dart';
import 'package:datadashwallet/core/core.dart';
import 'package:datadashwallet/features/common/contract/token_contract_use_case.dart';
import 'package:datadashwallet/features/settings/subfeatures/chain_configuration/domain/chain_configuration_use_case.dart';
import 'package:mxc_logic/mxc_logic.dart';
import 'package:background_fetch/background_fetch.dart' as bgFetch;

import '../../../../../main.dart';
import 'background_fetch_config_repository.dart';

class BackgroundFetchConfigUseCase extends ReactiveUseCase {
Expand Down Expand Up @@ -35,14 +37,14 @@ class BackgroundFetchConfigUseCase extends ReactiveUseCase {

void initialize() {
_chainConfigurationUseCase.selectedNetwork.listen((network) {
if (network != null && !Config.isMxcChains(network.chainId)) {
final isMXCChains =
network != null && !Config.isMxcChains(network.chainId);
final periodicalCallData = _repository.item;
if (!isMXCChains) {
bgFetch.BackgroundFetch.stop(Config.axsPeriodicalTask);
} else if (isMXCChains && periodicalCallData.serviceEnabled) {
startBGFetch(periodicalCallData.duration);
}
// else if (network != null && Config.isMxcChains(network.chainId)) {
// isBGFetchEnabled(_repository.item) {

// }
// }
});
}

Expand Down Expand Up @@ -141,4 +143,55 @@ class BackgroundFetchConfigUseCase extends ReactiveUseCase {
periodicalCallData.expectedTransactionFeeEnabled ||
periodicalCallData.expectedEpochOccurrenceEnabled ||
periodicalCallData.lowBalanceLimitEnabled;

// delay is in minutes
Future<bool> startBGFetch(int delay) async {
try {
// Stop If any is running
await stopBGFetch();

final configurationState = await bgFetch.BackgroundFetch.configure(
bgFetch.BackgroundFetchConfig(
minimumFetchInterval: delay,
stopOnTerminate: false,
enableHeadless: true,
startOnBoot: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: bgFetch.NetworkType.ANY),
callbackDispatcherForeGround);
// Android Only
final backgroundFetchState =
await bgFetch.BackgroundFetch.registerHeadlessTask(
callbackDispatcher);

final scheduleState =
await bgFetch.BackgroundFetch.scheduleTask(bgFetch.TaskConfig(
taskId: Config.axsPeriodicalTask,
delay: delay * 60 * 1000,
periodic: true,
requiresNetworkConnectivity: true,
startOnBoot: true,
stopOnTerminate: false,
requiredNetworkType: bgFetch.NetworkType.ANY,
));

if (scheduleState &&
configurationState == bgFetch.BackgroundFetch.STATUS_AVAILABLE ||
configurationState == bgFetch.BackgroundFetch.STATUS_RESTRICTED &&
(Platform.isAndroid ? backgroundFetchState : true)) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}

Future<int> stopBGFetch() async {
return await bgFetch.BackgroundFetch.stop(Config.axsPeriodicalTask);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:mxc_ui/mxc_ui.dart';

import 'notifications_presenter.dart';
import 'notifications_state.dart';
import 'widgets/bg_service_information_widget.dart';
import 'widgets/switch_row_item.dart';

class NotificationsPage extends HookConsumerWidget {
Expand All @@ -32,6 +33,10 @@ class NotificationsPage extends HookConsumerWidget {
notificationsState.periodicalCallData!.duration);

final isMXCChains = Config.isMxcChains(notificationsState.network!.chainId);
final bgServiceEnabled =
notificationsState.periodicalCallData!.serviceEnabled;

final isSettingsChangeEnabled = isMXCChains && bgServiceEnabled;

String translate(String text) => FlutterI18n.translate(context, text);

Expand Down Expand Up @@ -71,24 +76,28 @@ class NotificationsPage extends HookConsumerWidget {
],
),
const SizedBox(height: Sizes.spaceNormal),
Text(
translate('background_notifications_frequency'),
style: FontTheme.of(context).body2.primary(),
SwitchRowItem(
title: translate('background_notifications'),
value: notificationsState.periodicalCallData!.serviceEnabled,
onChanged: notificationsPresenter.changeEnableService,
enabled: isMXCChains,
textTrailingWidget: const BGServiceInformation(),
),
const SizedBox(height: Sizes.spaceNormal),
MXCDropDown(
key: const Key('bgNotificationsFrequencyDropDown'),
onTap: notificationsPresenter.showBGFetchFrequencyDialog,
selectedItem: frequency.toStringFormatted(),
enabled: isMXCChains,
enabled: isSettingsChangeEnabled &&
notificationsState.periodicalCallData!.serviceEnabled,
),
const SizedBox(height: Sizes.spaceNormal),
SwitchRowItem(
title: translate('low_balance'),
value:
notificationsState.periodicalCallData!.lowBalanceLimitEnabled,
onChanged: notificationsPresenter.enableLowBalanceLimit,
enabled: isMXCChains,
enabled: isSettingsChangeEnabled,
),
MxcTextField(
key: const ValueKey('lowBalanceTextField'),
Expand All @@ -97,7 +106,7 @@ class NotificationsPage extends HookConsumerWidget {
keyboardType: TextInputType.number,
action: TextInputAction.next,
suffixText: ref.watch(state).network!.symbol,
readOnly: !isMXCChains ||
readOnly: !isSettingsChangeEnabled ||
!notificationsState.periodicalCallData!.lowBalanceLimitEnabled,
hasClearButton: false,
validator: (value) {
Expand Down Expand Up @@ -135,7 +144,7 @@ class NotificationsPage extends HookConsumerWidget {
value: notificationsState
.periodicalCallData!.expectedTransactionFeeEnabled,
onChanged: notificationsPresenter.enableExpectedGasPrice,
enabled: isMXCChains,
enabled: isSettingsChangeEnabled,
),
MxcTextField(
key: const ValueKey('expectedTransactionFeeTextField'),
Expand All @@ -144,7 +153,7 @@ class NotificationsPage extends HookConsumerWidget {
keyboardType: TextInputType.number,
action: TextInputAction.next,
suffixText: ref.watch(state).network!.symbol,
readOnly: !isMXCChains ||
readOnly: !isSettingsChangeEnabled ||
!notificationsState
.periodicalCallData!.expectedTransactionFeeEnabled,
hasClearButton: false,
Expand Down Expand Up @@ -183,7 +192,7 @@ class NotificationsPage extends HookConsumerWidget {
value: notificationsState
.periodicalCallData!.expectedEpochOccurrenceEnabled,
onChanged: notificationsPresenter.enableExpectedEpochQuantity,
enabled: isMXCChains,
enabled: isSettingsChangeEnabled,
),
const SizedBox(height: Sizes.spaceNormal),
MXCDropDown(
Expand All @@ -195,7 +204,7 @@ class NotificationsPage extends HookConsumerWidget {
.periodicalCallData!.expectedEpochOccurrence);
},
selectedItem: '$expectedEpochOccur Epoch occurrence',
enabled: isMXCChains &&
enabled: isSettingsChangeEnabled &&
notificationsState
.periodicalCallData!.expectedEpochOccurrenceEnabled,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ class NotificationsPresenter extends CompletePresenter<NotificationsState>
state.periodicalCallData!.duration));
}

void changeEnableService(bool value) {
final newPeriodicalCallData =
state.periodicalCallData!.copyWith(serviceEnabled: value);
backgroundFetchConfigUseCase.updateItem(newPeriodicalCallData);
}

void enableExpectedGasPrice(bool value) {
final newPeriodicalCallData = state.periodicalCallData!
.copyWith(expectedTransactionFeeEnabled: value);
Expand Down Expand Up @@ -176,83 +182,47 @@ class NotificationsPresenter extends CompletePresenter<NotificationsState>

void checkPeriodicalCallDataChange(
PeriodicalCallData newPeriodicalCallData) async {
bool newNoneEnabled =
!(newPeriodicalCallData.expectedEpochOccurrenceEnabled ||
newPeriodicalCallData.expectedTransactionFeeEnabled ||
newPeriodicalCallData.lowBalanceLimitEnabled);

if (state.periodicalCallData != null) {
if (backgroundFetchConfigUseCase.isServicesEnabledStatusChanged(
newPeriodicalCallData, state.periodicalCallData!) &&
backgroundFetchConfigUseCase.hasAnyServiceBeenEnabled(
newPeriodicalCallData, state.periodicalCallData!) ||
backgroundFetchConfigUseCase.hasDurationChanged(
newPeriodicalCallData, state.periodicalCallData!)) {}

// none enabled means stopped || was stopped
if (newNoneEnabled == true) {
await stopBGFetch();
}
// If none was enabled & now one is enabled => Start BG service
// Other wise It was enabled so start BG service in case It's not running
else if (noneEnabled == true && newNoneEnabled == false) {
await showBackgroundFetchAlertDialog(context: context!);
startBGFetch(newPeriodicalCallData.duration);
final isBGServiceChanged = state.periodicalCallData!.serviceEnabled !=
newPeriodicalCallData.serviceEnabled;
final bgServiceDurationChanged =
state.periodicalCallData!.duration != newPeriodicalCallData.duration;

if (isBGServiceChanged && newPeriodicalCallData.serviceEnabled == true) {
startBGFetch(
delay: newPeriodicalCallData.duration, showBGFetchAlert: true);
} else if (isBGServiceChanged &&
newPeriodicalCallData.serviceEnabled == false) {
stopBGFetch(showSnackbar: true);
} else if (bgServiceDurationChanged) {
startBGFetch(
delay: newPeriodicalCallData.duration, showBGFetchAlert: false);
}
}
noneEnabled = newNoneEnabled;

notify(() => state.periodicalCallData = newPeriodicalCallData);
}

// delay is in minutes
void startBGFetch(int delay) async {
try {
// Stop If any is running
await stopBGFetch();

final configurationState = await bgFetch.BackgroundFetch.configure(
bgFetch.BackgroundFetchConfig(
minimumFetchInterval: 15,
stopOnTerminate: false,
enableHeadless: true,
startOnBoot: true,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: bgFetch.NetworkType.ANY),
callbackDispatcherForeGround);
// Android Only
final backgroundFetchState =
await bgFetch.BackgroundFetch.registerHeadlessTask(
callbackDispatcher);

final scheduleState =
await bgFetch.BackgroundFetch.scheduleTask(bgFetch.TaskConfig(
taskId: Config.axsPeriodicalTask,
delay: delay * 60 * 1000,
periodic: true,
requiresNetworkConnectivity: true,
startOnBoot: true,
stopOnTerminate: false,
requiredNetworkType: bgFetch.NetworkType.ANY,
));

if (scheduleState &&
configurationState == bgFetch.BackgroundFetch.STATUS_AVAILABLE ||
configurationState == bgFetch.BackgroundFetch.STATUS_RESTRICTED &&
(Platform.isAndroid ? backgroundFetchState : true)) {
showBGFetchSuccessSnackBar();
} else {
showBGFetchFailureSnackBar();
}
} catch (e) {
void startBGFetch(
{required int delay, required bool showBGFetchAlert}) async {
if (showBGFetchAlert) {
await showBackgroundFetchAlertDialog(context: context!);
}
final success = await backgroundFetchConfigUseCase.startBGFetch(delay);
if (success) {
showBGFetchSuccessSnackBar();
} else {
showBGFetchFailureSnackBar();
}
}

Future<int> stopBGFetch() async {
return await bgFetch.BackgroundFetch.stop(Config.axsPeriodicalTask);
Future<int> stopBGFetch({required bool showSnackbar}) async {
final res = await bgFetch.BackgroundFetch.stop(Config.axsPeriodicalTask);
if (showSnackbar) {
showBGFetchDisableSuccessSnackBar();
}
return res;
}

void showBGFetchFailureSnackBar() {
Expand All @@ -266,7 +236,14 @@ class NotificationsPresenter extends CompletePresenter<NotificationsState>
showSnackBar(
context: context!,
content: translate(
'Background_notifications_service_launched_successfully')!);
'background_notifications_service_launched_successfully')!);
}

void showBGFetchDisableSuccessSnackBar() {
showSnackBar(
context: context!,
content: translate(
'background_notifications_service_disabled_successfully')!);
}

@override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:mxc_ui/mxc_ui.dart';

class BGServiceInformation extends StatelessWidget {
const BGServiceInformation({super.key});

@override
Widget build(BuildContext context) {
return Tooltip(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(15)),
color: ColorsTheme.of(context).mainRed,
),
showDuration: const Duration(seconds: 5),
triggerMode: TooltipTriggerMode.tap,
richMessage: TextSpan(
style: FontTheme.of(context)
.subtitle1()
.copyWith(color: ColorsTheme.of(context).chipTextBlack),
children: [
TextSpan(
text: FlutterI18n.translate(context, 'experiencing_issues'),
style: FontTheme.of(context)
.subtitle2()
.copyWith(color: ColorsTheme.of(context).chipTextBlack),
),
const TextSpan(text: ' '),
TextSpan(
text:
FlutterI18n.translate(context, 'background_service_solution'),
style: FontTheme.of(context)
.subtitle1()
.copyWith(color: ColorsTheme.of(context).chipTextBlack),
),
]),
preferBelow: false,
child: Icon(
Icons.info_rounded,
color: ColorsTheme.of(context).iconPrimary,
),
);
}
}
Loading

0 comments on commit f1e7583

Please sign in to comment.