From eced391288ecb661251df7d40473a091b4474926 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Wed, 16 Oct 2019 15:51:05 +0100 Subject: [PATCH] MOBILE-3188 Download interface: Show and delete total downloaded data When showing downloaded sizes in the context menu and in the 'Manage storage' screen, show the total size including downloaded files plus cached web service data. When deleting the downloaded data in either location, delete both kinds of data. --- .../pages/course-storage/course-storage.ts | 12 +++++- src/classes/site.ts | 42 +++++++++++++++++++ src/core/course/providers/helper.ts | 7 +++- .../providers/module-prefetch-delegate.ts | 30 +++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/addon/storagemanager/pages/course-storage/course-storage.ts b/src/addon/storagemanager/pages/course-storage/course-storage.ts index 6bdeecc52..9e38df36c 100644 --- a/src/addon/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addon/storagemanager/pages/course-storage/course-storage.ts @@ -20,6 +20,7 @@ import { CoreCourseHelperProvider } from '@core/course/providers/helper'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { TranslateService } from '@ngx-translate/core'; import { CoreConstants } from '@core/constants'; +import { CoreSitesProvider } from '@providers/sites'; /** * Page that displays the amount of file storage used by each activity on the course, and allows @@ -39,6 +40,7 @@ export class AddonStorageManagerCourseStoragePage { totalSize: number; constructor(navParams: NavParams, + private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider, private prefetchDelegate: CoreCourseModulePrefetchDelegate, private courseHelperProvider: CoreCourseHelperProvider, @@ -70,7 +72,7 @@ export class AddonStorageManagerCourseStoragePage { // But these aren't necessarily consistent, for example mod_frog vs mmaModFrog. // There is nothing enforcing correct values. // Most modules which have large files are downloadable, so I think this is sufficient. - const promise = this.prefetchDelegate.getModuleDownloadedSize(module, this.course.id). + const promise = this.prefetchDelegate.getModuleTotalSize(module, this.course.id). then((size) => { // There are some cases where the return from this is not a valid number. if (!isNaN(size)) { @@ -185,7 +187,13 @@ export class AddonStorageManagerCourseStoragePage { modules.forEach((module) => { // Remove the files. const promise = this.prefetchDelegate.removeModuleFiles(module, this.course.id).then(() => { - // When the files are removed, update the size. + const handler = this.prefetchDelegate.getPrefetchHandlerFor(module); + if (handler) { + + return this.sitesProvider.getCurrentSite().deleteComponentFromCache(handler.component, module.id); + } + }).then(() => { + // When the files and cache are removed, update the size. module.parentSection.totalSize -= module.totalSize; this.totalSize -= module.totalSize; module.totalSize = 0; diff --git a/src/classes/site.ts b/src/classes/site.ts index c24685ef3..77f7e994f 100644 --- a/src/classes/site.ts +++ b/src/classes/site.ts @@ -1100,6 +1100,25 @@ export class CoreSite { }); } + /** + * Gets the size of cached data for a specific component or component instance. + * + * @param component Component name + * @param componentId Optional component id (if not included, returns sum for whole component) + * @return Promise resolved when we have calculated the size + */ + getComponentCacheSize(component: string, componentId?: string): Promise { + const params = [component]; + let extraClause = ''; + if (componentId) { + params.push(componentId); + extraClause = ' AND componentId = ?'; + } + + return this.db.getFieldSql('SELECT SUM(length(data)) FROM ' + CoreSite.WS_CACHE_TABLE + + ' WHERE component = ?' + extraClause, params); + } + /** * Save a WS response to cache. * @@ -1173,6 +1192,29 @@ export class CoreSite { return this.db.deleteRecords(CoreSite.WS_CACHE_TABLE, { id: id }); } + /** + * Deletes WS cache entries for all methods relating to a specific component (and + * optionally component id). + * + * @param component Component name. + * @param componentId Component id. + * @return Promise resolved when the entries are deleted. + */ + deleteComponentFromCache(component: string, componentId?: string): Promise { + if (!this.db) { + return Promise.reject(null); + } + + const params = { + component: component + } as any; + if (componentId) { + params.componentId = componentId; + } + + return this.db.deleteRecords(CoreSite.WS_CACHE_TABLE, params); + } + /* * Uploads a file using Cordova File API. * diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 1ba933eac..870bced3c 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -425,6 +425,11 @@ export class CoreCourseHelperProvider { await this.prefetchDelegate.removeModuleFiles(module, courseId); + const handler = this.prefetchDelegate.getPrefetchHandlerFor(module); + if (handler) { + await this.sitesProvider.getCurrentSite().deleteComponentFromCache(handler.component, String(module.id)); + } + done && done(); } catch (error) { @@ -1131,7 +1136,7 @@ export class CoreCourseHelperProvider { this.prefetchDelegate.invalidateModuleStatusCache(module); } - promises.push(this.prefetchDelegate.getModuleDownloadedSize(module, courseId).then((moduleSize) => { + promises.push(this.prefetchDelegate.getModuleTotalSize(module, courseId).then((moduleSize) => { moduleInfo.size = moduleSize; moduleInfo.sizeReadable = this.textUtils.bytesToSize(moduleSize, 2); })); diff --git a/src/core/course/providers/module-prefetch-delegate.ts b/src/core/course/providers/module-prefetch-delegate.ts index 917a7bc4f..a42d080c5 100644 --- a/src/core/course/providers/module-prefetch-delegate.ts +++ b/src/core/course/providers/module-prefetch-delegate.ts @@ -690,6 +690,36 @@ export class CoreCourseModulePrefetchDelegate extends CoreDelegate { return Promise.resolve(0); } + /** + * Gets the estimated total size of data stored for a module. This includes + * the files downloaded for it (getModuleDownloadedSize) and also the total + * size of web service requests stored for it. + * + * @param module Module to get the size. + * @param courseId Course ID the module belongs to. + * @return Promise resolved with the total size (0 if unknown) + */ + getModuleTotalSize(module: any, courseId: number): Promise { + return this.getModuleDownloadedSize(module, courseId).then((downloadedSize) => { + if (isNaN(downloadedSize)) { + downloadedSize = 0; + } + const handler = this.getPrefetchHandlerFor(module); + if (handler) { + const site = this.sitesProvider.getCurrentSite(); + + return site.getComponentCacheSize(handler.component, module.id).then((cachedSize) => { + return cachedSize + downloadedSize; + }); + } else { + // If there is no handler then we can't find out the component name. + // So we can't work out the cached size, so just return downloaded size. + + return downloadedSize; + } + }); + } + /** * Get module files. *