From 5dda36af8db5ac7b950de953621255804ac65ffc Mon Sep 17 00:00:00 2001 From: himeshr Date: Wed, 25 Oct 2023 18:26:02 +0530 Subject: [PATCH] #1149 | Disable manual sync-button when background auto-sync is in progress --- .../openchs-android/src/action/SyncActions.js | 14 ++++- .../src/service/SyncService.js | 5 +- packages/openchs-android/src/task/Sync.js | 56 +++++++++++++++++-- .../src/views/SyncComponent.js | 14 ++++- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/packages/openchs-android/src/action/SyncActions.js b/packages/openchs-android/src/action/SyncActions.js index 90ba028b7..e55d7276b 100644 --- a/packages/openchs-android/src/action/SyncActions.js +++ b/packages/openchs-android/src/action/SyncActions.js @@ -10,7 +10,8 @@ class SyncActions { progress: 0, message: '', syncMessage: '', - startSync: false + startSync: false, + backgroundSyncInProgress: false }; } @@ -50,6 +51,13 @@ class SyncActions { } } + static onBackgroundSyncStatusChange(state, action, context) { + return { + ...state, + backgroundSyncInProgress: action.backgroundSyncInProgress + } + } + static onMessageCallback(state, action, context) { return { ...state, @@ -66,7 +74,8 @@ const SyncActionNames = { ON_ERROR: `${ActionPrefix}.ON_ERROR`, ON_CONNECTION_CHANGE: `${ActionPrefix}.ON_CONNECTION_CHANGE`, ON_UPDATE: `${ActionPrefix}.ON_UPDATE`, - ON_MESSAGE_CALLBACK: `${ActionPrefix}.ON_MESSAGE_CALLBACK` + ON_MESSAGE_CALLBACK: `${ActionPrefix}.ON_MESSAGE_CALLBACK`, + ON_BACKGROUND_SYNC_STATUS_CHANGE: `${ActionPrefix}.ON_BACKGROUND_SYNC_STATUS_CHANGE` }; const SyncActionMap = new Map([ @@ -76,6 +85,7 @@ const SyncActionMap = new Map([ [SyncActionNames.ON_CONNECTION_CHANGE, SyncActions.onConnectionChange], [SyncActionNames.ON_UPDATE, SyncActions.onUpdate], [SyncActionNames.ON_MESSAGE_CALLBACK, SyncActions.onMessageCallback], + [SyncActionNames.ON_BACKGROUND_SYNC_STATUS_CHANGE, SyncActions.onBackgroundSyncStatusChange], ]); export { diff --git a/packages/openchs-android/src/service/SyncService.js b/packages/openchs-android/src/service/SyncService.js index 7d43dd60b..edcd6445f 100644 --- a/packages/openchs-android/src/service/SyncService.js +++ b/packages/openchs-android/src/service/SyncService.js @@ -75,7 +75,10 @@ class SyncService extends BaseService { .then(() => Promise.resolve(progressBarStatus.onSyncComplete())) .then(() => Promise.resolve(this.logSyncCompleteEvent(syncStartTime))) .then(() => this.clearDataIn([RuleFailureTelemetry])) - .then(() => this.downloadNewsImages()); + .then(() => this.downloadNewsImages()) + .then(() => { + return isOnlyUploadRequired; + }); // Even blank dataServerSync with no data in or out takes quite a while. // Don't do it twice if no image sync required diff --git a/packages/openchs-android/src/task/Sync.js b/packages/openchs-android/src/task/Sync.js index e9819ff75..c3b6e17d2 100644 --- a/packages/openchs-android/src/task/Sync.js +++ b/packages/openchs-android/src/task/Sync.js @@ -10,10 +10,26 @@ import UserInfoService from "../service/UserInfoService"; import _ from "lodash"; import SettingsService from '../service/SettingsService'; import EnvironmentConfig from "../framework/EnvironmentConfig"; +import {SyncActionNames as SyncActions} from '../action/SyncActions'; +import RuleEvaluationService from '../service/RuleEvaluationService'; +import ProgramConfigService from '../service/ProgramConfigService'; +import MessageService from '../service/MessageService'; +import RuleService from '../service/RuleService'; +import PrivilegeService from '../service/PrivilegeService'; +import {IndividualSearchActionNames as IndividualSearchActions} from '../action/individual/IndividualSearchActions'; +import {LandingViewActions} from '../action/LandingViewActions'; class Sync extends BaseTask { async execute() { + const dispatchAction = (action, params) => { + const type = action instanceof Function ? action.Id : action; + if (General.canLog(General.LogLevel.Debug)) + General.logDebug('BaseService', `Dispatching action: ${JSON.stringify(type)}`); + return GlobalContext.getInstance().reduxStore.dispatch({type, ...params}); + } + try { + General.logInfo("Sync", "Starting background sync"); const globalContext = GlobalContext.getInstance(); let settings = globalContext.beanRegistry.getService(SettingsService).getSettings(); if (_.isNil(settings.userId)) { @@ -29,17 +45,21 @@ class Sync extends BaseTask { General.logInfo("Sync", "Starting SyncService"); General.logInfo("Sync", "Getting SyncService"); const syncService = globalContext.beanRegistry.getService("syncService"); + + dispatchAction(SyncActions.ON_BACKGROUND_SYNC_STATUS_CHANGE, {backgroundSyncInProgress: true}); General.logInfo("Sync", "Getting connection info"); let connectionInfo; await NetInfo.fetch().then((state) => connectionInfo = state); General.logInfo("Sync", "Calling syncService.sync"); return syncService.sync(EntityMetaData.model(), (progress) => { - General.logInfo("Sync", progress); - }, - (message) => { - }, connectionInfo, Date.now(), SyncService.syncSources.ONLY_UPLOAD_BACKGROUND_JOB, null).then(() => General.logInfo("Sync", "Sync completed")).catch((e) => { - ErrorHandler.postScheduledJobError(e); - }); + General.logInfo("Sync", progress); + }, + (message) => { + }, connectionInfo, Date.now(), SyncService.syncSources.ONLY_UPLOAD_BACKGROUND_JOB, null) + .then(this.performPostBackgroundSyncActions(dispatchAction, globalContext)) + .catch((e) => { + ErrorHandler.postScheduledJobError(e); + }); } catch (e) { if (e instanceof AuthenticationError && e.code === NO_USER) { return; @@ -47,6 +67,30 @@ class Sync extends BaseTask { ErrorHandler.postScheduledJobError(e); } } + + performPostBackgroundSyncActions(dispatchAction, globalContext) { + return (updatedSyncSource) => { + General.logInfo("Sync", "Sync completed") + dispatchAction(SyncActions.ON_BACKGROUND_SYNC_STATUS_CHANGE, {backgroundSyncInProgress: false}); + if (updatedSyncSource === SyncService.syncSources.BACKGROUND_JOB) { + General.logInfo("Background Sync", "Full Background Sync completed, performing reset") + setTimeout(() => { + globalContext.beanRegistry.getService(RuleEvaluationService).init(); + globalContext.beanRegistry.getService(ProgramConfigService).init(); + globalContext.beanRegistry.getService(MessageService).init(); + globalContext.beanRegistry.getService(RuleService).init(); + globalContext.beanRegistry.getService(PrivilegeService).deleteRevokedEntities(); + //To load subjectType after sync + globalContext.beanRegistry.getService(IndividualSearchActions.ON_LOAD); + + //To re-render LandingView after sync + dispatchAction(LandingViewActions.ON_LOAD, {syncRequired: false}); + }, 1); + globalContext.beanRegistry.getService(SettingsService).initLanguages(); + General.logInfo("Background Sync", 'Background Sync completed, reset completed'); + } + }; + } } export default new Sync(); diff --git a/packages/openchs-android/src/views/SyncComponent.js b/packages/openchs-android/src/views/SyncComponent.js index bd7f1a205..44ccb282b 100644 --- a/packages/openchs-android/src/views/SyncComponent.js +++ b/packages/openchs-android/src/views/SyncComponent.js @@ -208,9 +208,18 @@ class SyncComponent extends AbstractComponent { alignSelf: 'center', fontSize: 30 }); + const syncDisabledIcon = this.props.icon("sync-circle", { + color: Colors.DisabledButtonColor, + alignSelf: 'center', + fontSize: 30 + }); const entitySyncStatusService = this.context.getService(EntitySyncStatusService); const totalPending = entitySyncStatusService.getTotalEntitiesPending(); - return !this.state.syncing && totalPending > 0 ? : icon; + if(this.state.backgroundSyncInProgress) { + return syncDisabledIcon; + } else { + return !this.state.syncing && totalPending > 0 ? : icon; + } } render() { @@ -218,7 +227,8 @@ class SyncComponent extends AbstractComponent { {this.renderSyncModal()} this.sync()}> + onPress={() => this.sync()} + disabled={this.state.backgroundSyncInProgress}>