MOBILE-3931 module: Merge duplicated prefetch statuses

main
Pau Ferrer Ocaña 2022-02-15 17:12:37 +01:00
parent 344ee6d57e
commit 16cee9df14
7 changed files with 82 additions and 92 deletions

View File

@ -558,13 +558,9 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Displays some data based on the current status. * @inheritdoc
*
* @param status The current status.
* @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): void {
protected showStatus(status: string, previousStatus?: string): void {
this.showSpinner = status == CoreConstants.DOWNLOADING; this.showSpinner = status == CoreConstants.DOWNLOADING;
} }

View File

@ -63,7 +63,7 @@
<ion-label> <ion-label>
<h3>{{ 'core.lastdownloaded' | translate }}</h3> <h3>{{ 'core.lastdownloaded' | translate }}</h3>
<p>{{ downloadTimeReadable }}</p> <p>{{ downloadTimeReadable }}</p>
<ion-grid *ngIf="prefetchStatus === outdatedStatus" class="addon-mod_resource-outdated"> <ion-grid *ngIf="currentStatus === outdatedStatus" class="addon-mod_resource-outdated">
<ion-row class="ion-align-items-center"> <ion-row class="ion-align-items-center">
<ion-col size="auto"> <ion-col size="auto">
<ion-icon color="warning" name="fas-exclamation-triangle" aria-hidden="true"></ion-icon> <ion-icon color="warning" name="fas-exclamation-triangle" aria-hidden="true"></ion-icon>

View File

