MOBILE-4660 storagemanager: Prefetch subsections
parent
a3bb081f60
commit
d3c3c56296
|
@ -0,0 +1,15 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
export const ADDON_MOD_SUBSECTION_COMPONENT = 'mmaModSubsection';
|
|
@ -0,0 +1,98 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler';
|
||||
import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSSection } from '@features/course/services/course';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { ADDON_MOD_SUBSECTION_COMPONENT } from '../../constants';
|
||||
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||
import { CoreFileSizeSum } from '@services/plugin-file-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreSites } from '@services/sites';
|
||||
|
||||
/**
|
||||
* Handler to prefetch subsections.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModSubsectionPrefetchHandlerService extends CoreCourseResourcePrefetchHandlerBase {
|
||||
|
||||
name = 'AddonModSubsection';
|
||||
modName = 'subsection';
|
||||
component = ADDON_MOD_SUBSECTION_COMPONENT;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async performDownloadOrPrefetch(
|
||||
siteId: string,
|
||||
module: CoreCourseModuleData,
|
||||
courseId: number,
|
||||
): Promise<void> {
|
||||
const section = await this.getSection(module, courseId, siteId);
|
||||
if (!section) {
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreCourseHelper.prefetchSections([section], courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getDownloadSize(module: CoreCourseAnyModuleData, courseId: number): Promise<CoreFileSizeSum> {
|
||||
const section = await this.getSection(module, courseId);
|
||||
if (!section) {
|
||||
return { size: 0, total: true };
|
||||
}
|
||||
|
||||
return await CoreCourseModulePrefetchDelegate.getDownloadSize(section.modules, courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getDownloadedSize(module: CoreCourseAnyModuleData, courseId: number): Promise<number> {
|
||||
const section = await this.getSection(module, courseId);
|
||||
if (!section) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CoreCourseHelper.getModulesDownloadedSize(section.modules, courseId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the section of a module.
|
||||
*
|
||||
* @param module Module.
|
||||
* @param courseId Course ID.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @returns Promise resolved with the section if found.
|
||||
*/
|
||||
protected async getSection(
|
||||
module: CoreCourseAnyModuleData,
|
||||
courseId: number,
|
||||
siteId?: string,
|
||||
): Promise<CoreCourseWSSection | undefined> {
|
||||
siteId = siteId ?? CoreSites.getCurrentSiteId();
|
||||
|
||||
const sections = await CoreCourse.getSections(courseId, false, true, undefined, siteId);
|
||||
|
||||
return sections.find((section) =>
|
||||
section.component === 'mod_subsection' && section.itemid === module.instance);
|
||||
}
|
||||
|
||||
}
|
||||
export const AddonModSubsectionPrefetchHandler = makeSingleton(AddonModSubsectionPrefetchHandlerService);
|
|
@ -15,6 +15,8 @@
|
|||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { AddonModSubsectionIndexLinkHandler } from './services/handlers/index-link';
|
||||
import { AddonModSubsectionPrefetchHandler } from './services/handlers/prefetch';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
|
@ -23,6 +25,7 @@ import { AddonModSubsectionIndexLinkHandler } from './services/handlers/index-li
|
|||
multi: true,
|
||||
useValue: () => {
|
||||
CoreContentLinksDelegate.registerHandler(AddonModSubsectionIndexLinkHandler.instance);
|
||||
CoreCourseModulePrefetchDelegate.registerHandler(AddonModSubsectionPrefetchHandler.instance);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
<div class="storage-buttons" slot="end" *ngIf="(!section.calculatingSize && section.totalSize > 0) || downloadEnabled">
|
||||
<div *ngIf="downloadEnabled" slot="end" class="core-button-spinner">
|
||||
<core-download-refresh *ngIf="!section.isDownloading && section.downloadStatus !== statusDownloaded"
|
||||
[status]="section.downloadStatus" [enabled]="true" (action)="prefecthSection(section)"
|
||||
[status]="section.downloadStatus" [enabled]="true" (action)="prefetchSection(section)"
|
||||
[loading]="section.isDownloading || section.isCalculating" [canTrustDownload]="true"
|
||||
[statusesTranslatable]="{notdownloaded: 'addon.storagemanager.downloaddatafrom' }"
|
||||
[statusSubject]="section.name" />
|
||||
|
|
|
@ -30,10 +30,10 @@ import { CoreLoadings } from '@services/loadings';
|
|||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreArray } from '@singletons/array';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreEventObserver, CoreEvents, CoreEventSectionStatusChangedData } from '@singletons/events';
|
||||
|
||||
/**
|
||||
* Page that displays the amount of file storage used by each activity on the course, and allows
|
||||
|
@ -120,11 +120,12 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
.map(section => ({
|
||||
...section,
|
||||
totalSize: 0,
|
||||
calculatingSize: true,
|
||||
calculatingSize: false,
|
||||
expanded: section.id === initialSectionId,
|
||||
modules: section.modules.map(module => ({
|
||||
...module,
|
||||
calculatingSize: true,
|
||||
totalSize: 0,
|
||||
calculatingSize: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
|
@ -162,8 +163,6 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
/**
|
||||
* Init course prefetch information.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async initCoursePrefetch(): Promise<void> {
|
||||
if (!this.downloadCourseEnabled || this.courseStatusObserver) {
|
||||
|
@ -180,7 +179,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
// Determine the course prefetch status.
|
||||
await this.determineCoursePrefetchIcon();
|
||||
|
||||
if (this.prefetchCourseData.icon != CoreConstants.ICON_LOADING) {
|
||||
if (this.prefetchCourseData.icon !== CoreConstants.ICON_LOADING) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -203,8 +202,6 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
/**
|
||||
* Init module prefetch information.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async initModulePrefetch(): Promise<void> {
|
||||
if (!this.downloadEnabled || this.sectionStatusObserver) {
|
||||
|
@ -219,46 +216,44 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
// Check if the affected section is being downloaded.
|
||||
// If so, we don't update section status because it'll already be updated when the download finishes.
|
||||
const downloadId = CoreCourseHelper.getSectionDownloadId({ id: data.sectionId });
|
||||
if (CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the affected section.
|
||||
const sectionFinder = CoreCourseHelper.findSectionWithSubsection(this.sections, data.sectionId);
|
||||
if (!sectionFinder?.section) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate the status.
|
||||
await CoreCourseHelper.calculateSectionStatus(sectionFinder.section, this.courseId, false);
|
||||
if (sectionFinder.subSection) {
|
||||
await CoreCourseHelper.calculateSectionStatus(sectionFinder.subSection, this.courseId, false);
|
||||
const section = sectionFinder.section;
|
||||
|
||||
// Check if the affected section is being downloaded.
|
||||
// If so, we don't update section status because it'll already be updated when the download finishes.
|
||||
const downloadId = CoreCourseHelper.getSectionDownloadId({ id: section.id });
|
||||
if (CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sectionFinder.section.isDownloading && !CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
// Recalculate the status.
|
||||
await this.updateSizes([section]);
|
||||
|
||||
if (section.isDownloading && !CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
// All the modules are now downloading, set a download all promise.
|
||||
this.prefecthSection(sectionFinder.section);
|
||||
this.prefetchSection(section);
|
||||
}
|
||||
},
|
||||
CoreSites.getCurrentSiteId(),
|
||||
);
|
||||
|
||||
// The download status of a section might have been changed from within a module page.
|
||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, false, false);
|
||||
|
||||
this.sections.forEach((section) => {
|
||||
this.calculateModulesStatusOnSection(section);
|
||||
});
|
||||
|
||||
this.moduleStatusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => {
|
||||
let moduleFound: AddonStorageManagerModule | undefined;
|
||||
|
||||
this.sections.some((section) =>
|
||||
section.modules.some((module) => {
|
||||
if (module.subSection) {
|
||||
if (module.id === data.componentId &&
|
||||
module.prefetchHandler &&
|
||||
data.component === module.prefetchHandler?.component) {
|
||||
moduleFound = module;
|
||||
|
||||
return true;
|
||||
} else if (module.subSection) {
|
||||
return module.subSection.modules.some((module) => {
|
||||
if (module.id === data.componentId &&
|
||||
module.prefetchHandler &&
|
||||
|
@ -268,14 +263,6 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (module.id === data.componentId &&
|
||||
module.prefetchHandler &&
|
||||
data.component === module.prefetchHandler?.component) {
|
||||
moduleFound = module;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -287,87 +274,81 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
// Call determineModuleStatus to get the right status to display.
|
||||
const status = CoreCourseModulePrefetchDelegate.determineModuleStatus(moduleFound, data.status);
|
||||
if (moduleFound.subSection) {
|
||||
const data: CoreEventSectionStatusChangedData = {
|
||||
sectionId: moduleFound.subSection.id,
|
||||
courseId: this.courseId,
|
||||
};
|
||||
CoreEvents.trigger(CoreEvents.SECTION_STATUS_CHANGED, data, CoreSites.getCurrentSiteId());
|
||||
}
|
||||
|
||||
// Update the status.
|
||||
this.updateModuleStatus(moduleFound, status);
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
// The download status of a section might have been changed from within a module page.
|
||||
this.updateSizes(this.sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init section, course and modules sizes.
|
||||
*/
|
||||
protected async initSizes(): Promise<void> {
|
||||
const modules = this.getAllModulesList();
|
||||
await Promise.all(modules.map(async (module) => {
|
||||
await this.calculateModuleSize(module);
|
||||
}));
|
||||
|
||||
await this.updateModulesSizes(modules);
|
||||
await this.updateSizes(this.sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the sizes of some modules.
|
||||
* Update the sizes of some sections and modules.
|
||||
*
|
||||
* @param modules Modules.
|
||||
* @returns Promise resolved when done.
|
||||
* @param sections Modules.
|
||||
*/
|
||||
protected async updateModulesSizes(modules: AddonStorageManagerModule[]): Promise<void> {
|
||||
protected async updateSizes(sections: AddonStorageManagerCourseSection[]): Promise<void> {
|
||||
sections = CoreArray.unique(sections, 'id');
|
||||
|
||||
this.calculatingSize = true;
|
||||
let section: AddonStorageManagerCourseSection | undefined;
|
||||
let subSection: AddonStorageManagerCourseSection | undefined;
|
||||
|
||||
await Promise.all(modules.map(async (module) => {
|
||||
if (module.calculatingSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
module.calculatingSize = true;
|
||||
|
||||
const sectionFinder = CoreCourseHelper.findSectionWithSubsection(this.sections, module.section);
|
||||
section = sectionFinder?.section;
|
||||
if (section) {
|
||||
section.calculatingSize = true;
|
||||
|
||||
subSection = sectionFinder?.subSection;
|
||||
if (subSection) {
|
||||
subSection.calculatingSize = true;
|
||||
sections.forEach((section) => {
|
||||
section.calculatingSize = true;
|
||||
section.modules.map((module) => {
|
||||
if (module.subSection) {
|
||||
module.subSection.calculatingSize = true;
|
||||
}
|
||||
}
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
});
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
|
||||
// Update only affected module sections.
|
||||
const modules = this.getAllModulesList(sections);
|
||||
await Promise.all(modules.map(async (module) => {
|
||||
await this.calculateModuleSize(module);
|
||||
}));
|
||||
|
||||
const updateSectionSize = (section: AddonStorageManagerCourseSection): void => {
|
||||
section.totalSize = 0;
|
||||
section.calculatingSize = true;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
|
||||
section.modules.forEach((module) => {
|
||||
if (module.subSection) {
|
||||
updateSectionSize(module.subSection);
|
||||
module.totalSize = module.subSection.totalSize;
|
||||
}
|
||||
|
||||
section.totalSize += module.totalSize ?? 0;
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
section.calculatingSize = false;
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
};
|
||||
|
||||
// Update section and total sizes.
|
||||
this.totalSize = 0;
|
||||
this.sections.forEach((section) => {
|
||||
section.totalSize = 0;
|
||||
section.modules.forEach((module) => {
|
||||
if (module.subSection) {
|
||||
const subSection = module.subSection;
|
||||
|
||||
subSection.totalSize = 0;
|
||||
subSection.modules.forEach((module) => {
|
||||
if (module.totalSize && module.totalSize > 0) {
|
||||
subSection.totalSize += module.totalSize;
|
||||
}
|
||||
});
|
||||
subSection.calculatingSize = false;
|
||||
|
||||
section.totalSize += module.subSection.totalSize;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (module.totalSize && module.totalSize > 0) {
|
||||
section.totalSize += module.totalSize;
|
||||
}
|
||||
});
|
||||
|
||||
section.calculatingSize = false;
|
||||
updateSectionSize(section);
|
||||
this.totalSize += section.totalSize;
|
||||
});
|
||||
|
||||
this.calculatingSize = false;
|
||||
|
||||
// Mark course as not downloaded if course size is 0.
|
||||
|
@ -376,6 +357,9 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
|
||||
await this.calculateSectionsStatus(sections);
|
||||
this.changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -402,7 +386,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
const modules = this.getAllModulesList().filter((module) => module.totalSize && module.totalSize > 0);
|
||||
const modules = this.getAllModulesList(this.sections).filter((module) => module.totalSize && module.totalSize > 0);
|
||||
|
||||
await this.deleteModules(modules);
|
||||
}
|
||||
|
@ -489,16 +473,21 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
* Deletes the specified modules, showing the loading overlay while it happens.
|
||||
*
|
||||
* @param modules Modules to delete
|
||||
* @returns Promise<void> Once deleting has finished
|
||||
*/
|
||||
protected async deleteModules(modules: AddonStorageManagerModule[]): Promise<void> {
|
||||
const modal = await CoreLoadings.show('core.deleting', true);
|
||||
|
||||
const sections: AddonStorageManagerCourseSection[] = [];
|
||||
const promises = modules.map(async (module) => {
|
||||
// Remove the files.
|
||||
await CoreCourseHelper.removeModuleStoredData(module, this.courseId);
|
||||
|
||||
module.totalSize = 0;
|
||||
|
||||
const sectionFinder = CoreCourseHelper.findSectionWithSubsection(this.sections, module.section);
|
||||
if (sectionFinder?.section) {
|
||||
sections.push(sectionFinder?.section);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
|
@ -508,8 +497,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
modal.dismiss();
|
||||
|
||||
await this.updateModulesSizes(modules);
|
||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, false, false);
|
||||
await this.updateSizes(sections);
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
@ -526,39 +514,26 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
CoreCourse.setCourseStatus(this.courseId, DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the status of sections.
|
||||
*
|
||||
* @param refresh If refresh or not.
|
||||
*/
|
||||
protected calculateSectionsStatus(refresh?: boolean): void {
|
||||
if (!this.sections) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreUtils.ignoreErrors(CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, refresh));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm and prefetch a section. If the section is "all sections", prefetch all the sections.
|
||||
*
|
||||
* @param section Section to download.
|
||||
*/
|
||||
async prefecthSection(section: AddonStorageManagerCourseSection): Promise<void> {
|
||||
async prefetchSection(section: AddonStorageManagerCourseSection): Promise<void> {
|
||||
section.isCalculating = true;
|
||||
this.changeDetectorRef.markForCheck();
|
||||
try {
|
||||
await CoreCourseHelper.confirmDownloadSizeSection(this.courseId, section, this.sections);
|
||||
await CoreCourseHelper.confirmDownloadSizeSection(this.courseId, [section]);
|
||||
|
||||
try {
|
||||
await CoreCourseHelper.prefetchSection(section, this.courseId, this.sections);
|
||||
await CoreCourseHelper.prefetchSections([section], this.courseId);
|
||||
|
||||
} catch (error) {
|
||||
if (!this.isDestroyed) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
|
||||
}
|
||||
} finally {
|
||||
await this.updateModulesSizes(section.modules);
|
||||
await this.updateSizes([section]);
|
||||
}
|
||||
} catch (error) {
|
||||
// User cancelled or there was an error calculating the size.
|
||||
|
@ -594,12 +569,9 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
try {
|
||||
// Get download size to ask for confirm if it's high.
|
||||
|
||||
const size = await module.prefetchHandler.getDownloadSize(module, module.course, true);
|
||||
|
||||
await CoreCourseHelper.prefetchModule(module.prefetchHandler, module, size, module.course, refresh);
|
||||
|
||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, false, false);
|
||||
} catch (error) {
|
||||
if (!this.isDestroyed) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
|
@ -607,7 +579,10 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
module.spinner = false;
|
||||
|
||||
await this.updateModulesSizes([module]);
|
||||
const sectionFinder = CoreCourseHelper.findSectionWithSubsection(this.sections, module.section);
|
||||
if (sectionFinder?.section) {
|
||||
await this.updateSizes([sectionFinder?.section]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,37 +611,23 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
*/
|
||||
protected async calculateModulesStatusOnSection(section: AddonStorageManagerCourseSection): Promise<void> {
|
||||
await Promise.all(section.modules.map(async (module) => {
|
||||
if (module.subSection) {
|
||||
await this.calculateModulesStatusOnSection(module.subSection);
|
||||
} else if (module.handlerData?.showDownloadButton) {
|
||||
if (module.handlerData?.showDownloadButton) {
|
||||
module.spinner = true;
|
||||
// Listen for changes on this module status, even if download isn't enabled.
|
||||
module.prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(module.modname);
|
||||
await this.calculateModuleStatus(module);
|
||||
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, this.courseId);
|
||||
|
||||
this.updateModuleStatus(module, status);
|
||||
}
|
||||
|
||||
if (module.subSection) {
|
||||
await this.calculateModulesStatusOnSection(module.subSection);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and show module status.
|
||||
*
|
||||
* @param module Module to update.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async calculateModuleStatus(module: AddonStorageManagerModule): Promise<void> {
|
||||
if (!module) {
|
||||
return;
|
||||
}
|
||||
|
||||
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(module, this.courseId);
|
||||
|
||||
this.updateModuleStatus(module, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the prefetch icon of the course.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async determineCoursePrefetchIcon(): Promise<void> {
|
||||
this.prefetchCourseData = await CoreCourseHelper.getCourseStatusIconAndTitle(this.courseId);
|
||||
|
@ -739,8 +700,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
},
|
||||
);
|
||||
|
||||
const modules = this.getAllModulesList();
|
||||
await this.updateModulesSizes(modules);
|
||||
await this.updateSizes(this.sections);
|
||||
} catch (error) {
|
||||
if (this.isDestroyed) {
|
||||
return;
|
||||
|
@ -753,21 +713,20 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Get all modules list.
|
||||
*
|
||||
* @param sections Sections to get the modules from.
|
||||
* @returns All modules list.
|
||||
*/
|
||||
protected getAllModulesList(): AddonStorageManagerModule[] {
|
||||
protected getAllModulesList(sections: AddonStorageManagerCourseSection[]): AddonStorageManagerModule[] {
|
||||
const modules: AddonStorageManagerModule[] = [];
|
||||
this.sections.forEach((section) => {
|
||||
sections.forEach((section) => {
|
||||
section.modules.forEach((module) => {
|
||||
modules.push(module);
|
||||
|
||||
if (module.subSection) {
|
||||
module.subSection.modules.forEach((module) => {
|
||||
modules.push(module);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
modules.push(module);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -775,12 +734,17 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Calculate the size of a module.
|
||||
* Calculate the size of the modules.
|
||||
*
|
||||
* @param module Module to calculate.
|
||||
*/
|
||||
protected async calculateModuleSize(module: AddonStorageManagerModule): Promise<void> {
|
||||
if (module.calculatingSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
module.calculatingSize = true;
|
||||
this.changeDetectorRef.markForCheck();
|
||||
|
||||
// Note: This function only gets the size for modules which are downloadable.
|
||||
// For other modules it always returns 0, even if they have downloaded some files.
|
||||
|
@ -789,15 +753,10 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
// But these aren't necessarily consistent, for example mod_frog vs mmaModFrog.
|
||||
// There is nothing enforcing correct values.
|
||||
// Most modules which have large files are downloadable, so I think this is sufficient.
|
||||
const size = await CoreUtils.ignoreErrors(CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId));
|
||||
module.totalSize = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId);
|
||||
|
||||
if (size !== undefined) {
|
||||
// There are some cases where the return from this is not a valid number.
|
||||
module.totalSize = !isNaN(size) ? Number(size) : 0;
|
||||
}
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
module.calculatingSize = false;
|
||||
this.changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -845,6 +804,39 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
this.isDestroyed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the status of a list of sections, setting attributes to determine the icons/data to be shown.
|
||||
*
|
||||
* @param sections Sections to calculate their status.
|
||||
*/
|
||||
protected async calculateSectionsStatus(
|
||||
sections: AddonStorageManagerCourseSection[],
|
||||
): Promise<void> {
|
||||
if (!sections) {
|
||||
return;
|
||||
}
|
||||
|
||||
await Promise.all(sections.map(async (section) => {
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
section.isCalculating = true;
|
||||
await this.calculateModulesStatusOnSection(section);
|
||||
await CoreCourseHelper.calculateSectionStatus(section, this.courseId, false, false);
|
||||
|
||||
await Promise.all(section.modules.map(async (module) => {
|
||||
if (module.subSection) {
|
||||
return CoreCourseHelper.calculateSectionStatus(module.subSection, this.courseId, false, false);
|
||||
}
|
||||
}));
|
||||
} finally {
|
||||
section.isCalculating = false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type AddonStorageManagerCourseSection = Omit<CoreCourseSectionWithStatus, 'modules'> & {
|
||||
|
|
|
@ -17,7 +17,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
|
|||
import { CoreQueueRunner } from '@classes/queue-runner';
|
||||
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses';
|
||||
import { CoreSettingsHelper, CoreSiteSpaceUsage } from '@features/settings/services/settings-helper';
|
||||
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
|
||||
|
@ -241,14 +240,8 @@ export class AddonStorageManagerCoursesStoragePage implements OnInit, OnDestroy
|
|||
private async calculateDownloadedCourseSize(courseId: number): Promise<number> {
|
||||
const sections = await CoreCourse.getSections(courseId);
|
||||
const modules = CoreCourseHelper.getSectionsModules(sections);
|
||||
const promisedModuleSizes = modules.map(async (module) => {
|
||||
const size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId);
|
||||
|
||||
return isNaN(size) ? 0 : size;
|
||||
});
|
||||
const moduleSizes = await Promise.all(promisedModuleSizes);
|
||||
|
||||
return moduleSizes.reduce((totalSize, moduleSize) => totalSize + moduleSize, 0);
|
||||
return CoreCourseHelper.getModulesDownloadedSize(modules, courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -142,11 +142,7 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
const moduleSize = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(this.module, this.courseId);
|
||||
|
||||
if (moduleSize) {
|
||||
this.size = moduleSize;
|
||||
}
|
||||
this.size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(this.module, this.courseId);
|
||||
}, 1000);
|
||||
|
||||
this.fileStatusObserver = CoreEvents.on(
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
CoreCourseModuleCompletionStatus,
|
||||
CoreCourseGetContentsWSModule,
|
||||
sectionContentIsModule,
|
||||
CoreCourseAnyModuleData,
|
||||
} from './course';
|
||||
import { CoreConstants, DownloadStatus, ContextLevel } from '@/core/constants';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
@ -283,14 +284,14 @@ export class CoreCourseHelperProvider {
|
|||
refresh?: boolean,
|
||||
checkUpdates: boolean = true,
|
||||
): Promise<{statusData: CoreCourseModulesStatus; section: CoreCourseSectionWithStatus}> {
|
||||
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
throw new CoreError('Invalid section');
|
||||
}
|
||||
|
||||
const sectionWithStatus = <CoreCourseSectionWithStatus> section;
|
||||
|
||||
// Get the status of this section.
|
||||
const result = await CoreCourseModulePrefetchDelegate.getModulesStatus(
|
||||
const statusData = await CoreCourseModulePrefetchDelegate.getModulesStatus(
|
||||
section.contents,
|
||||
courseId,
|
||||
section.id,
|
||||
|
@ -302,13 +303,13 @@ export class CoreCourseHelperProvider {
|
|||
// Check if it's being downloaded.
|
||||
const downloadId = this.getSectionDownloadId(section);
|
||||
if (CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
result.status = DownloadStatus.DOWNLOADING;
|
||||
statusData.status = DownloadStatus.DOWNLOADING;
|
||||
}
|
||||
|
||||
sectionWithStatus.downloadStatus = result.status;
|
||||
sectionWithStatus.downloadStatus = statusData.status;
|
||||
|
||||
// Set this section data.
|
||||
if (result.status !== DownloadStatus.DOWNLOADING) {
|
||||
if (statusData.status !== DownloadStatus.DOWNLOADING) {
|
||||
sectionWithStatus.isDownloading = false;
|
||||
sectionWithStatus.total = 0;
|
||||
} else {
|
||||
|
@ -320,62 +321,7 @@ export class CoreCourseHelperProvider {
|
|||
});
|
||||
}
|
||||
|
||||
return { statusData: result, section: sectionWithStatus };
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the status of a list of sections, setting attributes to determine the icons/data to be shown.
|
||||
*
|
||||
* @param sections Sections to calculate their status.
|
||||
* @param courseId Course ID the sections belong to.
|
||||
* @param refresh True if it shouldn't use module status cache (slower).
|
||||
* @param checkUpdates Whether to use the WS to check updates. Defaults to true.
|
||||
* @returns Promise resolved when the states are calculated.
|
||||
*/
|
||||
async calculateSectionsStatus(
|
||||
sections: CoreCourseSection[],
|
||||
courseId: number,
|
||||
refresh?: boolean,
|
||||
checkUpdates: boolean = true,
|
||||
): Promise<CoreCourseSectionWithStatus[]> {
|
||||
let allSectionsSection: CoreCourseSectionWithStatus | undefined;
|
||||
let allSectionsStatus = DownloadStatus.NOT_DOWNLOADABLE as DownloadStatus;
|
||||
|
||||
const promises = sections.map(async (section: CoreCourseSectionWithStatus) => {
|
||||
section.isCalculating = true;
|
||||
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
// "All sections" section status is calculated using the status of the rest of sections.
|
||||
allSectionsSection = section;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.calculateSectionStatus(section, courseId, refresh, checkUpdates);
|
||||
|
||||
// Calculate "All sections" status.
|
||||
allSectionsStatus = CoreFilepool.determinePackagesStatus(allSectionsStatus, result.statusData.status);
|
||||
} finally {
|
||||
section.isCalculating = false;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(promises);
|
||||
|
||||
if (allSectionsSection) {
|
||||
// Set "All sections" data.
|
||||
allSectionsSection.downloadStatus = allSectionsStatus;
|
||||
allSectionsSection.isDownloading = allSectionsStatus === DownloadStatus.DOWNLOADING;
|
||||
}
|
||||
|
||||
return sections;
|
||||
} finally {
|
||||
if (allSectionsSection) {
|
||||
allSectionsSection.isCalculating = false;
|
||||
}
|
||||
}
|
||||
return { statusData, section: sectionWithStatus };
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +357,7 @@ export class CoreCourseHelperProvider {
|
|||
}
|
||||
|
||||
// Confirm the download.
|
||||
await this.confirmDownloadSizeSection(course.id, undefined, options.sections, true);
|
||||
await this.confirmDownloadSizeSection(course.id, options.sections, true);
|
||||
|
||||
// User confirmed, get the course handlers if needed.
|
||||
if (!options.courseHandlers) {
|
||||
|
@ -508,48 +454,36 @@ export class CoreCourseHelperProvider {
|
|||
* Calculate the size to download a section and show a confirm modal if needed.
|
||||
*
|
||||
* @param courseId Course ID the section belongs to.
|
||||
* @param section Section. If not provided, all sections.
|
||||
* @param sections List of sections. Used when downloading all the sections.
|
||||
* @param sections List of sections to download
|
||||
* @param alwaysConfirm True to show a confirm even if the size isn't high, false otherwise.
|
||||
* @returns Promise resolved if the user confirms or there's no need to confirm.
|
||||
*/
|
||||
async confirmDownloadSizeSection(
|
||||
courseId: number,
|
||||
section?: CoreCourseWSSection,
|
||||
sections?: CoreCourseWSSection[],
|
||||
alwaysConfirm?: boolean,
|
||||
sections: CoreCourseWSSection[] = [],
|
||||
alwaysConfirm = false,
|
||||
): Promise<void> {
|
||||
let hasEmbeddedFiles = false;
|
||||
let sizeSum: CoreFileSizeSum = {
|
||||
const sizeSum: CoreFileSizeSum = {
|
||||
size: 0,
|
||||
total: true,
|
||||
};
|
||||
|
||||
// Calculate the size of the download.
|
||||
if (section && section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
sizeSum = await CoreCourseModulePrefetchDelegate.getDownloadSize(section.contents, courseId);
|
||||
await Promise.all(sections.map(async (section) => {
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sectionSize = await CoreCourseModulePrefetchDelegate.getDownloadSize(section.modules, courseId);
|
||||
|
||||
sizeSum.total = sizeSum.total && sectionSize.total;
|
||||
sizeSum.size += sectionSize.size;
|
||||
|
||||
// Check if the section has embedded files in the description.
|
||||
hasEmbeddedFiles = CoreFilepool.extractDownloadableFilesFromHtml(section.summary).length > 0;
|
||||
} else if (sections) {
|
||||
await Promise.all(sections.map(async (section) => {
|
||||
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sectionSize = await CoreCourseModulePrefetchDelegate.getDownloadSize(section.contents, courseId);
|
||||
|
||||
sizeSum.total = sizeSum.total && sectionSize.total;
|
||||
sizeSum.size += sectionSize.size;
|
||||
|
||||
// Check if the section has embedded files in the description.
|
||||
if (!hasEmbeddedFiles && CoreFilepool.extractDownloadableFilesFromHtml(section.summary).length > 0) {
|
||||
hasEmbeddedFiles = true;
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
throw new CoreError('Either section or list of sections needs to be supplied.');
|
||||
}
|
||||
if (!hasEmbeddedFiles && CoreFilepool.extractDownloadableFilesFromHtml(section.summary).length > 0) {
|
||||
hasEmbeddedFiles = true;
|
||||
}
|
||||
}));
|
||||
|
||||
if (hasEmbeddedFiles) {
|
||||
sizeSum.total = false;
|
||||
|
@ -559,6 +493,20 @@ export class CoreCourseHelperProvider {
|
|||
await CoreDomUtils.confirmDownloadSize(sizeSum, undefined, undefined, undefined, undefined, alwaysConfirm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums the stored module sizes.
|
||||
*
|
||||
* @param modules List of modules.
|
||||
* @param courseId Course ID.
|
||||
* @returns Promise resolved with the sum of the stored sizes.
|
||||
*/
|
||||
async getModulesDownloadedSize(modules: CoreCourseAnyModuleData[], courseId: number): Promise<number> {
|
||||
const moduleSizes = await Promise.all(modules.map(async (module) =>
|
||||
await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId)));
|
||||
|
||||
return moduleSizes.reduce((totalSize, moduleSize) => totalSize + moduleSize, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a course is accessed using guest access and if it requires user input to enter.
|
||||
*
|
||||
|
@ -1350,20 +1298,18 @@ export class CoreCourseHelperProvider {
|
|||
await CoreUtils.ignoreErrors(CoreCourseModulePrefetchDelegate.invalidateCourseUpdates(courseId));
|
||||
}
|
||||
|
||||
const results = await Promise.all([
|
||||
const [size, status, packageData] = await Promise.all([
|
||||
CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId),
|
||||
CoreCourseModulePrefetchDelegate.getModuleStatus(module, courseId),
|
||||
this.getModulePackageLastDownloaded(module, component),
|
||||
]);
|
||||
|
||||
// Treat stored size.
|
||||
const size = results[0];
|
||||
const sizeReadable = CoreText.bytesToSize(results[0], 2);
|
||||
const sizeReadable = CoreText.bytesToSize(size, 2);
|
||||
|
||||
// Treat module status.
|
||||
const status = results[1];
|
||||
let statusIcon: string | undefined;
|
||||
switch (results[1]) {
|
||||
switch (status) {
|
||||
case DownloadStatus.DOWNLOADABLE_NOT_DOWNLOADED:
|
||||
statusIcon = CoreConstants.ICON_NOT_DOWNLOADED;
|
||||
break;
|
||||
|
@ -1380,8 +1326,6 @@ export class CoreCourseHelperProvider {
|
|||
break;
|
||||
}
|
||||
|
||||
const packageData = results[2];
|
||||
|
||||
return {
|
||||
size,
|
||||
sizeReadable,
|
||||
|
@ -1625,12 +1569,7 @@ export class CoreCourseHelperProvider {
|
|||
|
||||
const promises: Promise<unknown>[] = [];
|
||||
|
||||
// Prefetch all the sections. If the first section is "All sections", use it. Otherwise, use a fake "All sections".
|
||||
let allSectionsSection: CoreCourseWSSection = sections[0];
|
||||
if (sections[0].id != CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
allSectionsSection = this.createAllSectionsSection();
|
||||
}
|
||||
promises.push(this.prefetchSection(allSectionsSection, course.id, sections));
|
||||
promises.push(this.prefetchSections(sections, course.id, true));
|
||||
|
||||
// Prefetch course options.
|
||||
courseHandlers.forEach((handler) => {
|
||||
|
@ -1700,41 +1639,32 @@ export class CoreCourseHelperProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Prefetch one section or all the sections.
|
||||
* If the section is "All sections" it will prefetch all the sections.
|
||||
* Prefetch some sections
|
||||
*
|
||||
* @param section Section.
|
||||
* @param sections List of sections. .
|
||||
* @param courseId Course ID the section belongs to.
|
||||
* @param sections List of sections. Used when downloading all the sections.
|
||||
* @returns Promise resolved when the prefetch is finished.
|
||||
* @param updateAllSections Update all sections status
|
||||
*/
|
||||
async prefetchSection(
|
||||
section: CoreCourseSectionWithStatus,
|
||||
async prefetchSections(
|
||||
sections: (CoreCourseSectionWithStatus & CoreCourseSectionWithSubsections)[],
|
||||
courseId: number,
|
||||
sections?: CoreCourseSectionWithStatus[],
|
||||
updateAllSections = false,
|
||||
): Promise<void> {
|
||||
if (section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
try {
|
||||
// Download only this section.
|
||||
await this.prefetchSingleSectionIfNeeded(section, courseId);
|
||||
} finally {
|
||||
// Calculate the status of the section that finished.
|
||||
await this.calculateSectionStatus(section, courseId, false, false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sections) {
|
||||
throw new CoreError('List of sections is required when downloading all sections.');
|
||||
}
|
||||
|
||||
// Download all the sections except "All sections".
|
||||
let allSectionsStatus = DownloadStatus.NOT_DOWNLOADABLE as DownloadStatus;
|
||||
let allSectionsSection: (CoreCourseSectionWithStatus) | undefined;
|
||||
if (updateAllSections) {
|
||||
// Prefetch all the sections. If the first section is "All sections", use it. Otherwise, use a fake "All sections".
|
||||
allSectionsSection = sections[0];
|
||||
if (sections[0].id !== CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
allSectionsSection = this.createAllSectionsSection();
|
||||
}
|
||||
allSectionsSection.isDownloading = true;
|
||||
}
|
||||
|
||||
section.isDownloading = true;
|
||||
const promises = sections.map(async (section) => {
|
||||
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
// Download all the sections except "All sections".
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1753,10 +1683,14 @@ export class CoreCourseHelperProvider {
|
|||
await CoreUtils.allPromises(promises);
|
||||
|
||||
// Set "All sections" data.
|
||||
section.downloadStatus = allSectionsStatus;
|
||||
section.isDownloading = allSectionsStatus === DownloadStatus.DOWNLOADING;
|
||||
if (allSectionsSection) {
|
||||
allSectionsSection.downloadStatus = allSectionsStatus;
|
||||
allSectionsSection.isDownloading = allSectionsStatus === DownloadStatus.DOWNLOADING;
|
||||
}
|
||||
} finally {
|
||||
section.isDownloading = false;
|
||||
if (allSectionsSection) {
|
||||
allSectionsSection.isDownloading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1769,7 +1703,7 @@ export class CoreCourseHelperProvider {
|
|||
* @returns Promise resolved when the section is prefetched.
|
||||
*/
|
||||
protected async prefetchSingleSectionIfNeeded(section: CoreCourseSectionWithStatus, courseId: number): Promise<void> {
|
||||
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID || section.hiddenbynumsections) {
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID || section.hiddenbynumsections) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1830,7 +1764,7 @@ export class CoreCourseHelperProvider {
|
|||
result: CoreCourseModulesStatus,
|
||||
courseId: number,
|
||||
): Promise<void> {
|
||||
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -472,17 +472,21 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo
|
|||
* @returns Promise resolved with the total size (0 if unknown)
|
||||
*/
|
||||
async getModuleStoredSize(module: CoreCourseAnyModuleData, courseId: number): Promise<number> {
|
||||
const site = CoreSites.getCurrentSite();
|
||||
const handler = this.getPrefetchHandlerFor(module.modname);
|
||||
try {
|
||||
const site = CoreSites.getCurrentSite();
|
||||
const handler = this.getPrefetchHandlerFor(module.modname);
|
||||
|
||||
const [downloadedSize, cachedSize] = await Promise.all([
|
||||
this.getModuleDownloadedSize(module, courseId),
|
||||
handler && site ? site.getComponentCacheSize(handler.component, module.id) : 0,
|
||||
]);
|
||||
const [downloadedSize, cachedSize] = await Promise.all([
|
||||
this.getModuleDownloadedSize(module, courseId),
|
||||
handler && site ? site.getComponentCacheSize(handler.component, module.id) : 0,
|
||||
]);
|
||||
|
||||
const totalSize = cachedSize + downloadedSize;
|
||||
const totalSize = cachedSize + downloadedSize;
|
||||
|
||||
return isNaN(totalSize) ? 0 : totalSize;
|
||||
return isNaN(totalSize) ? 0 : totalSize;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue