MOBILE-3931 module: Merge duplicated prefetch statuses
parent
344ee6d57e
commit
16cee9df14
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue