diff --git a/ElectronClient/app/gui/SideBar.jsx b/ElectronClient/app/gui/SideBar.jsx index 8cc2aafb5..f37a080aa 100644 --- a/ElectronClient/app/gui/SideBar.jsx +++ b/ElectronClient/app/gui/SideBar.jsx @@ -505,7 +505,13 @@ class SideBarComponent extends React.Component { decryptionReportText = _('Decrypting items: %d/%d', this.props.decryptionWorker.itemIndex + 1, this.props.decryptionWorker.itemCount); } + let resourceFetcherText = ''; + if (this.props.resourceFetcher && this.props.resourceFetcher.toFetchCount) { + resourceFetcherText = _('Fetching resources: %d', this.props.resourceFetcher.toFetchCount); + } + let lines = Synchronizer.reportToLines(this.props.syncReport); + if (resourceFetcherText) lines.push(resourceFetcherText); if (decryptionReportText) lines.push(decryptionReportText); const syncReportText = []; for (let i = 0; i < lines.length; i++) { @@ -547,6 +553,7 @@ const mapStateToProps = state => { theme: state.settings.theme, collapsedFolderIds: state.collapsedFolderIds, decryptionWorker: state.decryptionWorker, + resourceFetcher: state.resourceFetcher, }; }; diff --git a/ReactNativeClient/lib/BaseApplication.js b/ReactNativeClient/lib/BaseApplication.js index 53ea0cf7c..21c532239 100644 --- a/ReactNativeClient/lib/BaseApplication.js +++ b/ReactNativeClient/lib/BaseApplication.js @@ -389,6 +389,7 @@ class BaseApplication { reg.dispatch = this.store().dispatch; BaseSyncTarget.dispatch = this.store().dispatch; DecryptionWorker.instance().dispatch = this.store().dispatch; + ResourceFetcher.instance().dispatch = this.store().dispatch; } async readFlagsFromFile(flagPath) { diff --git a/ReactNativeClient/lib/models/Resource.js b/ReactNativeClient/lib/models/Resource.js index 477f4988d..aced75d0e 100644 --- a/ReactNativeClient/lib/models/Resource.js +++ b/ReactNativeClient/lib/models/Resource.js @@ -37,6 +37,11 @@ class Resource extends BaseItem { return this.modelSelectAll(sql, [Resource.FETCH_STATUS_IDLE]); } + static async needToBeFetchedCount() { + const r = await this.db().selectOne('SELECT count(*) as total FROM resource_local_states WHERE fetch_status = ?', [Resource.FETCH_STATUS_IDLE]); + return r ? r['total'] : 0; + } + static fsDriver() { if (!Resource.fsDriver_) Resource.fsDriver_ = new FsDriverDummy(); return Resource.fsDriver_; diff --git a/ReactNativeClient/lib/reducer.js b/ReactNativeClient/lib/reducer.js index 5e0c5b78e..936e75304 100644 --- a/ReactNativeClient/lib/reducer.js +++ b/ReactNativeClient/lib/reducer.js @@ -38,7 +38,10 @@ const defaultState = { itemIndex: 0, itemCount: 0, }, - selectedNoteTags: [] + selectedNoteTags: [], + resourceFetcher: { + toFetchCount: 0, + }, }; const stateUtils = {}; @@ -604,6 +607,14 @@ const reducer = (state = defaultState, action) => { newState.decryptionWorker = decryptionWorker; break; + case 'RESOURCE_FETCHER_SET': + + newState = Object.assign({}, state); + const rf = Object.assign({}, action); + delete rf.type; + newState.resourceFetcher = rf; + break; + case 'LOAD_CUSTOM_CSS': newState = Object.assign({}, state); diff --git a/ReactNativeClient/lib/services/ResourceFetcher.js b/ReactNativeClient/lib/services/ResourceFetcher.js index 7aca8511e..cae90babc 100644 --- a/ReactNativeClient/lib/services/ResourceFetcher.js +++ b/ReactNativeClient/lib/services/ResourceFetcher.js @@ -9,7 +9,9 @@ class ResourceFetcher extends BaseService { constructor(fileApi = null) { super(); - + + this.dispatch = (action) => {}; + this.setFileApi(fileApi); this.logger_ = new Logger(); this.queue_ = []; @@ -59,6 +61,19 @@ class ResourceFetcher extends BaseService { return -1; } + updateReport() { + if (this.updateReportIID_) return; + + this.updateReportIID_ = setTimeout(async () => { + const toFetchCount = await Resource.needToBeFetchedCount(); + this.dispatch({ + type: 'RESOURCE_FETCHER_SET', + toFetchCount: toFetchCount, + }); + this.updateReportIID_ = null; + }, 2000); + } + queueDownload(resourceId, priority = null) { if (priority === null) priority = 'normal'; @@ -73,6 +88,8 @@ class ResourceFetcher extends BaseService { this.queue_.push(item); } + this.updateReport(); + this.scheduleQueueProcess(); return true; } @@ -85,6 +102,7 @@ class ResourceFetcher extends BaseService { delete this.fetchingItems_[resource.id]; this.scheduleQueueProcess(); if (emitDownloadComplete) this.eventEmitter_.emit('downloadComplete', { id: resource.id }); + this.updateReport(); } const resource = await Resource.load(resourceId); diff --git a/ReactNativeClient/lib/synchronizer.js b/ReactNativeClient/lib/synchronizer.js index aff793257..894db533f 100644 --- a/ReactNativeClient/lib/synchronizer.js +++ b/ReactNativeClient/lib/synchronizer.js @@ -74,7 +74,7 @@ class Synchronizer { if (report.deleteLocal) lines.push(_("Deleted local items: %d.", report.deleteLocal)); if (report.deleteRemote) lines.push(_("Deleted remote items: %d.", report.deleteRemote)); if (report.fetchingTotal && report.fetchingProcessed) lines.push(_("Fetched items: %d/%d.", report.fetchingProcessed, report.fetchingTotal)); - if (!report.completedTime && report.state) lines.push(_('State: %s.', Synchronizer.stateToLabel(report.state))); + // if (!report.completedTime && report.state) lines.push(_('State: %s.', Synchronizer.stateToLabel(report.state))); if (report.cancelling && !report.completedTime) lines.push(_("Cancelling...")); if (report.completedTime) lines.push(_("Completed: %s", time.formatMsToLocal(report.completedTime))); if (report.errors && report.errors.length) lines.push(_("Last error: %s", report.errors[report.errors.length - 1].toString().substr(0, 500)));