diff --git a/scripts/langindex.json b/scripts/langindex.json index 53faeef0b..43ba30b47 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1710,6 +1710,7 @@ "core.settings.privacypolicy": "local_moodlemobileapp", "core.settings.pushid": "local_moodlemobileapp", "core.settings.reportinbackground": "local_moodlemobileapp", + "core.settings.entriesincache": "local_moodlemobileapp", "core.settings.settings": "moodle", "core.settings.showdownloadoptions": "local_moodlemobileapp", "core.settings.sites": "moodle", diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 9a3acd3d6..70f0b0601 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1680,7 +1680,7 @@ "core.settings.currentlanguage": "Current language", "core.settings.debugdisplay": "Display debug messages", "core.settings.debugdisplaydescription": "If enabled, error modals will display more data about the error if possible.", - "core.settings.deletesitefiles": "Are you sure that you want to delete the downloaded files from the site '{{sitename}}'?", + "core.settings.deletesitefiles": "Are you sure that you want to delete the downloaded files and cached data from the site '{{sitename}}'? You won't be able to use the app in offline mode.", "core.settings.deletesitefilestitle": "Delete site files", "core.settings.deviceinfo": "Device info", "core.settings.deviceos": "Device OS", @@ -1692,6 +1692,7 @@ "core.settings.enablerichtexteditor": "Enable text editor", "core.settings.enablerichtexteditordescription": "If enabled, a text editor will be available when entering content.", "core.settings.enablesyncwifi": "Allow sync only when on Wi-Fi", + "core.settings.entriesincache": "{{$a}} entries in cache", "core.settings.errordeletesitefiles": "Error deleting site files.", "core.settings.errorsyncsite": "Error synchronising site data. Please check your Internet connection and try again.", "core.settings.estimatedfreespace": "Estimated free space", diff --git a/src/components/ion-tabs/ion-tabs.scss b/src/components/ion-tabs/ion-tabs.scss index a4efdc295..48c459042 100644 --- a/src/components/ion-tabs/ion-tabs.scss +++ b/src/components/ion-tabs/ion-tabs.scss @@ -5,14 +5,13 @@ ion-app.app-root core-ion-tabs { z-index: 101; // For some reason, the regular z-index isn't enough with our tabs, use a higher one. .core-ion-tabs-loading { + height: 100%; width: 100%; - display: table; + display: flex; + align-items: center; + justify-content: center; .core-ion-tabs-loading-spinner { - display: table-cell; - text-align: center; - vertical-align: middle; - .spinner circle, .spinner line { stroke: $white; } diff --git a/src/core/mainmenu/pages/menu/menu.scss b/src/core/mainmenu/pages/menu/menu.scss index 5b532fcb8..a5114c071 100644 --- a/src/core/mainmenu/pages/menu/menu.scss +++ b/src/core/mainmenu/pages/menu/menu.scss @@ -1,4 +1,10 @@ ion-app.app-root page-core-mainmenu { + ion-icon { + text-overflow: unset; + overflow: visible; + text-align: center; + } + .ion-md-fa-graduation-cap, .ion-ios-fa-graduation-cap, .ion-ios-fa-graduation-cap-outline, @@ -8,6 +14,7 @@ ion-app.app-root page-core-mainmenu { @extend .fa; font-size: 21px; height: 21px; + } .ion-ios-fa-graduation-cap-outline { diff --git a/src/core/settings/lang/en.json b/src/core/settings/lang/en.json index a960ccf02..d2b371887 100644 --- a/src/core/settings/lang/en.json +++ b/src/core/settings/lang/en.json @@ -12,7 +12,7 @@ "currentlanguage": "Current language", "debugdisplay": "Display debug messages", "debugdisplaydescription": "If enabled, error modals will display more data about the error if possible.", - "deletesitefiles": "Are you sure that you want to delete the downloaded files from the site '{{sitename}}'?", + "deletesitefiles": "Are you sure that you want to delete the downloaded files and cached data from the site '{{sitename}}'? You won't be able to use the app in offline mode.", "deletesitefilestitle": "Delete site files", "deviceinfo": "Device info", "deviceos": "Device OS", @@ -42,6 +42,7 @@ "privacypolicy": "Privacy policy", "pushid": "Push notifications ID", "reportinbackground": "Report errors automatically", + "entriesincache": "{{$a}} entries in cache", "settings": "Settings", "showdownloadoptions": "Show download options", "sites": "Sites", diff --git a/src/core/settings/pages/space-usage/space-usage.html b/src/core/settings/pages/space-usage/space-usage.html index 00d578ba9..8b93dcf93 100644 --- a/src/core/settings/pages/space-usage/space-usage.html +++ b/src/core/settings/pages/space-usage/space-usage.html @@ -9,16 +9,22 @@ -

-

{{ site.fullName }}

-

{{ site.spaceUsage | coreBytesToSize }}

-

{{ 'core.settings.total' | translate }}

-

{{ totalUsage | coreBytesToSize }}

+
+

{{ totalUsage | coreBytesToSize }}

+

{{ 'core.settings.entriesincache' | translate: { $a: totalEntries } }}

+
diff --git a/src/core/settings/pages/space-usage/space-usage.ts b/src/core/settings/pages/space-usage/space-usage.ts index 3fec9f5d1..457ee82b2 100644 --- a/src/core/settings/pages/space-usage/space-usage.ts +++ b/src/core/settings/pages/space-usage/space-usage.ts @@ -35,6 +35,7 @@ export class CoreSettingsSpaceUsagePage { sites = []; currentSiteId = ''; totalUsage = 0; + totalEntries = 0; constructor(private filePoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, @@ -63,9 +64,17 @@ export class CoreSettingsSpaceUsagePage { // Get space usage. const promises = this.sites.map((siteEntry) => { return this.sitesProvider.getSite(siteEntry.id).then((site) => { - return site.getSpaceUsage().then((size) => { + const proms2 = []; + + proms2.push(this.calcSiteClearRows(site).then((rows) => { + siteEntry.cacheEntries = rows; + })); + + proms2.push(site.getSpaceUsage().then((size) => { siteEntry.spaceUsage = size; - }); + })); + + return Promise.all(proms2); }); }); @@ -77,13 +86,14 @@ export class CoreSettingsSpaceUsagePage { * Convenience function to calculate total usage. */ protected calculateTotalUsage(): void { - let total = 0; + let totalSize = 0, + totalEntries = 0; this.sites.forEach((site) => { - if (site.spaceUsage) { - total += parseInt(site.spaceUsage, 10); - } + totalSize += (site.spaceUsage ? parseInt(site.spaceUsage, 10) : 0); + totalEntries += (site.cacheEntries ? parseInt(site.cacheEntries, 10) : 0); }); - this.totalUsage = total; + this.totalUsage = totalSize; + this.totalEntries = totalEntries; } /** @@ -123,11 +133,33 @@ export class CoreSettingsSpaceUsagePage { } /** - * Deletes files of a site. + * Calculate the number of rows to be deleted on a site. + * + * @param {any} site Site object. + * @return {Promise} If there are rows to delete or not. + */ + protected calcSiteClearRows(site: any): Promise { + const clearTables = this.sitesProvider.getSiteTableSchemasToClear(); + + let totalEntries = 0; + + const promises = clearTables.map((name) => { + return site.getDb().countRecords(name).then((rows) => { + totalEntries += rows; + }); + }); + + return Promise.all(promises).then(() => { + return totalEntries; + }); + } + + /** + * Deletes files of a site and the tables that can be cleared. * * @param {any} siteData Site object with space usage. */ - deleteSiteFiles(siteData: any): void { + deleteSiteStorage(siteData: any): void { this.textUtils.formatText(siteData.siteName).then((siteName) => { const title = this.translate.instant('core.settings.deletesitefilestitle'); const message = this.translate.instant('core.settings.deletesitefiles', {sitename: siteName}); @@ -135,7 +167,14 @@ export class CoreSettingsSpaceUsagePage { this.domUtils.showConfirm(message, title).then(() => { return this.sitesProvider.getSite(siteData.id); }).then((site) => { - site.deleteFolder().then(() => { + + // Clear cache tables. + const cleanSchemas = this.sitesProvider.getSiteTableSchemasToClear(); + const promises = cleanSchemas.map((name) => { + return site.getDb().deleteRecords(name); + }); + + promises.push(site.deleteFolder().then(() => { this.filePoolProvider.clearAllPackagesStatus(site.id); this.filePoolProvider.clearFilepool(site.id); this.updateSiteUsage(siteData, 0); @@ -151,7 +190,13 @@ export class CoreSettingsSpaceUsagePage { this.updateSiteUsage(siteData, size); }); } - }); + }).finally(() => { + this.calcSiteClearRows(site).then((rows) => { + siteData.cacheEntries = rows; + }); + })); + + return Promise.all(promises); }).catch(() => { // Ignore cancelled confirmation modal. }); diff --git a/src/core/user/providers/user.ts b/src/core/user/providers/user.ts index 085a73502..fe1ec6c7c 100644 --- a/src/core/user/providers/user.ts +++ b/src/core/user/providers/user.ts @@ -36,6 +36,7 @@ export class CoreUserProvider { protected siteSchema: CoreSiteSchema = { name: 'CoreUserProvider', version: 1, + canBeCleared: [ this.USERS_TABLE ], tables: [ { name: this.USERS_TABLE, @@ -53,7 +54,7 @@ export class CoreUserProvider { name: 'profileimageurl', type: 'TEXT' } - ] + ], } ] }; diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index 7b3725174..2be089ba3 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -306,7 +306,7 @@ export class CoreFilepoolProvider { primaryKeys: ['siteId', 'fileId'] } ]; - protected siteSchma: CoreSiteSchema = { + protected siteSchema: CoreSiteSchema = { name: 'CoreFilepoolProvider', version: 1, tables: [ @@ -447,7 +447,7 @@ export class CoreFilepoolProvider { this.appDB = this.appProvider.getDB(); this.appDB.createTablesFromSchema(this.appTablesSchema); - this.sitesProvider.registerSiteSchema(this.siteSchma); + this.sitesProvider.registerSiteSchema(this.siteSchema); initDelegate.ready().then(() => { // Waiting for the app to be ready to start processing the queue. @@ -857,7 +857,10 @@ export class CoreFilepoolProvider { */ clearFilepool(siteId: string): Promise { return this.sitesProvider.getSiteDb(siteId).then((db) => { - return db.deleteRecords(this.FILES_TABLE); + return Promise.all([ + db.deleteRecords(this.FILES_TABLE), + db.deleteRecords(this.LINKS_TABLE) + ]); }); } diff --git a/src/providers/sites.ts b/src/providers/sites.ts index f673c9609..31fc08b64 100644 --- a/src/providers/sites.ts +++ b/src/providers/sites.ts @@ -145,6 +145,13 @@ export interface CoreSiteSchema { */ version: number; + /** + * Names of the tables of the site schema that can be cleared. + * + * @type {string[]} + */ + canBeCleared?: string[]; + /** * Tables to create when installing or upgrading the schema. */ @@ -270,6 +277,7 @@ export class CoreSitesProvider { protected siteSchema: CoreSiteSchema = { name: 'CoreSitesProvider', version: 1, + canBeCleared: [ CoreSite.WS_CACHE_TABLE ], tables: [ { name: CoreSite.WS_CACHE_TABLE, @@ -1521,4 +1529,20 @@ export class CoreSitesProvider { return result; }); } + + /** + * Returns the Site Schema names that can be cleared on space storage. + * + * @return {string[]} Name of the site schemas. + */ + getSiteTableSchemasToClear(): string[] { + let reset = []; + for (const name in this.siteSchemas) { + if (this.siteSchemas[name].canBeCleared) { + reset = reset.concat(this.siteSchemas[name].canBeCleared); + } + } + + return reset; + } }