From 2533829030a08cf0a477f95b3efe9498c15aba99 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 6 Mar 2024 08:58:20 +0100 Subject: [PATCH 1/3] MOBILE-4539 course: Don't call isDownloadable to check module updates --- .../services/module-prefetch-delegate.ts | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index 845e2c99fd7..5451cb1390b 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -122,8 +122,8 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { try { - const data = await this.getModuleStatusAndDownloadTime(module, courseId); - if (data.status != CoreConstants.DOWNLOADED) { + const data = await this.getModuleDownloadTime(module); + if (!data.downloadTime || data.outdated) { return; } @@ -730,22 +730,20 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + ): Promise<{ downloadTime?: number; outdated?: boolean }> { const handler = this.getPrefetchHandlerFor(module.modname); const siteId = CoreSites.getCurrentSiteId(); if (!handler) { - // No handler found, module not downloadable. - return { status: CoreConstants.NOT_DOWNLOADABLE }; + return {}; } // Get the status from the cache. @@ -753,14 +751,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status'); if (status !== undefined && !CoreFileHelper.isStateDownloaded(status)) { - // Module isn't downloaded, just return the status. - return { status }; - } - - // Check if the module is downloadable. - const downloadable = await this.isModuleDownloadable(module, courseId); - if (!downloadable) { - return { status: CoreConstants.NOT_DOWNLOADABLE }; + return {}; } try { @@ -768,11 +759,11 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate Date: Thu, 7 Mar 2024 11:07:46 +0100 Subject: [PATCH 2/3] MOBILE-4539 core: Create and use new DownloadStatus types --- .../components/myoverview/myoverview.ts | 3 +- .../mod/book/pages/contents/contents.ts | 4 +- .../mod/h5pactivity/components/index/index.ts | 18 ++-- .../h5pactivity/services/handlers/prefetch.ts | 4 +- src/addons/mod/imscp/pages/view/view.ts | 4 +- .../mod/lesson/components/index/index.ts | 8 +- src/addons/mod/quiz/components/index/index.ts | 10 +- .../mod/quiz/services/handlers/prefetch.ts | 6 +- .../mod/resource/components/index/index.ts | 6 +- .../mod/resource/services/handlers/module.ts | 6 +- .../resource/services/handlers/prefetch.ts | 10 +- .../mod/scorm/components/index/index.ts | 14 +-- src/addons/mod/scorm/services/scorm.ts | 6 +- .../services/remotethemes-handler.ts | 4 +- .../pages/course-storage/course-storage.ts | 14 +-- .../pages/courses-storage/courses-storage.ts | 10 +- .../download-refresh/download-refresh.ts | 12 +-- src/core/components/file/file.ts | 8 +- src/core/constants.ts | 57 ++++++++++- src/core/directives/external-content.ts | 6 +- src/core/features/compile/services/compile.ts | 3 +- .../classes/activity-prefetch-handler.ts | 6 +- .../course/classes/main-resource-component.ts | 11 ++- .../module-summary/module-summary.ts | 8 +- .../course/components/module/module.ts | 16 +-- .../features/course/services/course-helper.ts | 93 +++++++++--------- src/core/features/course/services/course.ts | 33 ++++--- .../course/services/database/course.ts | 5 +- .../course/services/module-delegate.ts | 3 +- .../services/module-prefetch-delegate.ts | 62 ++++++------ .../course-list-item/course-list-item.ts | 12 +-- .../h5p/components/h5p-iframe/h5p-iframe.ts | 6 +- .../h5p/components/h5p-player/h5p-player.ts | 7 +- src/core/services/database/filepool.ts | 5 +- src/core/services/file-helper.ts | 18 ++-- src/core/services/filepool.ts | 97 ++++++++++--------- src/core/services/plugin-file-delegate.ts | 4 +- src/core/singletons/events.ts | 5 +- 38 files changed, 342 insertions(+), 262 deletions(-) diff --git a/src/addons/block/myoverview/components/myoverview/myoverview.ts b/src/addons/block/myoverview/components/myoverview/myoverview.ts index e749a714589..53120bdfd80 100644 --- a/src/addons/block/myoverview/components/myoverview/myoverview.ts +++ b/src/addons/block/myoverview/components/myoverview/myoverview.ts @@ -35,6 +35,7 @@ import { IonSearchbar } from '@ionic/angular'; import { CoreNavigator } from '@services/navigator'; import { PageLoadWatcher } from '@classes/page-load-watcher'; import { PageLoadsManager } from '@classes/page-loads-manager'; +import { DownloadStatus } from '@/core/constants'; const FILTER_PRIORITY: AddonBlockMyOverviewTimeFilters[] = ['all', 'inprogress', 'future', 'past', 'favourite', 'allincludinghidden', 'hidden']; @@ -54,7 +55,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem prefetchCoursesData: CorePrefetchStatusInfo = { icon: '', statusTranslatable: 'core.loading', - status: '', + status: DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, loading: true, }; diff --git a/src/addons/mod/book/pages/contents/contents.ts b/src/addons/mod/book/pages/contents/contents.ts index 02bf9560a0a..a1475bfaa1a 100644 --- a/src/addons/mod/book/pages/contents/contents.ts +++ b/src/addons/mod/book/pages/contents/contents.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreSwipeSlidesItemsManager } from '@classes/items-management/swipe-slides-items-manager'; @@ -180,7 +180,7 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy { // Get module status to determine if it needs to be downloaded. const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, this.courseId, undefined, refresh); - if (status !== CoreConstants.DOWNLOADED) { + if (status !== DownloadStatus.DOWNLOADED) { // Download content. This function also loads module contents if needed. try { await CoreCourseModulePrefetchDelegate.downloadModule(module, this.courseId); diff --git a/src/addons/mod/h5pactivity/components/index/index.ts b/src/addons/mod/h5pactivity/components/index/index.ts index b95684ca090..bb7e74b9497 100644 --- a/src/addons/mod/h5pactivity/components/index/index.ts +++ b/src/addons/mod/h5pactivity/components/index/index.ts @@ -15,7 +15,7 @@ import { Component, Optional, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core'; import { IonContent } from '@ionic/angular'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { CoreSite } from '@classes/sites/site'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; @@ -161,12 +161,16 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv ); } - if (!this.siteCanDownload || this.state == CoreConstants.DOWNLOADED) { + if (!this.siteCanDownload || this.state === DownloadStatus.DOWNLOADED) { // Cannot download the file or already downloaded, play the package directly. this.play(); - } else if ((this.state == CoreConstants.NOT_DOWNLOADED || this.state == CoreConstants.OUTDATED) && CoreNetwork.isOnline() && - this.deployedFile?.filesize && CoreFilepool.shouldDownload(this.deployedFile.filesize)) { + } else if ( + (this.state == DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED || this.state == DownloadStatus.OUTDATED) && + CoreNetwork.isOnline() && + this.deployedFile?.filesize && + CoreFilepool.shouldDownload(this.deployedFile.filesize) + ) { // Package is small, download it automatically. Don't block this function for this. this.downloadAutomatically(); } @@ -295,13 +299,13 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv * Displays some data based on the state of the main file. */ protected async showFileState(): Promise { - if (this.state == CoreConstants.OUTDATED) { + if (this.state === DownloadStatus.OUTDATED) { this.stateMessage = 'addon.mod_h5pactivity.filestateoutdated'; this.needsDownload = true; - } else if (this.state == CoreConstants.NOT_DOWNLOADED) { + } else if (this.state === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { this.stateMessage = 'addon.mod_h5pactivity.filestatenotdownloaded'; this.needsDownload = true; - } else if (this.state == CoreConstants.DOWNLOADING) { + } else if (this.state === DownloadStatus.DOWNLOADING) { this.stateMessage = ''; if (!this.downloading) { diff --git a/src/addons/mod/h5pactivity/services/handlers/prefetch.ts b/src/addons/mod/h5pactivity/services/handlers/prefetch.ts index cc1eb09b3c9..bd1d658478c 100644 --- a/src/addons/mod/h5pactivity/services/handlers/prefetch.ts +++ b/src/addons/mod/h5pactivity/services/handlers/prefetch.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler'; @@ -144,7 +144,7 @@ export class AddonModH5PActivityPrefetchHandlerService extends CoreCourseActivit // If the file needs to be downloaded, delete the states because it means the package has changed or user deleted it. const fileState = await CoreFilepool.getFileStateByUrl(siteId, CoreFileHelper.getFileUrl(deployedFile)); - if (fileState !== CoreConstants.DOWNLOADED) { + if (fileState !== DownloadStatus.DOWNLOADED) { await CoreUtils.ignoreErrors(CoreXAPIOffline.deleteStates(AddonModH5PActivityProvider.TRACK_COMPONENT, { itemId: h5pActivity.context, siteId, diff --git a/src/addons/mod/imscp/pages/view/view.ts b/src/addons/mod/imscp/pages/view/view.ts index 6fb1d7d6b31..7a96a332482 100644 --- a/src/addons/mod/imscp/pages/view/view.ts +++ b/src/addons/mod/imscp/pages/view/view.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { Component, OnInit } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreNavigationBarItem } from '@components/navigation-bar/navigation-bar'; @@ -173,7 +173,7 @@ export class AddonModImscpViewPage implements OnInit { // Get module status to determine if it needs to be downloaded. const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, this.courseId, undefined, refresh); - if (status !== CoreConstants.DOWNLOADED) { + if (status !== DownloadStatus.DOWNLOADED) { // Download content. This function also loads module contents if needed. try { await CoreCourseModulePrefetchDelegate.downloadModule(module, this.courseId); diff --git a/src/addons/mod/lesson/components/index/index.ts b/src/addons/mod/lesson/components/index/index.ts index b4b6bcc98b8..c81cf96afd5 100644 --- a/src/addons/mod/lesson/components/index/index.ts +++ b/src/addons/mod/lesson/components/index/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { Component, Input, ViewChild, ElementRef, OnInit, OnDestroy, Optional } from '@angular/core'; import { CoreTabsComponent } from '@components/tabs/tabs'; @@ -575,8 +575,8 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo /** * @inheritdoc */ - protected showStatus(status: string): void { - this.showSpinner = status == CoreConstants.DOWNLOADING; + protected showStatus(status: TDownloadStatus): void { + this.showSpinner = status === DownloadStatus.DOWNLOADING; } /** @@ -590,7 +590,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo return; } - if (!AddonModLesson.isLessonOffline(this.lesson) || this.currentStatus == CoreConstants.DOWNLOADED) { + if (!AddonModLesson.isLessonOffline(this.lesson) || this.currentStatus == DownloadStatus.DOWNLOADED) { // Not downloadable or already downloaded, open it. this.playLesson(continueLast); diff --git a/src/addons/mod/quiz/components/index/index.ts b/src/addons/mod/quiz/components/index/index.ts index f0dd6bb5be9..04a2d16e510 100644 --- a/src/addons/mod/quiz/components/index/index.ts +++ b/src/addons/mod/quiz/components/index/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { safeNumber, SafeNumber } from '@/core/utils/types'; import { Component, OnDestroy, OnInit, Optional } from '@angular/core'; @@ -141,7 +141,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp // Quiz supports offline, check if it needs to be downloaded. // If the site doesn't support check updates, always prefetch it because we cannot tell if there's something new. - const isDownloaded = this.currentStatus == CoreConstants.DOWNLOADED; + const isDownloaded = this.currentStatus === DownloadStatus.DOWNLOADED; if (isDownloaded) { // Already downloaded, open it. @@ -543,10 +543,10 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp * @param status The current status. * @param previousStatus The previous status. If not defined, there is no previous status. */ - protected showStatus(status: string, previousStatus?: string): void { - this.showStatusSpinner = status == CoreConstants.DOWNLOADING; + protected showStatus(status: TDownloadStatus, previousStatus?: TDownloadStatus): void { + this.showStatusSpinner = status === DownloadStatus.DOWNLOADING; - if (status == CoreConstants.DOWNLOADED && previousStatus == CoreConstants.DOWNLOADING) { + if (status === DownloadStatus.DOWNLOADED && previousStatus === DownloadStatus.DOWNLOADING) { // Quiz downloaded now, maybe a new attempt was created. Load content again. this.showLoadingAndFetch(); } diff --git a/src/addons/mod/quiz/services/handlers/prefetch.ts b/src/addons/mod/quiz/services/handlers/prefetch.ts index 4b1e9d1c24e..05c470835ea 100644 --- a/src/addons/mod/quiz/services/handlers/prefetch.ts +++ b/src/addons/mod/quiz/services/handlers/prefetch.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { isSafeNumber } from '@/core/utils/types'; import { Injectable } from '@angular/core'; @@ -604,7 +604,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet // Check the current status of the quiz. const status = await CoreFilepool.getPackageStatus(options.siteId, this.component, quiz.coursemodule); - if (status === CoreConstants.NOT_DOWNLOADED) { + if (status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { return; } @@ -612,7 +612,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet // If no attempts or last is finished we'll mark it as not downloaded to show download icon. const lastAttempt = attempts[attempts.length - 1]; const isLastFinished = !lastAttempt || AddonModQuiz.isAttemptFinished(lastAttempt.state); - const newStatus = isLastFinished ? CoreConstants.NOT_DOWNLOADED : CoreConstants.DOWNLOADED; + const newStatus = isLastFinished ? DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED : DownloadStatus.DOWNLOADED; await CoreFilepool.storePackageStatus(options.siteId, newStatus, this.component, quiz.coursemodule); } diff --git a/src/addons/mod/resource/components/index/index.ts b/src/addons/mod/resource/components/index/index.ts index 50cf5907ff0..48a589d759c 100644 --- a/src/addons/mod/resource/components/index/index.ts +++ b/src/addons/mod/resource/components/index/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { Component, OnDestroy, OnInit, Optional } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component'; @@ -66,7 +66,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource timecreated = -1; timemodified = -1; isExternalFile = false; - outdatedStatus = CoreConstants.OUTDATED; + outdatedStatus = DownloadStatus.OUTDATED; protected onlineObserver?: Subscription; @@ -211,7 +211,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource downloadable = await AddonModResourceHelper.isMainFileDownloadable(this.module); if (downloadable) { - if (this.currentStatus === CoreConstants.OUTDATED && !this.isOnline && !this.isExternalFile) { + if (this.currentStatus === DownloadStatus.OUTDATED && !this.isOnline && !this.isExternalFile) { // Warn the user that the file isn't updated. const alert = await CoreDomUtils.showAlert( undefined, diff --git a/src/addons/mod/resource/services/handlers/module.ts b/src/addons/mod/resource/services/handlers/module.ts index 2ffc361f971..9c0c69a3b21 100644 --- a/src/addons/mod/resource/services/handlers/module.ts +++ b/src/addons/mod/resource/services/handlers/module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants, ModPurpose } from '@/core/constants'; +import { CoreConstants, DownloadStatus, ModPurpose } from '@/core/constants'; import { Injectable, Type } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; import { CoreCourse } from '@features/course/services/course'; @@ -76,7 +76,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase return; } - handlerData.button.hidden = status !== CoreConstants.DOWNLOADED || + handlerData.button.hidden = status !== DownloadStatus.DOWNLOADED || AddonModResourceHelper.isDisplayedInIframe(module); }; handlerData.button = { @@ -124,7 +124,7 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, module.course); - return status !== CoreConstants.DOWNLOADED || AddonModResourceHelper.isDisplayedInIframe(module); + return status !== DownloadStatus.DOWNLOADED || AddonModResourceHelper.isDisplayedInIframe(module); } /** diff --git a/src/addons/mod/resource/services/handlers/prefetch.ts b/src/addons/mod/resource/services/handlers/prefetch.ts index 93ab036a9c6..8fe22dbed9e 100644 --- a/src/addons/mod/resource/services/handlers/prefetch.ts +++ b/src/addons/mod/resource/services/handlers/prefetch.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course'; @@ -36,18 +36,18 @@ export class AddonModResourcePrefetchHandlerService extends CoreCourseResourcePr /** * @inheritdoc */ - determineStatus(module: CoreCourseAnyModuleData, status: string): string { - if (status == CoreConstants.DOWNLOADED && module) { + determineStatus(module: CoreCourseAnyModuleData, status: TDownloadStatus): TDownloadStatus { + if (status === DownloadStatus.DOWNLOADED && module) { // If the main file is an external file, always display the module as outdated. if ('contentsinfo' in module && module.contentsinfo) { if (module.contentsinfo.repositorytype) { // It's an external file. - return CoreConstants.OUTDATED; + return DownloadStatus.OUTDATED; } } else if (module.contents) { const mainFile = module.contents[0]; if (mainFile && mainFile.isexternalfile) { - return CoreConstants.OUTDATED; + return DownloadStatus.OUTDATED; } } } diff --git a/src/addons/mod/scorm/components/index/index.ts b/src/addons/mod/scorm/components/index/index.ts index 8b7759bf427..31bd6a394d1 100644 --- a/src/addons/mod/scorm/components/index/index.ts +++ b/src/addons/mod/scorm/components/index/index.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { Component, Input, OnInit, Optional } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; @@ -495,10 +495,10 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom return; } - const isOutdated = this.currentStatus === CoreConstants.OUTDATED; + const isOutdated = this.currentStatus === DownloadStatus.OUTDATED; const scorm = this.scorm; - if (!isOutdated && this.currentStatus !== CoreConstants.NOT_DOWNLOADED) { + if (!isOutdated && this.currentStatus !== DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // Already downloaded, open it. this.openScorm(scoId, preview); @@ -578,16 +578,16 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom /** * @inheritdoc */ - protected async showStatus(status: string): Promise { + protected async showStatus(status: TDownloadStatus): Promise { - if (status === CoreConstants.OUTDATED && this.scorm) { + if (status === DownloadStatus.OUTDATED && this.scorm) { // Only show the outdated message if the file should be downloaded. const download = await AddonModScorm.shouldDownloadMainFile(this.scorm, true); this.statusMessage = download ? 'addon.mod_scorm.scormstatusoutdated' : ''; - } else if (status === CoreConstants.NOT_DOWNLOADED) { + } else if (status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { this.statusMessage = 'addon.mod_scorm.scormstatusnotdownloaded'; - } else if (status === CoreConstants.DOWNLOADING) { + } else if (status === DownloadStatus.DOWNLOADING) { if (!this.downloading) { // It's being downloaded right now but the view isn't tracking it. "Restore" the download. this.downloadScormPackage(); diff --git a/src/addons/mod/scorm/services/scorm.ts b/src/addons/mod/scorm/services/scorm.ts index 3fe5fab5ee0..9c89fcc7632 100644 --- a/src/addons/mod/scorm/services/scorm.ts +++ b/src/addons/mod/scorm/services/scorm.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { Injectable } from '@angular/core'; import { CoreError } from '@classes/errors/error'; import { CoreSite } from '@classes/sites/site'; @@ -1669,8 +1669,8 @@ export class AddonModScormProvider { return false; } - const isOutdated = data.status == CoreConstants.OUTDATED || - (data.status == CoreConstants.DOWNLOADING && data.previous == CoreConstants.OUTDATED); + const isOutdated = data.status === DownloadStatus.OUTDATED || + (data.status === DownloadStatus.DOWNLOADING && data.previous === DownloadStatus.OUTDATED); // Package needs to be downloaded if it's not outdated (not downloaded) or if the hash has changed. return !isOutdated || data.extra != scorm.sha1hash; diff --git a/src/addons/remotethemes/services/remotethemes-handler.ts b/src/addons/remotethemes/services/remotethemes-handler.ts index c4c96e5b58d..46bbdc1d000 100644 --- a/src/addons/remotethemes/services/remotethemes-handler.ts +++ b/src/addons/remotethemes/services/remotethemes-handler.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site'; import { CoreFile } from '@services/file'; import { CoreFilepool } from '@services/filepool'; @@ -124,7 +124,7 @@ export class AddonRemoteThemesHandlerService implements CoreStyleHandler { // Check if the file is downloaded. const state = await CoreFilepool.getFileStateByUrl(siteId, url); - if (state == CoreConstants.NOT_DOWNLOADED) { + if (state === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // File not downloaded, URL has changed or first time. Delete downloaded CSS files. await CoreFilepool.removeFilesByComponent(siteId, COMPONENT, 1); } diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index f0b1e18ea8f..7fd54e1c7c0 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus, TDownloadStatus } from '@/core/constants'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit } from '@angular/core'; import { CoreCourse, CoreCourseProvider } from '@features/course/services/course'; import { @@ -58,11 +58,11 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { prefetchCourseData: CorePrefetchStatusInfo = { icon: CoreConstants.ICON_LOADING, statusTranslatable: 'core.course.downloadcourse', - status: '', + status: DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, loading: true, }; - statusDownloaded = CoreConstants.DOWNLOADED; + statusDownloaded = DownloadStatus.DOWNLOADED; protected initialSectionId?: number; protected siteUpdatedObserver?: CoreEventObserver; @@ -511,7 +511,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { // We are currently marking as not downloaded if size is 0 but we should take into account that // resources without files can be downloaded and cached. - CoreCourse.setCourseStatus(this.courseId, CoreConstants.NOT_DOWNLOADED); + CoreCourse.setCourseStatus(this.courseId, DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED); } /** @@ -607,7 +607,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { * @param module Module to update. * @param status Module status. */ - protected updateModuleStatus(module: AddonStorageManagerModule, status: string): void { + protected updateModuleStatus(module: AddonStorageManagerModule, status: TDownloadStatus): void { if (!status) { return; } @@ -649,7 +649,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { * * @param status Status to show. */ - protected updateCourseStatus(status: string): void { + protected updateCourseStatus(status: TDownloadStatus): void { const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status); this.prefetchCourseData.status = statusData.status; @@ -758,5 +758,5 @@ type AddonStorageManagerModule = CoreCourseModuleData & { calculatingSize: boolean; prefetchHandler?: CoreCourseModulePrefetchHandler; spinner?: boolean; - downloadStatus?: string; + downloadStatus?: TDownloadStatus; }; diff --git a/src/addons/storagemanager/pages/courses-storage/courses-storage.ts b/src/addons/storagemanager/pages/courses-storage/courses-storage.ts index cde85d50ac9..ccf2f599ae6 100644 --- a/src/addons/storagemanager/pages/courses-storage/courses-storage.ts +++ b/src/addons/storagemanager/pages/courses-storage/courses-storage.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { Component, OnDestroy, OnInit } from '@angular/core'; import { CoreCourse, CoreCourseProvider } from '@features/course/services/course'; import { CoreCourseHelper } from '@features/course/services/course-helper'; @@ -82,7 +82,7 @@ export class AddonStorageManagerCoursesStoragePage implements OnInit, OnDestroy id: siteHomeId, title: Translate.instant('core.sitehome.sitehome'), totalSize: size, - isDownloading: status === CoreConstants.DOWNLOADING, + isDownloading: status === DownloadStatus.DOWNLOADING, }); } } @@ -175,7 +175,7 @@ export class AddonStorageManagerCoursesStoragePage implements OnInit, OnDestroy * * @param courseId Updated course id. */ - private async onCourseUpdated(courseId: number, status: string): Promise { + private async onCourseUpdated(courseId: number, status: TDownloadStatus): Promise { if (courseId == CoreCourseProvider.ALL_COURSES_CLEARED) { this.setDownloadedCourses([]); @@ -188,7 +188,7 @@ export class AddonStorageManagerCoursesStoragePage implements OnInit, OnDestroy return; } - course.isDownloading = status === CoreConstants.DOWNLOADING; + course.isDownloading = status === DownloadStatus.DOWNLOADING; course.totalSize = await this.calculateDownloadedCourseSize(course.id); this.setDownloadedCourses(this.downloadedCourses); @@ -219,7 +219,7 @@ export class AddonStorageManagerCoursesStoragePage implements OnInit, OnDestroy id: course.id, title: course.displayname || course.fullname, totalSize, - isDownloading: status === CoreConstants.DOWNLOADING, + isDownloading: status === DownloadStatus.DOWNLOADING, }; } diff --git a/src/core/components/download-refresh/download-refresh.ts b/src/core/components/download-refresh/download-refresh.ts index 7c71944de59..f4c35a050a3 100644 --- a/src/core/components/download-refresh/download-refresh.ts +++ b/src/core/components/download-refresh/download-refresh.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreAnimations } from '@components/animations'; /** @@ -31,17 +31,17 @@ import { CoreAnimations } from '@components/animations'; }) export class CoreDownloadRefreshComponent { - @Input() status?: string; // Download status. + @Input() status?: TDownloadStatus; // Download status. @Input() statusTranslatable?: string; // Download status translatable string. @Input() enabled = false; // Whether the download is enabled. @Input() loading = true; // Force loading status when is not downloading. @Input() canTrustDownload = false; // If false, refresh will be shown if downloaded. @Output() action: EventEmitter; // Will emit an event when the item clicked. - statusDownloaded = CoreConstants.DOWNLOADED; - statusNotDownloaded = CoreConstants.NOT_DOWNLOADED; - statusOutdated = CoreConstants.OUTDATED; - statusDownloading = CoreConstants.DOWNLOADING; + statusDownloaded = DownloadStatus.DOWNLOADED; + statusNotDownloaded = DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; + statusOutdated = DownloadStatus.OUTDATED; + statusDownloading = DownloadStatus.DOWNLOADING; constructor() { this.action = new EventEmitter(); diff --git a/src/core/components/file/file.ts b/src/core/components/file/file.ts index 157b06a74d8..a347c42ec6f 100644 --- a/src/core/components/file/file.ts +++ b/src/core/components/file/file.ts @@ -23,7 +23,7 @@ import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreWSFile } from '@services/ws'; import { CorePlatform } from '@services/platform'; @@ -53,7 +53,7 @@ export class CoreFileComponent implements OnInit, OnDestroy { fileIcon?: string; fileName!: string; fileSizeReadable?: string; - state?: string; + state?: TDownloadStatus; timemodified!: number; isIOS = false; openButtonIcon = ''; @@ -138,7 +138,7 @@ export class CoreFileComponent implements OnInit, OnDestroy { this.canDownload = site.canDownloadFiles(); this.state = state; - this.isDownloading = this.canDownload && state === CoreConstants.DOWNLOADING; + this.isDownloading = this.canDownload && state === DownloadStatus.DOWNLOADING; this.isDownloaded = this.canDownload && CoreFileHelper.isStateDownloaded(state); } @@ -193,7 +193,7 @@ export class CoreFileComponent implements OnInit, OnDestroy { return; } - if (!this.canDownload || !this.state || this.state == CoreConstants.NOT_DOWNLOADABLE) { + if (!this.canDownload || !this.state || this.state === DownloadStatus.NOT_DOWNLOADABLE) { // File cannot be downloaded, just open it. if (CoreUrlUtils.isLocalFileUrl(this.fileUrl)) { CoreUtils.openFile(this.fileUrl); diff --git a/src/core/constants.ts b/src/core/constants.ts index 25504259b8d..1188338b618 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -46,6 +46,38 @@ export const enum ModPurpose { MOD_PURPOSE_OTHER = 'other', } +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * Possible statuses for downloaded modules/files. + */ +export const DownloadedStatus = { + DOWNLOADED: 'downloaded', + DOWNLOADING: 'downloading', + OUTDATED: 'outdated', +} as const; + +/** + * Possible statuses for not downloaded modules/files. + */ +export const NotDownloadedStatus = { + DOWNLOADABLE_NOT_DOWNLOADED: 'notdownloaded', + NOT_DOWNLOADABLE: 'notdownloadable', +} as const; + +/** + * Possible statuses for modules regarding download. + */ +export const DownloadStatus = { + ...DownloadedStatus, + ...NotDownloadedStatus, +} as const; + +export type TDownloadedStatus = typeof DownloadedStatus[keyof typeof DownloadedStatus]; +export type TNotDownloadedStatus = typeof NotDownloadedStatus[keyof typeof NotDownloadedStatus]; +export type TDownloadStatus = typeof DownloadStatus[keyof typeof DownloadStatus]; + +/* eslint-enable @typescript-eslint/naming-convention */ + /** * Static class to contain all the core constants. */ @@ -99,11 +131,26 @@ export class CoreConstants { static readonly LOGIN_LAUNCH_DATA = 'CoreLoginLaunchData'; // Download status constants. - static readonly DOWNLOADED = 'downloaded'; - static readonly DOWNLOADING = 'downloading'; - static readonly NOT_DOWNLOADED = 'notdownloaded'; - static readonly OUTDATED = 'outdated'; - static readonly NOT_DOWNLOADABLE = 'notdownloadable'; + /** + * @deprecated since 4.4. Use DownloadStatus.DOWNLOADED instead. + */ + static readonly DOWNLOADED = DownloadStatus.DOWNLOADED; + /** + * @deprecated since 4.4. Use DownloadStatus.DOWNLOADING instead. + */ + static readonly DOWNLOADING = DownloadStatus.DOWNLOADING; + /** + * @deprecated since 4.4. Use DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED instead. + */ + static readonly NOT_DOWNLOADED = DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; + /** + * @deprecated since 4.4. Use DownloadStatus.OUTDATED instead. + */ + static readonly OUTDATED = DownloadStatus.OUTDATED; + /** + * @deprecated since 4.4. Use DownloadStatus.NOT_DOWNLOADABLE instead. + */ + static readonly NOT_DOWNLOADABLE = DownloadStatus.NOT_DOWNLOADABLE; // Download / prefetch status icon. static readonly ICON_DOWNLOADED = 'fam-cloud-done'; diff --git a/src/core/directives/external-content.ts b/src/core/directives/external-content.ts index e8c239884d1..35a1bbf8fa0 100644 --- a/src/core/directives/external-content.ts +++ b/src/core/directives/external-content.ts @@ -32,7 +32,7 @@ import { CoreLogger } from '@singletons/logger'; import { CoreError } from '@classes/errors/error'; import { CoreSite } from '@classes/sites/site'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreConstants } from '../constants'; +import { DownloadStatus } from '../constants'; import { CoreNetwork } from '@services/network'; import { Translate } from '@singletons'; import { AsyncDirective } from '@classes/async-directive'; @@ -418,7 +418,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges, O } state = newState; - if (state === CoreConstants.DOWNLOADING) { + if (state === DownloadStatus.DOWNLOADING) { return; } @@ -442,7 +442,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges, O clickableEl.addEventListener(eventName, () => { // User played media or opened a downloadable link. // Download the file if in wifi and it hasn't been downloaded already (for big files). - if (state !== CoreConstants.DOWNLOADED && state !== CoreConstants.DOWNLOADING && CoreNetwork.isWifi()) { + if (state !== DownloadStatus.DOWNLOADED && state !== DownloadStatus.DOWNLOADING && CoreNetwork.isWifi()) { // We aren't using the result, so it doesn't matter which of the 2 functions we call. CoreFilepool.getUrlByUrl(site.getId(), url, this.component, this.componentId, 0, false); } diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 4bf951299ea..7cc8a2911d2 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -71,7 +71,7 @@ import { getXAPIServices } from '@features/xapi/xapi.module'; import { DomSanitizer } from '@angular/platform-browser'; import { FormBuilder, Validators } from '@angular/forms'; import { HttpClient } from '@angular/common/http'; -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus } from '@/core/constants'; import moment from 'moment-timezone'; import { Md5 } from 'ts-md5/dist/md5'; @@ -305,6 +305,7 @@ export class CoreCompileProvider { instance['injector'] = this.injector; instance['Validators'] = Validators; instance['CoreConstants'] = CoreConstants; + instance['DownloadStatus'] = DownloadStatus; instance['CoreConfigConstants'] = CoreConstants.CONFIG; instance['CoreEventsProvider'] = CoreEvents; instance['CoreLoggerProvider'] = CoreLogger; diff --git a/src/core/features/course/classes/activity-prefetch-handler.ts b/src/core/features/course/classes/activity-prefetch-handler.ts index 19df8150ec8..89dac07fb9b 100644 --- a/src/core/features/course/classes/activity-prefetch-handler.ts +++ b/src/core/features/course/classes/activity-prefetch-handler.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { CoreNetwork } from '@services/network'; @@ -150,7 +150,7 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe setDownloaded(id: number, siteId?: string, extra?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); - return CoreFilepool.storePackageStatus(siteId, CoreConstants.DOWNLOADED, this.component, id, extra); + return CoreFilepool.storePackageStatus(siteId, DownloadStatus.DOWNLOADED, this.component, id, extra); } /** @@ -163,7 +163,7 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe setDownloading(id: number, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); - return CoreFilepool.storePackageStatus(siteId, CoreConstants.DOWNLOADING, this.component, id); + return CoreFilepool.storePackageStatus(siteId, DownloadStatus.DOWNLOADING, this.component, id); } /** diff --git a/src/core/features/course/classes/main-resource-component.ts b/src/core/features/course/classes/main-resource-component.ts index 8acc3e87232..2ea85942bef 100644 --- a/src/core/features/course/classes/main-resource-component.ts +++ b/src/core/features/course/classes/main-resource-component.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { OnInit, OnDestroy, Input, Output, EventEmitter, Component, Optional, Inject } from '@angular/core'; import { CoreAnyError } from '@classes/errors/error'; import { CoreNetwork } from '@services/network'; @@ -65,7 +65,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, protected isCurrentView = false; // Whether the component is in the current view. protected siteId?: string; // Current Site ID. protected statusObserver?: CoreEventObserver; // Observer of package status. Only if setStatusListener is called. - currentStatus?: string; // The current status of the module. Only if setStatusListener is called. + currentStatus?: TDownloadStatus; // The current status of the module. Only if setStatusListener is called. downloadTimeReadable?: string; // Last download time in a readable format. Only if setStatusListener is called. protected completionObserver?: CoreEventObserver; @@ -242,7 +242,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, * @returns If module has been prefetched. */ protected isPrefetched(): boolean { - return this.currentStatus != CoreConstants.NOT_DOWNLOADABLE && this.currentStatus != CoreConstants.NOT_DOWNLOADED; + return this.currentStatus !== DownloadStatus.NOT_DOWNLOADABLE && + this.currentStatus !== DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } /** @@ -281,7 +282,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, * @param previousStatus The previous status. If not defined, there is no previous status. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected showStatus(status: string, previousStatus?: string): void { + protected showStatus(status: TDownloadStatus, previousStatus?: TDownloadStatus): void { // To be overridden. } @@ -345,7 +346,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, // Get module status to determine if it needs to be downloaded. await this.setStatusListener(refresh); - if (this.currentStatus != CoreConstants.DOWNLOADED) { + if (this.currentStatus !== DownloadStatus.DOWNLOADED) { // Download content. This function also loads module contents if needed. try { await CoreCourseModulePrefetchDelegate.downloadModule(this.module, this.courseId); diff --git a/src/core/features/course/components/module-summary/module-summary.ts b/src/core/features/course/components/module-summary/module-summary.ts index 8c908987ed9..e4f219605d8 100644 --- a/src/core/features/course/components/module-summary/module-summary.ts +++ b/src/core/features/course/components/module-summary/module-summary.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus } from '@/core/constants'; import { AddonBlog } from '@addons/blog/services/blog'; import { AddonBlogMainMenuHandlerService } from '@addons/blog/services/handlers/mainmenu'; import { Component, Input, OnDestroy, OnInit } from '@angular/core'; @@ -216,15 +216,15 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy { const moduleInfo = await CoreCourseHelper.getModulePrefetchInfo(this.module, this.courseId, refresh, this.component); - this.canPrefetch = moduleInfo.status != CoreConstants.NOT_DOWNLOADABLE; + this.canPrefetch = moduleInfo.status !== DownloadStatus.NOT_DOWNLOADABLE; this.downloadTimeReadable = ''; if (this.canPrefetch) { if (moduleInfo.downloadTime && moduleInfo.downloadTime > 0) { this.downloadTimeReadable = CoreTextUtils.ucFirst(moduleInfo.downloadTimeReadable); } - this.prefetchLoading = moduleInfo.status == CoreConstants.DOWNLOADING; - this.prefetchDisabled = moduleInfo.status == CoreConstants.DOWNLOADED; + this.prefetchLoading = moduleInfo.status === DownloadStatus.DOWNLOADING; + this.prefetchDisabled = moduleInfo.status === DownloadStatus.DOWNLOADED; } if (moduleInfo.size && moduleInfo.size > 0) { diff --git a/src/core/features/course/components/module/module.ts b/src/core/features/course/components/module/module.ts index 8fdce6b4def..5a1d42fb7b8 100644 --- a/src/core/features/course/components/module/module.ts +++ b/src/core/features/course/components/module/module.ts @@ -27,7 +27,7 @@ import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler, } from '@features/course/services/module-prefetch-delegate'; -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { BehaviorSubject } from 'rxjs'; @@ -144,19 +144,19 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { /** * Show module status. * - * @param prefetchstatus Module status. + * @param prefetchStatus Module status. */ - protected updateModuleStatus(prefetchstatus: string): void { - if (!prefetchstatus) { + protected updateModuleStatus(prefetchStatus: TDownloadStatus): void { + if (!prefetchStatus) { return; } - switch (prefetchstatus) { - case CoreConstants.OUTDATED: + switch (prefetchStatus) { + case DownloadStatus.OUTDATED: this.prefetchStatusIcon$.next(CoreConstants.ICON_OUTDATED); this.prefetchStatusText$.next('core.outdated'); break; - case CoreConstants.DOWNLOADED: + case DownloadStatus.DOWNLOADED: this.prefetchStatusIcon$.next(CoreConstants.ICON_DOWNLOADED); this.prefetchStatusText$.next('core.downloaded'); break; @@ -166,7 +166,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { break; } - this.module.handlerData?.updateStatus?.(prefetchstatus); + this.module.handlerData?.updateStatus?.(prefetchStatus); } /** diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index d80fa7fbb84..ea52468c3dc 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -28,7 +28,7 @@ import { CoreCourseModuleCompletionStatus, CoreCourseGetContentsWSModule, } from './course'; -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreLogger } from '@singletons/logger'; import { ApplicationInit, makeSingleton, Translate } from '@singletons'; import { CoreFilepool } from '@services/filepool'; @@ -82,7 +82,7 @@ import { LazyRoutesModule } from '@/app/app-routing.module'; export type CoreCourseModulePrefetchInfo = CoreCourseModulePackageLastDownloaded & { size: number; // Downloaded size. sizeReadable: string; // Downloadable size in a readable format. - status: string; // Module status. + status: TDownloadStatus; // Module status. statusIcon?: string; // Icon's name of the module status. }; @@ -120,7 +120,7 @@ export type CoreCourseCoursesProgress = { }; export type CorePrefetchStatusInfo = { - status: string; // Status of the prefetch. + status: TDownloadStatus; // Status of the prefetch. statusTranslatable: string; // Status translatable string. icon: string; // Icon based on the status. loading: boolean; // If it's a loading status. @@ -291,13 +291,13 @@ export class CoreCourseHelperProvider { // Check if it's being downloaded. const downloadId = this.getSectionDownloadId(section); if (CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) { - result.status = CoreConstants.DOWNLOADING; + result.status = DownloadStatus.DOWNLOADING; } sectionWithStatus.downloadStatus = result.status; // Set this section data. - if (result.status !== CoreConstants.DOWNLOADING) { + if (result.status !== DownloadStatus.DOWNLOADING) { sectionWithStatus.isDownloading = false; sectionWithStatus.total = 0; } else { @@ -328,7 +328,7 @@ export class CoreCourseHelperProvider { checkUpdates: boolean = true, ): Promise { let allSectionsSection: CoreCourseSectionWithStatus | undefined; - let allSectionsStatus = CoreConstants.NOT_DOWNLOADABLE; + let allSectionsStatus = DownloadStatus.NOT_DOWNLOADABLE as TDownloadStatus; const promises = sections.map(async (section: CoreCourseSectionWithStatus) => { section.isCalculating = true; @@ -356,7 +356,7 @@ export class CoreCourseHelperProvider { if (allSectionsSection) { // Set "All sections" data. allSectionsSection.downloadStatus = allSectionsStatus; - allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING; + allSectionsSection.isDownloading = allSectionsStatus === DownloadStatus.DOWNLOADING; } return sections; @@ -389,7 +389,7 @@ export class CoreCourseHelperProvider { data.downloadSucceeded = false; data.icon = CoreConstants.ICON_DOWNLOADING; - data.status = CoreConstants.DOWNLOADING; + data.status = DownloadStatus.DOWNLOADING; data.loading = true; data.statusTranslatable = 'core.downloading'; @@ -632,9 +632,9 @@ export class CoreCourseHelperProvider { * @param courses Courses * @returns Promise resolved with the status. */ - async determineCoursesStatus(courses: CoreCourseBasicData[]): Promise { + async determineCoursesStatus(courses: CoreCourseBasicData[]): Promise { // Get the status of each course. - const promises: Promise[] = []; + const promises: Promise[] = []; const siteId = CoreSites.getCurrentSiteId(); courses.forEach((course) => { @@ -724,12 +724,12 @@ export class CoreCourseHelperProvider { // Error opening the file, some apps don't allow opening online files. if (!CoreFile.isAvailable()) { throw error; - } else if (result.status === CoreConstants.DOWNLOADING) { + } else if (result.status === DownloadStatus.DOWNLOADING) { throw new CoreError(Translate.instant('core.erroropenfiledownloading')); } let path: string | undefined; - if (result.status === CoreConstants.NOT_DOWNLOADED) { + if (result.status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // Not downloaded, download it now and return the local file. await this.downloadModule(module, courseId, component, componentId, files, siteId); @@ -817,7 +817,7 @@ export class CoreCourseHelperProvider { files?: CoreCourseModuleContentFile[], siteId?: string, options: CoreUtilsOpenFileOptions = {}, - ): Promise<{ fixedUrl: string; path: string; status?: string }> { + ): Promise<{ fixedUrl: string; path: string; status?: TDownloadStatus }> { siteId = siteId || CoreSites.getCurrentSiteId(); @@ -843,16 +843,16 @@ export class CoreCourseHelperProvider { let path = ''; - if (status === CoreConstants.DOWNLOADING) { + if (status === DownloadStatus.DOWNLOADING) { // Use the online URL. path = fixedUrl; - } else if (status === CoreConstants.DOWNLOADED) { + } else if (status === DownloadStatus.DOWNLOADED) { try { // Get the local file URL. path = await CoreFilepool.getInternalUrlByUrl(siteId, mainFile.fileurl); } catch (error){ // File not found, mark the module as not downloaded. - await CoreFilepool.storePackageStatus(siteId, CoreConstants.NOT_DOWNLOADED, component, componentId); + await CoreFilepool.storePackageStatus(siteId, DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, component, componentId); } } @@ -870,7 +870,7 @@ export class CoreCourseHelperProvider { options, ); } catch (error) { - if (status !== CoreConstants.OUTDATED) { + if (status !== DownloadStatus.OUTDATED) { throw error; } @@ -910,7 +910,7 @@ export class CoreCourseHelperProvider { courseId: number, fixedUrl: string, files: CoreCourseModuleContentFile[], - status: string, + status: TDownloadStatus, component?: string, componentId?: string | number, siteId?: string, @@ -922,7 +922,7 @@ export class CoreCourseHelperProvider { const mainFile = files[0]; const timemodified = mainFile.timemodified || 0; - if (!isOnline && status === CoreConstants.NOT_DOWNLOADED) { + if (!isOnline && status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // Not downloaded and we're offline, reject. throw new CoreNetworkError(); } @@ -1239,7 +1239,7 @@ export class CoreCourseHelperProvider { * @param status Course status. * @returns Prefetch status info. */ - getCoursePrefetchStatusInfo(status: string): CorePrefetchStatusInfo { + getCoursePrefetchStatusInfo(status: TDownloadStatus): CorePrefetchStatusInfo { const prefetchStatus: CorePrefetchStatusInfo = { status: status, icon: this.getPrefetchStatusIcon(status, false), @@ -1247,10 +1247,10 @@ export class CoreCourseHelperProvider { loading: false, }; - if (status == CoreConstants.DOWNLOADED) { + if (status === DownloadStatus.DOWNLOADED) { // Always show refresh icon, we cannot know if there's anything new in course options. prefetchStatus.statusTranslatable = 'core.course.refreshcourse'; - } else if (status == CoreConstants.DOWNLOADING) { + } else if (status === DownloadStatus.DOWNLOADING) { prefetchStatus.statusTranslatable = 'core.downloading'; prefetchStatus.loading = true; } else { @@ -1266,7 +1266,7 @@ export class CoreCourseHelperProvider { * @param status Courses status. * @returns Prefetch status info. */ - getCoursesPrefetchStatusInfo(status: string): CorePrefetchStatusInfo { + getCoursesPrefetchStatusInfo(status: TDownloadStatus): CorePrefetchStatusInfo { const prefetchStatus: CorePrefetchStatusInfo = { status: status, icon: this.getPrefetchStatusIcon(status, false), @@ -1274,10 +1274,10 @@ export class CoreCourseHelperProvider { loading: false, }; - if (status == CoreConstants.DOWNLOADED) { + if (status === DownloadStatus.DOWNLOADED) { // Always show refresh icon, we cannot know if there's anything new in course options. prefetchStatus.statusTranslatable = 'core.courses.refreshcourses'; - } else if (status == CoreConstants.DOWNLOADING) { + } else if (status === DownloadStatus.DOWNLOADING) { prefetchStatus.statusTranslatable = 'core.downloading'; prefetchStatus.loading = true; } else { @@ -1294,17 +1294,17 @@ export class CoreCourseHelperProvider { * @param trustDownload True to show download success, false to show an outdated status when downloaded. * @returns Icon name. */ - getPrefetchStatusIcon(status: string, trustDownload: boolean = false): string { - if (status == CoreConstants.NOT_DOWNLOADED) { + getPrefetchStatusIcon(status: TDownloadStatus, trustDownload: boolean = false): string { + if (status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { return CoreConstants.ICON_NOT_DOWNLOADED; } - if (status == CoreConstants.OUTDATED || (status == CoreConstants.DOWNLOADED && !trustDownload)) { + if (status === DownloadStatus.OUTDATED || (status === DownloadStatus.DOWNLOADED && !trustDownload)) { return CoreConstants.ICON_OUTDATED; } - if (status == CoreConstants.DOWNLOADED && trustDownload) { + if (status === DownloadStatus.DOWNLOADED && trustDownload) { return CoreConstants.ICON_DOWNLOADED; } - if (status == CoreConstants.DOWNLOADING) { + if (status === DownloadStatus.DOWNLOADING) { return CoreConstants.ICON_DOWNLOADING; } @@ -1348,16 +1348,16 @@ export class CoreCourseHelperProvider { const status = results[1]; let statusIcon: string | undefined; switch (results[1]) { - case CoreConstants.NOT_DOWNLOADED: + case DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED: statusIcon = CoreConstants.ICON_NOT_DOWNLOADED; break; - case CoreConstants.DOWNLOADING: + case DownloadStatus.DOWNLOADING: statusIcon = CoreConstants.ICON_DOWNLOADING; break; - case CoreConstants.OUTDATED: + case DownloadStatus.OUTDATED: statusIcon = CoreConstants.ICON_OUTDATED; break; - case CoreConstants.DOWNLOADED: + case DownloadStatus.DOWNLOADED: break; default: statusIcon = ''; @@ -1391,7 +1391,12 @@ export class CoreCourseHelperProvider { const packageData = await CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, component, module.id)); // Treat download time. - if (!packageData || !packageData.downloadTime || !CoreFileHelper.isStateDownloaded(packageData.status || '')) { + if ( + !packageData || + !packageData.downloadTime || + !packageData.status || + !CoreFileHelper.isStateDownloaded(packageData.status) + ) { // Not downloaded. return { downloadTime: 0, @@ -1598,7 +1603,7 @@ export class CoreCourseHelperProvider { // First of all, mark the course as being downloaded. this.courseDwnPromises[requiredSiteId][course.id] = CoreCourse.setCourseStatus( course.id, - CoreConstants.DOWNLOADING, + DownloadStatus.DOWNLOADING, requiredSiteId, ).then(async () => { @@ -1636,7 +1641,7 @@ export class CoreCourseHelperProvider { await CoreUtils.allPromises(promises); // Download success, mark the course as downloaded. - return CoreCourse.setCourseStatus(course.id, CoreConstants.DOWNLOADED, requiredSiteId); + return CoreCourse.setCourseStatus(course.id, DownloadStatus.DOWNLOADED, requiredSiteId); }).catch(async (error) => { // Error, restore previous status. await CoreCourse.setCoursePreviousStatus(course.id, requiredSiteId); @@ -1709,7 +1714,7 @@ export class CoreCourseHelperProvider { } // Download all the sections except "All sections". - let allSectionsStatus = CoreConstants.NOT_DOWNLOADABLE; + let allSectionsStatus = DownloadStatus.NOT_DOWNLOADABLE as TDownloadStatus; section.isDownloading = true; const promises = sections.map(async (section) => { @@ -1733,7 +1738,7 @@ export class CoreCourseHelperProvider { // Set "All sections" data. section.downloadStatus = allSectionsStatus; - section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING; + section.isDownloading = allSectionsStatus === DownloadStatus.DOWNLOADING; } finally { section.isDownloading = false; } @@ -1787,7 +1792,7 @@ export class CoreCourseHelperProvider { // Validate the section needs to be downloaded and calculate amount of modules that need to be downloaded. const result = await CoreCourseModulePrefetchDelegate.getModulesStatus(section.modules, courseId, section.id); - if (result.status == CoreConstants.DOWNLOADED || result.status == CoreConstants.NOT_DOWNLOADABLE) { + if (result.status === DownloadStatus.DOWNLOADED || result.status === DownloadStatus.NOT_DOWNLOADABLE) { // Section is downloaded or not downloadable, nothing to do. return ; } @@ -1819,8 +1824,8 @@ export class CoreCourseHelperProvider { } // We only download modules with status notdownloaded, downloading or outdated. - const modules = result[CoreConstants.OUTDATED].concat(result[CoreConstants.NOT_DOWNLOADED]) - .concat(result[CoreConstants.DOWNLOADING]); + const modules = result[DownloadStatus.OUTDATED].concat(result[DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED]) + .concat(result[DownloadStatus.DOWNLOADING]); const downloadId = this.getSectionDownloadId(section); section.isDownloading = true; @@ -1914,7 +1919,7 @@ export class CoreCourseHelperProvider { modules.map((module) => this.removeModuleStoredData(module, courseId)), ); - await CoreCourse.setCourseStatus(courseId, CoreConstants.NOT_DOWNLOADED); + await CoreCourse.setCourseStatus(courseId, DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED); } /** @@ -2068,7 +2073,7 @@ export type CoreCourseSection = CoreCourseWSSection & { * Section with data about prefetch. */ export type CoreCourseSectionWithStatus = CoreCourseSection & { - downloadStatus?: string; // Section status. + downloadStatus?: TDownloadStatus; // Section status. isDownloading?: boolean; // Whether section is being downloaded. total?: number; // Total of modules being downloaded. count?: number; // Number of downloaded modules. diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index 8b1143cbe61..0451da80fd8 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -22,7 +22,7 @@ import { CoreSitesCommonWSOptions, CoreSites, CoreSitesReadingStrategy } from '@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUtils } from '@services/utils/utils'; import { CoreSite } from '@classes/sites/site'; -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus, TDownloadStatus } from '@/core/constants'; import { makeSingleton, Translate } from '@singletons'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; @@ -268,7 +268,11 @@ export class CoreCourseProvider { this.logger.debug('Clear all course status for site ' + site.id); await this.statusTables[site.getId()].delete(); - this.triggerCourseStatusChanged(CoreCourseProvider.ALL_COURSES_CLEARED, CoreConstants.NOT_DOWNLOADED, site.id); + this.triggerCourseStatusChanged( + CoreCourseProvider.ALL_COURSES_CLEARED, + DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, + site.id, + ); } /** @@ -473,13 +477,13 @@ export class CoreCourseProvider { * @param siteId Site ID. If not defined, current site. * @returns Promise resolved with the status. */ - async getCourseStatus(courseId: number, siteId?: string): Promise { + async getCourseStatus(courseId: number, siteId?: string): Promise { try { const entry = await this.getCourseStatusData(courseId, siteId); - return entry.status || CoreConstants.NOT_DOWNLOADED; + return entry.status || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } catch { - return CoreConstants.NOT_DOWNLOADED; + return DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } } @@ -490,7 +494,8 @@ export class CoreCourseProvider { * @returns Resolves with an array containing downloaded course ids. */ async getDownloadedCourseIds(siteId?: string): Promise { - const downloadedStatuses = [CoreConstants.DOWNLOADED, CoreConstants.DOWNLOADING, CoreConstants.OUTDATED]; + const downloadedStatuses: TDownloadStatus[] = + [DownloadStatus.DOWNLOADED, DownloadStatus.DOWNLOADING, DownloadStatus.OUTDATED]; const site = await CoreSites.getSite(siteId); const entries = await this.statusTables[site.getId()].getManyWhere({ sql: 'status IN (?,?,?)', @@ -1398,7 +1403,7 @@ export class CoreCourseProvider { * @param siteId Site ID. If not defined, current site. * @returns Promise resolved when the status is changed. Resolve param: new status. */ - async setCoursePreviousStatus(courseId: number, siteId?: string): Promise { + async setCoursePreviousStatus(courseId: number, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); this.logger.debug(`Set previous status for course ${courseId} in site ${siteId}`); @@ -1410,10 +1415,10 @@ export class CoreCourseProvider { const newData = { id: courseId, - status: entry.previous || CoreConstants.NOT_DOWNLOADED, + status: entry.previous || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, updated: Date.now(), // Going back from downloading to previous status, restore previous download time. - downloadTime: entry.status == CoreConstants.DOWNLOADING ? entry.previousDownloadTime : entry.downloadTime, + downloadTime: entry.status == DownloadStatus.DOWNLOADING ? entry.previousDownloadTime : entry.downloadTime, }; await this.statusTables[site.getId()].update(newData, { id: courseId }); @@ -1431,7 +1436,7 @@ export class CoreCourseProvider { * @param siteId Site ID. If not defined, current site. * @returns Promise resolved when the status is stored. */ - async setCourseStatus(courseId: number, status: string, siteId?: string): Promise { + async setCourseStatus(courseId: number, status: TDownloadStatus, siteId?: string): Promise { siteId = siteId || CoreSites.getCurrentSiteId(); this.logger.debug(`Set status '${status}' for course ${courseId} in site ${siteId}`); @@ -1439,9 +1444,9 @@ export class CoreCourseProvider { const site = await CoreSites.getSite(siteId); let downloadTime = 0; let previousDownloadTime = 0; - let previousStatus = ''; + let previousStatus: TDownloadStatus | undefined; - if (status == CoreConstants.DOWNLOADING) { + if (status === DownloadStatus.DOWNLOADING) { // Set download time if course is now downloading. downloadTime = CoreTimeUtils.timestamp(); } @@ -1461,7 +1466,7 @@ export class CoreCourseProvider { // New entry. } - if (previousStatus != status) { + if (previousStatus !== status) { // Status has changed, update it. await this.statusTables[site.getId()].insert({ id: courseId, @@ -1529,7 +1534,7 @@ export class CoreCourseProvider { * @param status New course status. * @param siteId Site ID. If not defined, current site. */ - protected triggerCourseStatusChanged(courseId: number, status: string, siteId?: string): void { + protected triggerCourseStatusChanged(courseId: number, status: TDownloadStatus, siteId?: string): void { CoreEvents.trigger(CoreEvents.COURSE_STATUS_CHANGED, { courseId: courseId, status: status, diff --git a/src/core/features/course/services/database/course.ts b/src/core/features/course/services/database/course.ts index 0c114e1e0fe..32d04abb6c7 100644 --- a/src/core/features/course/services/database/course.ts +++ b/src/core/features/course/services/database/course.ts @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { TDownloadStatus } from '@/core/constants'; import { CoreSiteSchema } from '@services/sites'; /** @@ -120,8 +121,8 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = { export type CoreCourseStatusDBRecord = { id: number; - status: string; - previous: string; + status: TDownloadStatus; + previous: TDownloadStatus | undefined; updated: number; downloadTime: number; previousDownloadTime: number; diff --git a/src/core/features/course/services/module-delegate.ts b/src/core/features/course/services/module-delegate.ts index 0c524c4d63c..195f8daddfb 100644 --- a/src/core/features/course/services/module-delegate.ts +++ b/src/core/features/course/services/module-delegate.ts @@ -25,6 +25,7 @@ import { makeSingleton } from '@singletons'; import { CoreCourseModuleData } from './course-helper'; import { CoreNavigationOptions } from '@services/navigator'; import { CoreIonicColorNames } from '@singletons/colors'; +import { TDownloadStatus } from '@/core/constants'; /** * Interface that all course module handlers must implement. @@ -222,7 +223,7 @@ export interface CoreCourseModuleHandlerData { * * @param status Module status. */ - updateStatus?(status: string): void; + updateStatus?(status: TDownloadStatus): void; /** * On Destroy function in case it's needed. diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index 5451cb1390b..fa5166b06b2 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -25,7 +25,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile } from './course'; import { CoreCache } from '@classes/cache'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { makeSingleton } from '@singletons'; import { CoreEvents, CoreEventSectionStatusChangedData } from '@singletons/events'; @@ -160,7 +160,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + ): Promise { const handler = this.getPrefetchHandlerFor(module.modname); if (!handler) { // No handler found, module not downloadable. - return CoreConstants.NOT_DOWNLOADABLE; + return DownloadStatus.NOT_DOWNLOADABLE; } // Check if the status is cached. const packageId = CoreFilepool.getPackageId(handler.component, module.id); - const status = this.statusCache.getValue(packageId, 'status'); + const status = this.statusCache.getValue(packageId, 'status'); if (!refresh && status !== undefined) { this.storeCourseAndSection(packageId, courseId, sectionId); @@ -571,12 +571,12 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + ): Promise<{status: TDownloadStatus; updateStatus: boolean}> { // Check if the module is downloadable. const downloadable = await this.isModuleDownloadable(module, courseId); if (!downloadable) { return { - status: CoreConstants.NOT_DOWNLOADABLE, + status: DownloadStatus.NOT_DOWNLOADABLE, updateStatus: true, }; } @@ -586,7 +586,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status', true); + const status = this.statusCache.getValue(packageId, 'status', true); return { - status: this.determineModuleStatus(module, status || CoreConstants.NOT_DOWNLOADED), + status: this.determineModuleStatus(module, status || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED), updateStatus: true, }; } @@ -676,11 +676,11 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status', true); + const cacheStatus = this.statusCache.getValue(packageId, 'status', true); if (cacheStatus === undefined) { throw error; } @@ -748,7 +748,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status'); + const status = this.statusCache.getValue(packageId, 'status'); if (status !== undefined && !CoreFileHelper.isStateDownloaded(status)) { return {}; @@ -760,7 +760,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status', true); + const cachedStatus = this.statusCache.getValue(packageId, 'status', true); // If courseId/sectionId is set, store it. this.storeCourseAndSection(packageId, courseId, sectionId); @@ -1404,7 +1404,7 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler { * @param canCheck Whether the site allows checking for updates. This parameter was deprecated since app 4.0. * @returns Status to display. */ - determineStatus?(module: CoreCourseAnyModuleData, status: string, canCheck: true): string; + determineStatus?(module: CoreCourseAnyModuleData, status: TDownloadStatus, canCheck: true): TDownloadStatus; /** * Get the downloaded size of a module. If not defined, we'll use getFiles to calculate it (it can be slow). @@ -1497,11 +1497,11 @@ type CourseUpdates = Record; */ export type CoreCourseModulesStatus = { total: number; // Number of modules. - status: string; // Status of the list of modules. - [CoreConstants.NOT_DOWNLOADED]: CoreCourseModuleData[]; // Modules with state NOT_DOWNLOADED. - [CoreConstants.DOWNLOADED]: CoreCourseModuleData[]; // Modules with state DOWNLOADED. - [CoreConstants.DOWNLOADING]: CoreCourseModuleData[]; // Modules with state DOWNLOADING. - [CoreConstants.OUTDATED]: CoreCourseModuleData[]; // Modules with state OUTDATED. + status: TDownloadStatus; // Status of the list of modules. + [DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED]: CoreCourseModuleData[]; // Modules with state NOT_DOWNLOADED. + [DownloadStatus.DOWNLOADED]: CoreCourseModuleData[]; // Modules with state DOWNLOADED. + [DownloadStatus.DOWNLOADING]: CoreCourseModuleData[]; // Modules with state DOWNLOADING. + [DownloadStatus.OUTDATED]: CoreCourseModuleData[]; // Modules with state OUTDATED. }; /** diff --git a/src/core/features/courses/components/course-list-item/course-list-item.ts b/src/core/features/courses/components/course-list-item/course-list-item.ts index 449fbf5b86f..5a110359f07 100644 --- a/src/core/features/courses/components/course-list-item/course-list-item.ts +++ b/src/core/features/courses/components/course-list-item/course-list-item.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; import { CoreCourseProvider, CoreCourse } from '@features/course/services/course'; import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper'; @@ -51,7 +51,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On prefetchCourseData: CorePrefetchStatusInfo = { icon: '', statusTranslatable: 'core.loading', - status: '', + status: DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, loading: true, }; @@ -60,7 +60,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On progress = -1; completionUserTracked: boolean | undefined = false; - protected courseStatus = CoreConstants.NOT_DOWNLOADED; + protected courseStatus: TDownloadStatus = DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; protected isDestroyed = false; protected courseStatusObserver?: CoreEventObserver; @@ -211,7 +211,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On * * @param status Status to show. */ - protected updateCourseStatus(status: string): void { + protected updateCourseStatus(status: TDownloadStatus): void { const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status); this.courseStatus = status; @@ -219,7 +219,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On this.prefetchCourseData.icon = statusData.icon; this.prefetchCourseData.statusTranslatable = statusData.statusTranslatable; this.prefetchCourseData.loading = statusData.loading; - this.prefetchCourseData.downloadSucceeded = status === CoreConstants.DOWNLOADED; + this.prefetchCourseData.downloadSucceeded = status === DownloadStatus.DOWNLOADED; } /** @@ -295,7 +295,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On } break; case 'delete': - if (this.courseStatus == CoreConstants.DOWNLOADED || this.courseStatus == CoreConstants.OUTDATED) { + if (this.courseStatus === DownloadStatus.DOWNLOADED || this.courseStatus === DownloadStatus.OUTDATED) { this.deleteCourseStoredData(); } break; diff --git a/src/core/features/h5p/components/h5p-iframe/h5p-iframe.ts b/src/core/features/h5p/components/h5p-iframe/h5p-iframe.ts index e4faf397d0c..577eb9d663b 100644 --- a/src/core/features/h5p/components/h5p-iframe/h5p-iframe.ts +++ b/src/core/features/h5p/components/h5p-iframe/h5p-iframe.ts @@ -24,7 +24,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreH5P } from '@features/h5p/services/h5p'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreSite } from '@classes/sites/site'; import { CoreLogger } from '@singletons/logger'; import { CoreH5PCore, CoreH5PDisplayOptions } from '../../classes/core'; @@ -100,7 +100,7 @@ export class CoreH5PIframeComponent implements OnChanges, OnDestroy { */ protected async play(): Promise { let localUrl: string | undefined; - let state: string; + let state: TDownloadStatus; this.onlinePlayerUrl = this.onlinePlayerUrl || CoreH5P.h5pPlayer.calculateOnlinePlayerUrl( this.site.getURL(), this.fileUrl || '', @@ -111,7 +111,7 @@ export class CoreH5PIframeComponent implements OnChanges, OnDestroy { if (this.fileUrl) { state = await CoreFilepool.getFileStateByUrl(this.siteId, this.fileUrl); } else { - state = CoreConstants.NOT_DOWNLOADABLE; + state = DownloadStatus.NOT_DOWNLOADABLE; } if (this.siteCanDownload && CoreFileHelper.isStateDownloaded(state)) { diff --git a/src/core/features/h5p/components/h5p-player/h5p-player.ts b/src/core/features/h5p/components/h5p-player/h5p-player.ts index 1b158ca877d..cf67708138a 100644 --- a/src/core/features/h5p/components/h5p-player/h5p-player.ts +++ b/src/core/features/h5p/components/h5p-player/h5p-player.ts @@ -20,7 +20,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrlUtils } from '@services/utils/url'; import { CorePluginFileDelegate } from '@services/plugin-file-delegate'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { CoreSite } from '@classes/sites/site'; import { CoreEvents, CoreEventObserver } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; @@ -94,7 +94,10 @@ export class CoreH5PPlayerComponent implements OnInit, OnChanges, OnDestroy { this.displayOptions = CoreH5P.h5pPlayer.getDisplayOptionsFromUrlParams(this.urlParams); this.showPackage = true; - if (!this.canDownload$.getValue() || (this.state != CoreConstants.OUTDATED && this.state != CoreConstants.NOT_DOWNLOADED)) { + if ( + !this.canDownload$.getValue() || + (this.state !== DownloadStatus.OUTDATED && this.state !== DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) + ) { return; } diff --git a/src/core/services/database/filepool.ts b/src/core/services/database/filepool.ts index af922424585..7346d7a25d8 100644 --- a/src/core/services/database/filepool.ts +++ b/src/core/services/database/filepool.ts @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { TDownloadStatus } from '@/core/constants'; import { CoreAppSchema } from '@services/app'; import { CoreSiteSchema } from '@services/sites'; @@ -314,12 +315,12 @@ export type CoreFilepoolPackageEntry = { /** * Package status. */ - status?: string; + status?: TDownloadStatus; /** * Package previous status. */ - previous?: string; + previous?: TDownloadStatus; /** * Timestamp when this package was updated. diff --git a/src/core/services/file-helper.ts b/src/core/services/file-helper.ts index 4914dab064b..9e9b026d041 100644 --- a/src/core/services/file-helper.ts +++ b/src/core/services/file-helper.ts @@ -23,7 +23,7 @@ import { CoreWS, CoreWSFile } from '@services/ws'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils'; -import { CoreConstants } from '@/core/constants'; +import { CoreConstants, DownloadStatus, TDownloadStatus } from '@/core/constants'; import { CoreError } from '@classes/errors/error'; import { makeSingleton, Translate } from '@singletons'; import { CoreNetworkError } from '@classes/errors/network-error'; @@ -63,7 +63,7 @@ export class CoreFileHelperProvider { file: CoreWSFile, component?: string, componentId?: string | number, - state?: string, + state?: TDownloadStatus, onProgress?: CoreFileHelperOnProgress, siteId?: string, options: CoreUtilsOpenFileOptions = {}, @@ -113,11 +113,11 @@ export class CoreFileHelperProvider { state = await CoreFilepool.getFileStateByUrl(siteId, fileUrl, timemodified); } - if (state == CoreConstants.DOWNLOADING) { + if (state === DownloadStatus.DOWNLOADING) { throw new CoreError(Translate.instant('core.erroropenfiledownloading')); } - if (state === CoreConstants.NOT_DOWNLOADED) { + if (state === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // File is not downloaded, download and then return the local URL. url = await this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId); } else { @@ -150,7 +150,7 @@ export class CoreFileHelperProvider { component?: string, componentId?: string | number, timemodified?: number, - state?: string, + state?: TDownloadStatus, onProgress?: CoreFileHelperOnProgress, siteId?: string, options: CoreUtilsOpenFileOptions = {}, @@ -174,7 +174,7 @@ export class CoreFileHelperProvider { const isWifi = CoreNetwork.isWifi(); const isOnline = CoreNetwork.isOnline(); - if (state == CoreConstants.DOWNLOADED) { + if (state === DownloadStatus.DOWNLOADED) { // File is downloaded, get the local file URL. return CoreFilepool.getUrlByUrl(siteId, fileUrl, component, componentId, timemodified, false, false, file); } else { @@ -191,7 +191,7 @@ export class CoreFileHelperProvider { const shouldDownloadFirst = await CoreFilepool.shouldDownloadFileBeforeOpen(fixedUrl, file.filesize || 0, options); if (shouldDownloadFirst) { // Download the file first. - if (state == CoreConstants.DOWNLOADING) { + if (state === DownloadStatus.DOWNLOADING) { // It's already downloading, stop. return fixedUrl; } @@ -304,8 +304,8 @@ export class CoreFileHelperProvider { * @param state The state to check. * @returns If file has been downloaded (or outdated). */ - isStateDownloaded(state: string): boolean { - return state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED; + isStateDownloaded(state: TDownloadStatus): boolean { + return state === DownloadStatus.DOWNLOADED || state === DownloadStatus.OUTDATED; } /** diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index 995b6c15834..8dad71e354d 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -29,7 +29,7 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils'; import { CoreError } from '@classes/errors/error'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus } from '@/core/constants'; import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { @@ -593,7 +593,12 @@ export class CoreFilepoolProvider { } // Trigger module status changed, setting it as not downloaded. - this.triggerPackageStatusChanged(siteId, CoreConstants.NOT_DOWNLOADED, entry.component, entry.componentId); + this.triggerPackageStatusChanged( + siteId, + DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED, + entry.component, + entry.componentId, + ); }); } @@ -669,36 +674,36 @@ export class CoreFilepoolProvider { /** * Given the current status of a list of packages and the status of one of the packages, * determine the new status for the list of packages. The status of a list of packages is: - * - CoreConstants.NOT_DOWNLOADABLE if there are no downloadable packages. - * - CoreConstants.NOT_DOWNLOADED if at least 1 package has status CoreConstants.NOT_DOWNLOADED. - * - CoreConstants.DOWNLOADED if ALL the downloadable packages have status CoreConstants.DOWNLOADED. - * - CoreConstants.DOWNLOADING if ALL the downloadable packages have status CoreConstants.DOWNLOADING or - * CoreConstants.DOWNLOADED, with at least 1 package with CoreConstants.DOWNLOADING. - * - CoreConstants.OUTDATED if ALL the downloadable packages have status CoreConstants.OUTDATED or CoreConstants.DOWNLOADED - * or CoreConstants.DOWNLOADING, with at least 1 package with CoreConstants.OUTDATED. + * - NOT_DOWNLOADABLE if there are no downloadable packages. + * - DOWNLOADABLE_NOT_DOWNLOADED if at least 1 package has status DOWNLOADABLE_NOT_DOWNLOADED. + * - DOWNLOADED if ALL the downloadable packages have status DOWNLOADED. + * - DOWNLOADING if ALL the downloadable packages have status DOWNLOADING or DOWNLOADED, with at least 1 package + * with status DOWNLOADING. + * - OUTDATED if ALL the downloadable packages have status OUTDATED or DOWNLOADED or DOWNLOADING, with at least 1 package + * with OUTDATED. * * @param current Current status of the list of packages. * @param packageStatus Status of one of the packages. * @returns New status for the list of packages; */ - determinePackagesStatus(current: string, packageStatus: string): string { + determinePackagesStatus(current: TDownloadStatus, packageStatus: TDownloadStatus): TDownloadStatus { if (!current) { - current = CoreConstants.NOT_DOWNLOADABLE; + current = DownloadStatus.NOT_DOWNLOADABLE; } - if (packageStatus === CoreConstants.NOT_DOWNLOADED) { + if (packageStatus === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // If 1 package is not downloaded the status of the whole list will always be not downloaded. - return CoreConstants.NOT_DOWNLOADED; - } else if (packageStatus === CoreConstants.DOWNLOADED && current === CoreConstants.NOT_DOWNLOADABLE) { + return DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; + } else if (packageStatus === DownloadStatus.DOWNLOADED && current === DownloadStatus.NOT_DOWNLOADABLE) { // If all packages are downloaded or not downloadable with at least 1 downloaded, status will be downloaded. - return CoreConstants.DOWNLOADED; - } else if (packageStatus === CoreConstants.DOWNLOADING && - (current === CoreConstants.NOT_DOWNLOADABLE || current === CoreConstants.DOWNLOADED)) { + return DownloadStatus.DOWNLOADED; + } else if (packageStatus === DownloadStatus.DOWNLOADING && + (current === DownloadStatus.NOT_DOWNLOADABLE || current === DownloadStatus.DOWNLOADED)) { // If all packages are downloading/downloaded/notdownloadable with at least 1 downloading, status will be downloading. - return CoreConstants.DOWNLOADING; - } else if (packageStatus === CoreConstants.OUTDATED && current !== CoreConstants.NOT_DOWNLOADED) { + return DownloadStatus.DOWNLOADING; + } else if (packageStatus === DownloadStatus.OUTDATED && current !== DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED) { // If there are no packages notdownloaded and there is at least 1 outdated, status will be outdated. - return CoreConstants.OUTDATED; + return DownloadStatus.OUTDATED; } // Status remains the same. @@ -886,7 +891,7 @@ export class CoreFilepoolProvider { } // Set package as downloading. - const promise = this.storePackageStatus(siteId, CoreConstants.DOWNLOADING, component, componentId).then(async () => { + const promise = this.storePackageStatus(siteId, DownloadStatus.DOWNLOADING, component, componentId).then(async () => { const promises: Promise[] = []; let packageLoaded = 0; @@ -959,7 +964,7 @@ export class CoreFilepoolProvider { try { await Promise.all(promises); // Success prefetching, store package as downloaded. - await this.storePackageStatus(siteId, CoreConstants.DOWNLOADED, component, componentId, extra); + await this.storePackageStatus(siteId, DownloadStatus.DOWNLOADED, component, componentId, extra); return; } catch (error) { @@ -1520,13 +1525,13 @@ export class CoreFilepoolProvider { timemodified: number = 0, filePath?: string, revision?: number, - ): Promise { + ): Promise { let file: CoreWSFile; try { file = await this.fixPluginfileURL(siteId, fileUrl, timemodified); } catch (e) { - return CoreConstants.NOT_DOWNLOADABLE; + return DownloadStatus.NOT_DOWNLOADABLE; } fileUrl = CoreUrl.removeUrlAnchor(CoreFileHelper.getFileUrl(file)); @@ -1538,7 +1543,7 @@ export class CoreFilepoolProvider { // Check if the file is in queue (waiting to be downloaded). await this.hasFileInQueue(siteId, fileId); - return CoreConstants.DOWNLOADING; + return DownloadStatus.DOWNLOADING; } catch (e) { // Check if the file is being downloaded right now. const extension = CoreMimetypeUtils.guessExtensionFromUrl(fileUrl); @@ -1547,7 +1552,7 @@ export class CoreFilepoolProvider { const downloadId = this.getFileDownloadId(fileUrl, filePath); if (this.filePromises[siteId] && this.filePromises[siteId][downloadId] !== undefined) { - return CoreConstants.DOWNLOADING; + return DownloadStatus.DOWNLOADING; } try { @@ -1555,12 +1560,12 @@ export class CoreFilepoolProvider { const entry = await this.hasFileInPool(siteId, fileId); if (this.isFileOutdated(entry, revision, timemodified)) { - return CoreConstants.OUTDATED; + return DownloadStatus.OUTDATED; } - return CoreConstants.DOWNLOADED; + return DownloadStatus.DOWNLOADED; } catch (e) { - return CoreConstants.NOT_DOWNLOADED; + return DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } } } @@ -1855,13 +1860,13 @@ export class CoreFilepoolProvider { * @param componentId An ID to use in conjunction with the component. * @returns Promise resolved with the status. */ - async getPackagePreviousStatus(siteId: string, component: string, componentId?: string | number): Promise { + async getPackagePreviousStatus(siteId: string, component: string, componentId?: string | number): Promise { try { const entry = await this.getPackageData(siteId, component, componentId); - return entry.previous || CoreConstants.NOT_DOWNLOADED; + return entry.previous || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } catch (error) { - return CoreConstants.NOT_DOWNLOADED; + return DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } } @@ -1873,13 +1878,13 @@ export class CoreFilepoolProvider { * @param componentId An ID to use in conjunction with the component. * @returns Promise resolved with the status. */ - async getPackageStatus(siteId: string, component: string, componentId?: string | number): Promise { + async getPackageStatus(siteId: string, component: string, componentId?: string | number): Promise { try { const entry = await this.getPackageData(siteId, component, componentId); - return entry.status || CoreConstants.NOT_DOWNLOADED; + return entry.status || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } catch (error) { - return CoreConstants.NOT_DOWNLOADED; + return DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; } } @@ -2324,7 +2329,7 @@ export class CoreFilepoolProvider { ): Promise { const state = await this.getFileStateByUrl(siteId, fileUrl, timemodified, filePath, revision); - return state != CoreConstants.NOT_DOWNLOADABLE; + return state !== DownloadStatus.NOT_DOWNLOADABLE; } /** @@ -2807,7 +2812,7 @@ export class CoreFilepoolProvider { * @param componentId An ID to use in conjunction with the component. * @returns Promise resolved when the status is changed. Resolve param: new status. */ - async setPackagePreviousStatus(siteId: string, component: string, componentId?: string | number): Promise { + async setPackagePreviousStatus(siteId: string, component: string, componentId?: string | number): Promise { componentId = this.fixComponentId(componentId); this.logger.debug(`Set previous status for package ${component} ${componentId}`); @@ -2816,11 +2821,11 @@ export class CoreFilepoolProvider { // Get current stored data, we'll only update 'status' and 'updated' fields. const entry = await this.packagesTables[siteId].getOneByPrimaryKey({ id: packageId }); const newData: CoreFilepoolPackageEntry = {}; - if (entry.status == CoreConstants.DOWNLOADING) { + if (entry.status === DownloadStatus.DOWNLOADING) { // Going back from downloading to previous status, restore previous download time. newData.downloadTime = entry.previousDownloadTime; } - newData.status = entry.previous || CoreConstants.NOT_DOWNLOADED; + newData.status = entry.previous || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED; newData.updated = Date.now(); this.logger.debug(`Set previous status '${entry.status}' for package ${component} ${componentId}`); @@ -2886,7 +2891,7 @@ export class CoreFilepoolProvider { */ async storePackageStatus( siteId: string, - status: string, + status: TDownloadStatus, component: string, componentId?: string | number, extra?: string, @@ -2898,12 +2903,12 @@ export class CoreFilepoolProvider { let downloadTime: number | undefined; let previousDownloadTime: number | undefined; - if (status == CoreConstants.DOWNLOADING) { + if (status === DownloadStatus.DOWNLOADING) { // Set download time if package is now downloading. downloadTime = CoreTimeUtils.timestamp(); } - let previousStatus: string | undefined; + let previousStatus: TDownloadStatus | undefined; // Search current status to set it as previous status. try { const entry = await this.packagesTables[siteId].getOneByPrimaryKey({ id: packageId }); @@ -3050,7 +3055,12 @@ export class CoreFilepoolProvider { * @param component Package's component. * @param componentId An ID to use in conjunction with the component. */ - protected triggerPackageStatusChanged(siteId: string, status: string, component: string, componentId?: string | number): void { + protected triggerPackageStatusChanged( + siteId: string, + status: TDownloadStatus, + component: string, + componentId?: string | number, + ): void { const data: CoreEventPackageStatusChanged = { component, componentId: this.fixComponentId(componentId), @@ -3068,7 +3078,6 @@ export class CoreFilepoolProvider { * @param siteId Site ID. * @param component Package's component. * @param componentId An ID to use in conjunction with the component. - * @returns Promise resolved when status is stored. */ async updatePackageDownloadTime(siteId: string, component: string, componentId?: string | number): Promise { componentId = this.fixComponentId(componentId); diff --git a/src/core/services/plugin-file-delegate.ts b/src/core/services/plugin-file-delegate.ts index 65b0b8e1262..69a640e1a3c 100644 --- a/src/core/services/plugin-file-delegate.ts +++ b/src/core/services/plugin-file-delegate.ts @@ -17,7 +17,7 @@ import { FileEntry } from '@awesome-cordova-plugins/file/ngx'; import { CoreFilepool, CoreFilepoolOnProgressCallback } from '@services/filepool'; import { CoreWSFile } from '@services/ws'; -import { CoreConstants } from '@/core/constants'; +import { DownloadStatus } from '@/core/constants'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { makeSingleton } from '@singletons'; import { CoreSites } from './sites'; @@ -141,7 +141,7 @@ export class CorePluginFileDelegateService extends CoreDelegate { const state = await CoreFilepool.getFileStateByUrl(siteIdentifier, CoreFileHelper.getFileUrl(file), file.timemodified); - if (state !== CoreConstants.DOWNLOADED && state !== CoreConstants.NOT_DOWNLOADABLE) { + if (state !== DownloadStatus.DOWNLOADED && state !== DownloadStatus.NOT_DOWNLOADABLE) { filteredFiles.push(file); } })); diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts index 5ae964ad209..9026c7616d1 100644 --- a/src/core/singletons/events.ts +++ b/src/core/singletons/events.ts @@ -21,6 +21,7 @@ import { CoreRedirectPayload } from '@services/navigator'; import { CoreCourseModuleCompletionData } from '@features/course/services/course-helper'; import { CoreScreenOrientation } from '@services/screen'; import { CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site'; +import { TDownloadStatus } from '../constants'; /** * Observer instance to stop listening to an event. @@ -326,7 +327,7 @@ export type CoreEventLoadingChangedData = { */ export type CoreEventCourseStatusChanged = { courseId: number; // Course Id. - status: string; + status: TDownloadStatus; }; /** @@ -335,7 +336,7 @@ export type CoreEventCourseStatusChanged = { export type CoreEventPackageStatusChanged = { component: string; componentId: string | number; - status: string; + status: TDownloadStatus; }; /** From 054160f322ee0195125828bfeeff4f8b76b245cf Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 7 Mar 2024 11:54:14 +0100 Subject: [PATCH 3/3] MOBILE-4539 course: Stop calling isDownloadable in course page --- .../course/components/module/module.ts | 4 +- .../services/module-prefetch-delegate.ts | 95 ++++++++++++++++++- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/core/features/course/components/module/module.ts b/src/core/features/course/components/module/module.ts index 5a1d42fb7b8..3f02e900d58 100644 --- a/src/core/features/course/components/module/module.ts +++ b/src/core/features/course/components/module/module.ts @@ -115,7 +115,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { } if (this.showDownloadStatus && this.module.handlerData.showDownloadButton) { - const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course); + const status = await CoreCourseModulePrefetchDelegate.getDownloadedModuleStatus(this.module, this.module.course); this.updateModuleStatus(status); // Listen for changes on this module status, even if download isn't enabled. @@ -146,7 +146,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { * * @param prefetchStatus Module status. */ - protected updateModuleStatus(prefetchStatus: TDownloadStatus): void { + protected updateModuleStatus(prefetchStatus: TDownloadStatus | null): void { if (!prefetchStatus) { return; } diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index fa5166b06b2..0a56dc30ddb 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -25,7 +25,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreCourse, CoreCourseAnyModuleData, CoreCourseModuleContentFile } from './course'; import { CoreCache } from '@classes/cache'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; -import { DownloadStatus, TDownloadStatus } from '@/core/constants'; +import { DownloadStatus, TDownloadStatus, TDownloadedStatus } from '@/core/constants'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; import { makeSingleton } from '@singletons'; import { CoreEvents, CoreEventSectionStatusChangedData } from '@singletons/events'; @@ -554,6 +554,52 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { + const handler = this.getPrefetchHandlerFor(module.modname); + if (!handler) { + // No handler found, module not downloadable. + return null; + } + + // Check if the status is cached. + const packageId = CoreFilepool.getPackageId(handler.component, module.id); + const status = this.statusCache.getValue(packageId, 'status'); + + if (!refresh && status !== undefined) { + this.storeCourseAndSection(packageId, courseId, sectionId); + + return this.filterDownloadedStatus(this.determineModuleStatus(module, status)); + } + + const result = await this.calculateDownloadedModuleStatus(handler, module, courseId, updates, sectionId); + if (result.updateStatus && result.status) { + this.updateStatusCache(result.status, handler.component, module.id, courseId, sectionId); + } + + return this.filterDownloadedStatus( + this.determineModuleStatus(module, result.status ?? DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED), + ); + } + /** * Calculate a module status. * @@ -581,14 +627,42 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { // Get the saved package status. const siteId = CoreSites.getCurrentSiteId(); const currentStatus = await CoreFilepool.getPackageStatus(siteId, handler.component, module.id); let status = handler.determineStatus ? handler.determineStatus(module, currentStatus, true) : currentStatus; - if (status != DownloadStatus.DOWNLOADED || updates === false) { + if (status !== DownloadStatus.DOWNLOADED || updates === false) { return { - status, + status: this.filterDownloadedStatus(status), updateStatus: true, }; } @@ -604,7 +678,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate(packageId, 'status', true); return { - status: this.determineModuleStatus(module, status || DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED), + status: status ? this.filterDownloadedStatus(status) : null, updateStatus: true, }; } } + /** + * Given a download status, filter it to return only the downloaded statuses. + * + * @param status Status. + * @returns Filtered status, null for not downloaded statuses. + */ + protected filterDownloadedStatus(status: TDownloadStatus): TDownloadedStatus | null { + return status === DownloadStatus.NOT_DOWNLOADABLE || status === DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED ? + null : status; + } + /** * Get the status of a list of modules, along with the lists of modules for each status. *