@ -125,6 +125,8 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.displayDescription = options.printintro === undefined || !!options.printintro; this.displayDescription = options.printintro === undefined || !!options.printintro;
this.dataRetrieved.emit(resource); this.dataRetrieved.emit(resource);
this.setStatusListener();
if (AddonModResourceHelper.isDisplayedInIframe(this.module)) { if (AddonModResourceHelper.isDisplayedInIframe(this.module)) {
const downloadResult = await this.downloadResourceIfNeeded(refresh, true); const downloadResult = await this.downloadResourceIfNeeded(refresh, true);
@ -202,7 +204,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
downloadable = await AddonModResourceHelper.isMainFileDownloadable(this.module); downloadable = await AddonModResourceHelper.isMainFileDownloadable(this.module);
if (downloadable) { if (downloadable) {
if (this.prefetchStatus === CoreConstants.OUTDATED && !this.isOnline) { if (this.currentStatus === CoreConstants.OUTDATED && !this.isOnline) {
// Warn the user that the file isn't updated. // Warn the user that the file isn't updated.
const alert = await CoreDomUtils.showAlert( const alert = await CoreDomUtils.showAlert(
undefined, undefined,

View File

@ -58,21 +58,20 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
hasOffline = false; // Resources don't have any data to sync. hasOffline = false; // Resources don't have any data to sync.
description?: string; // Module description. description?: string; // Module description.
prefetchStatus?: string;
downloadTimeReadable?: string; // Last download time in a readable format.
isDestroyed = false; // Whether the component is destroyed. isDestroyed = false; // Whether the component is destroyed.
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents. protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
protected isCurrentView = false; // Whether the component is in the current view. protected isCurrentView = false; // Whether the component is in the current view.
protected siteId?: string; // Current Site ID. protected siteId?: string; // Current Site ID.
protected statusObserver?: CoreEventObserver; // Observer of package status. Only if setStatusListener is called. protected statusObserver?: CoreEventObserver; // Observer of package status. Only if setStatusListener is called.
protected currentStatus?: string; // The current status of the module. Only if setStatusListener is called. currentStatus?: string; // 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; protected completionObserver?: CoreEventObserver;
protected logger: CoreLogger; protected logger: CoreLogger;
protected debouncedUpdateModule?: () => void; // Update the module after a certain time. protected debouncedUpdateModule?: () => void; // Update the module after a certain time.
protected showCompletion = false; // Whether to show completion inside the activity. protected showCompletion = false; // Whether to show completion inside the activity.
protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary. protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary.
protected packageStatusObserver?: CoreEventObserver; // Observer of package status.
constructor( constructor(
@Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent', @Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent',
@ -106,16 +105,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.fetchModule(); this.fetchModule();
}, 10000); }, 10000);
} }
this.packageStatusObserver = CoreEvents.on(
CoreEvents.PACKAGE_STATUS_CHANGED,
(data) => {
if (data.componentId == module.id && data.component == this.component) {
this.getPackageStatus();
}
},
this.siteId,
);
} }
/** /**
@ -203,7 +192,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
try { try {
await this.fetchContent(refresh); await this.fetchContent(refresh);
await this.getPackageStatus(refresh);
} catch (error) { } catch (error) {
if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) { if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) {
// Module not found, retry without using cache. // Module not found, retry without using cache.
@ -227,28 +215,25 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
} }
/** /**
* Updage package status. * Updage package last downloaded.
*
* @param refresh If prefetch info has to be refreshed.
*/ */
async getPackageStatus(refresh = false): Promise<void> { protected async getPackageLastDownloaded(): Promise<void> {
if (!this.module) { if (!this.module) {
return; return;
} }
const moduleInfo = const lastDownloaded =
await CoreCourseHelper.getModulePrefetchInfo(this.module, this.courseId, refresh, this.component); await CoreCourseHelper.getModulePackageLastDownloaded(this.module, this.component);
this.downloadTimeReadable = CoreTextUtils.ucFirst(moduleInfo.downloadTimeReadable); this.downloadTimeReadable = lastDownloaded.downloadTimeReadable;
this.prefetchStatus = moduleInfo.status;
} }
/** /**
* Check if the module is prefetched or being prefetched. To make it faster, just use the data calculated by fillContextMenu. * Check if the module is prefetched or being prefetched.
* This means that you need to call fillContextMenu to make this work. * To make it faster, just use the data calculated by setStatusListener.
*/ */
protected isPrefetched(): boolean { protected isPrefetched(): boolean {
return this.prefetchStatus != CoreConstants.NOT_DOWNLOADABLE && this.prefetchStatus != CoreConstants.NOT_DOWNLOADED; return this.currentStatus != CoreConstants.NOT_DOWNLOADABLE && this.currentStatus != CoreConstants.NOT_DOWNLOADED;
} }
/** /**
@ -308,6 +293,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
const previousStatus = this.currentStatus; const previousStatus = this.currentStatus;
this.currentStatus = data.status; this.currentStatus = data.status;
this.getPackageLastDownloaded();
this.showStatus(this.currentStatus, previousStatus); this.showStatus(this.currentStatus, previousStatus);
}, this.siteId); }, this.siteId);
} else if (!refresh) { } else if (!refresh) {
@ -322,6 +309,9 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.courseId, undefined, refresh); const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.courseId, undefined, refresh);
this.currentStatus = status; this.currentStatus = status;
this.getPackageLastDownloaded();
this.showStatus(status); this.showStatus(status);
} }
@ -451,7 +441,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.isDestroyed = true; this.isDestroyed = true;
this.statusObserver?.off(); this.statusObserver?.off();
this.completionObserver?.off(); this.completionObserver?.off();
this.packageStatusObserver?.off();
} }
/** /**

View File

@ -110,7 +110,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
return; return;
} }
// Set a minimum height value. // Set a minimum height value.
this.initialHeight = this.initialHeight || 56; this.initialHeight = this.initialHeight || 48;
this.previousHeight = this.initialHeight; this.previousHeight = this.initialHeight;
this.content = this.element.closest('ion-content'); this.content = this.element.closest('ion-content');

View File

@ -75,36 +75,19 @@ import { CoreStatusWithWarningsWSResponse } from '@services/ws';
/** /**
* Prefetch info of a module. * Prefetch info of a module.
*/ */
export type CoreCourseModulePrefetchInfo = { export type CoreCourseModulePrefetchInfo = CoreCourseModulePackageLastDownloaded & {
/** size: number; // Downloaded size.
* Downloaded size. sizeReadable: string; // Downloadable size in a readable format.
*/ status: string; // Module status.
size: number; statusIcon?: string; // Icon's name of the module status.
};
/** /**
* Downloadable size in a readable format. * Prefetch info of a module.
*/ */
sizeReadable: string; export type CoreCourseModulePackageLastDownloaded = {
downloadTime: number; // Time when the module was last downloaded.
/** downloadTimeReadable: string; // Download time in a readable format.
* Module status.
*/
status: string;
/**
* Icon's name of the module status.
*/
statusIcon?: string;
/**
* Time when the module was last downloaded.
*/
downloadTime: number;
/**
* Download time in a readable format.
*/
downloadTimeReadable: string;
}; };
/** /**
@ -1484,12 +1467,9 @@ export class CoreCourseHelperProvider {
async getModulePrefetchInfo( async getModulePrefetchInfo(
module: CoreCourseModuleData, module: CoreCourseModuleData,
courseId: number, courseId: number,
invalidateCache?: boolean, invalidateCache = false,
component?: string, component = '',
): Promise<CoreCourseModulePrefetchInfo> { ): Promise<CoreCourseModulePrefetchInfo> {
const siteId = CoreSites.getCurrentSiteId();
if (invalidateCache) { if (invalidateCache) {
// Currently, some modules pass invalidateCache=false because they already invalidate data in downloadResourceIfNeeded. // Currently, some modules pass invalidateCache=false because they already invalidate data in downloadResourceIfNeeded.
// If this function is changed to do more actions if invalidateCache=true, please review those modules. // If this function is changed to do more actions if invalidateCache=true, please review those modules.
@ -1501,7 +1481,7 @@ export class CoreCourseHelperProvider {
const results = await Promise.all([ const results = await Promise.all([
CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId), CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId),
CoreCourseModulePrefetchDelegate.getModuleStatus(module, courseId), CoreCourseModulePrefetchDelegate.getModuleStatus(module, courseId),
CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, component || '', module.id)), this.getModulePackageLastDownloaded(module, component),
]); ]);
// Treat stored size. // Treat stored size.
@ -1528,33 +1508,53 @@ export class CoreCourseHelperProvider {
break; break;
} }
// Treat download time. const packageData = results[2];
if (!results[2] || !results[2].downloadTime || !CoreFileHelper.isStateDownloaded(results[2].status || '')) {
// Not downloaded.
return { return {
size, size,
sizeReadable, sizeReadable,
status, status,
statusIcon, statusIcon,
downloadTime: packageData.downloadTime,
downloadTimeReadable: packageData.downloadTimeReadable,
};
}
/**
* Get prefetch info for a module.
*
* @param module Module to get the info from.
* @param component Component of the module.
* @return Promise resolved with the info.
*/
async getModulePackageLastDownloaded(
module: CoreCourseModuleData,
component = '',
): Promise<CoreCourseModulePackageLastDownloaded> {
const siteId = CoreSites.getCurrentSiteId();
const packageData = await CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, component, module.id));
// Treat download time.
if (!packageData || !packageData.downloadTime || !CoreFileHelper.isStateDownloaded(packageData.status || '')) {
// Not downloaded.
return {
downloadTime: 0, downloadTime: 0,
downloadTimeReadable: '', downloadTimeReadable: '',
}; };
} }
const now = CoreTimeUtils.timestamp(); const now = CoreTimeUtils.timestamp();
const downloadTime = results[2].downloadTime; const downloadTime = packageData.downloadTime;
let downloadTimeReadable = ''; let downloadTimeReadable = '';
if (now - results[2].downloadTime < 7 * 86400) { if (now - downloadTime < 7 * 86400) {
downloadTimeReadable = moment(results[2].downloadTime * 1000).fromNow(); downloadTimeReadable = moment(downloadTime * 1000).fromNow();
} else { } else {
downloadTimeReadable = moment(results[2].downloadTime * 1000).calendar(); downloadTimeReadable = moment(downloadTime * 1000).calendar();
} }
downloadTimeReadable = CoreTextUtils.ucFirst(downloadTimeReadable);
return { return {
size,
sizeReadable,
status,
statusIcon,
downloadTime, downloadTime,
downloadTimeReadable, downloadTimeReadable,
}; };

View File

@ -233,6 +233,9 @@
} }
--core-loading-spinner: var(--brand); --core-loading-spinner: var(--brand);
ion-loading {
--spinner-color: var(--core-loading-spinner);
}
ion-spinner, ion-refresher { ion-spinner, ion-refresher {
--ion-color-base: var(--core-loading-spinner); --ion-color-base: var(--core-loading-spinner);
--ion-color-primary: var(--core-loading-spinner); --ion-color-primary: var(--core-loading-spinner);