MOBILE-3659 course: Implement prefetch delegate
parent
d14540218a
commit
031f238117
|
@ -201,6 +201,7 @@ const appConfig = {
|
|||
'no-duplicate-imports': 'error',
|
||||
'no-empty': 'error',
|
||||
'no-eval': 'error',
|
||||
'no-fallthrough': 'off',
|
||||
'no-invalid-this': 'error',
|
||||
'no-irregular-whitespace': 'error',
|
||||
'no-multiple-empty-lines': 'error',
|
||||
|
|
|
@ -17,7 +17,7 @@ import { CoreSites } from '@services/sites';
|
|||
import { CoreCourse, CoreCourseSection } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreSiteHome, FrontPageItemNames } from '@features/sitehome/services/sitehome';
|
||||
// @todo import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
|
||||
|
||||
/**
|
||||
|
@ -63,7 +63,7 @@ export class AddonBlockSiteMainMenuComponent extends CoreBlockBaseComponent impl
|
|||
|
||||
if (this.mainMenuBlock && this.mainMenuBlock.modules) {
|
||||
// Invalidate modules prefetch data.
|
||||
// @todo promises.push(this.prefetchDelegate.invalidateModules(this.mainMenuBlock.modules, this.siteHomeId));
|
||||
promises.push(CoreCourseModulePrefetchDelegate.instance.invalidateModules(this.mainMenuBlock.modules, this.siteHomeId));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
<ng-container *ngFor="let module of section.modules">
|
||||
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [courseId]="course?.id"
|
||||
[downloadEnabled]="downloadEnabled" [section]="section" (completionChanged)="onCompletionChange($event)"
|
||||
(statusChanged)="onModuleStatusChange($event)">
|
||||
(statusChanged)="onModuleStatusChange()">
|
||||
</core-course-module>
|
||||
</ng-container>
|
||||
</section>
|
||||
|
|
|
@ -37,15 +37,13 @@ import {
|
|||
CoreCourseModuleData,
|
||||
CoreCourseProvider,
|
||||
} from '@features/course/services/course';
|
||||
// import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreCourseHelper, CoreCourseSectionFormatted, CoreCourseSectionWithStatus } from '@features/course/services/course-helper';
|
||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||
import { CoreEventObserver, CoreEvents, CoreEventSectionStatusChangedData, CoreEventSelectCourseTabData } from '@singletons/events';
|
||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
// import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreBlockCourseBlocksComponent } from '@features/block/components/course-blocks/course-blocks';
|
||||
import { CoreCourseSectionFormatted } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleStatusChangedData } from '../module/module';
|
||||
import { ModalController } from '@singletons';
|
||||
import { CoreCourseSectionSelectorComponent } from '../section-selector/section-selector';
|
||||
|
||||
|
@ -62,13 +60,14 @@ import { CoreCourseSectionSelectorComponent } from '../section-selector/section-
|
|||
@Component({
|
||||
selector: 'core-course-format',
|
||||
templateUrl: 'core-course-format.html',
|
||||
styleUrls: ['format.scss'],
|
||||
})
|
||||
export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
static readonly LOAD_MORE_ACTIVITIES = 20; // How many activities should load each time showMoreActivities is called.
|
||||
|
||||
@Input() course?: CoreCourseAnyCourseData; // The course to render.
|
||||
@Input() sections?: CoreCourseSectionFormatted[]; // List of course sections.
|
||||
@Input() sections?: CoreCourseSectionWithStatus[]; // List of course sections. The status will be calculated in this component.
|
||||
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||
|
@ -125,26 +124,26 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
// @todo Check if the affected section is being downloaded.
|
||||
// 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.instance.getSectionDownloadId({ id: data.sectionId });
|
||||
// if (prefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
// return;
|
||||
// }
|
||||
const downloadId = CoreCourseHelper.instance.getSectionDownloadId({ id: data.sectionId });
|
||||
if (CoreCourseModulePrefetchDelegate.instance.isBeingDownloaded(downloadId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the affected section.
|
||||
// const section = this.sections.find(section => section.id == data.sectionId);
|
||||
// if (!section) {
|
||||
// return;
|
||||
// }
|
||||
const section = this.sections.find(section => section.id == data.sectionId);
|
||||
if (!section) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate the status.
|
||||
// await CoreCourseHelper.instance.calculateSectionStatus(section, this.course.id, false);
|
||||
await CoreCourseHelper.instance.calculateSectionStatus(section, this.course.id, false);
|
||||
|
||||
// if (section.isDownloading && !prefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
// // All the modules are now downloading, set a download all promise.
|
||||
// this.prefetch(section);
|
||||
// }
|
||||
if (section.isDownloading && !CoreCourseModulePrefetchDelegate.instance.isBeingDownloaded(downloadId)) {
|
||||
// All the modules are now downloading, set a download all promise.
|
||||
this.prefetch(section);
|
||||
}
|
||||
},
|
||||
CoreSites.instance.getCurrentSiteId(),
|
||||
);
|
||||
|
@ -392,7 +391,9 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.canLoadMore = false;
|
||||
this.showSectionId = 0;
|
||||
this.showMoreActivities();
|
||||
// @todo CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
||||
if (this.downloadEnabled) {
|
||||
this.calculateSectionsStatus(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.moduleId && typeof previousValue == 'undefined') {
|
||||
|
@ -427,11 +428,12 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
*
|
||||
* @param refresh If refresh or not.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected calculateSectionsStatus(refresh?: boolean): void {
|
||||
// @todo CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, refresh).catch(() => {
|
||||
// // Ignore errors (shouldn't happen).
|
||||
// });
|
||||
if (!this.sections || !this.course) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreUtils.instance.ignoreErrors(CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, refresh));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -440,38 +442,42 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
* @param section Section to download.
|
||||
* @param refresh Refresh clicked (not used).
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
prefetch(section: CoreCourseSectionFormatted): void {
|
||||
// section.isCalculating = true;
|
||||
// @todo CoreCourseHelper.instance.confirmDownloadSizeSection(this.course.id, section, this.sections).then(() => {
|
||||
// this.prefetchSection(section, true);
|
||||
// }, (error) => {
|
||||
// // User cancelled or there was an error calculating the size.
|
||||
// if (error) {
|
||||
// CoreDomUtils.instance.showErrorModal(error);
|
||||
// }
|
||||
// }).finally(() => {
|
||||
// section.isCalculating = false;
|
||||
// });
|
||||
async prefetch(section: CoreCourseSectionWithStatus): Promise<void> {
|
||||
section.isCalculating = true;
|
||||
|
||||
try {
|
||||
await CoreCourseHelper.instance.confirmDownloadSizeSection(this.course!.id, section, this.sections);
|
||||
|
||||
await this.prefetchSection(section, true);
|
||||
} catch (error) {
|
||||
// User cancelled or there was an error calculating the size.
|
||||
if (error) {
|
||||
CoreDomUtils.instance.showErrorModal(error);
|
||||
}
|
||||
} finally {
|
||||
section.isCalculating = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch a section. @todo
|
||||
* Prefetch a section.
|
||||
*
|
||||
* @param section The section to download.
|
||||
* @param manual Whether the prefetch was started manually or it was automatically started because all modules
|
||||
* are being downloaded.
|
||||
*/
|
||||
// protected prefetchSection(section: Section, manual?: boolean): void {
|
||||
// CoreCourseHelper.instance.prefetchSection(section, this.course.id, this.sections).catch((error) => {
|
||||
// // Don't show error message if it's an automatic download.
|
||||
// if (!manual) {
|
||||
// return;
|
||||
// }
|
||||
protected async prefetchSection(section: CoreCourseSectionWithStatus, manual?: boolean): Promise<void> {
|
||||
try {
|
||||
await CoreCourseHelper.instance.prefetchSection(section, this.course!.id, this.sections);
|
||||
} catch (error) {
|
||||
// Don't show error message if it's an automatic download.
|
||||
if (!manual) {
|
||||
return;
|
||||
}
|
||||
|
||||
// CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
|
||||
// });
|
||||
// }
|
||||
CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the data.
|
||||
|
@ -550,14 +556,16 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
component.callComponentFunction('ionViewDidEnter');
|
||||
});
|
||||
|
||||
// @todo if (this.downloadEnabled) {
|
||||
// // The download status of a section might have been changed from within a module page.
|
||||
// if (this.selectedSection && this.selectedSection.id !== CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
// CoreCourseHelper.instance.calculateSectionStatus(this.selectedSection, this.course.id, false, false);
|
||||
// } else {
|
||||
// CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
||||
// }
|
||||
// }
|
||||
if (!this.downloadEnabled || !this.course || !this.sections) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The download status of a section might have been changed from within a module page.
|
||||
if (this.selectedSection && this.selectedSection.id !== CoreCourseProvider.ALL_SECTIONS_ID) {
|
||||
CoreCourseHelper.instance.calculateSectionStatus(this.selectedSection, this.course.id, false, false);
|
||||
} else {
|
||||
CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -609,12 +617,13 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
/**
|
||||
* Recalculate the download status of each section, in response to a module being downloaded.
|
||||
*
|
||||
* @param eventData
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
onModuleStatusChange(eventData: CoreCourseModuleStatusChangedData): void {
|
||||
// @todo CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
||||
onModuleStatusChange(): void {
|
||||
if (!this.downloadEnabled || !this.sections || !this.course) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreCourseHelper.instance.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,13 +14,20 @@
|
|||
|
||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
||||
|
||||
// import { CoreSites } from '@services/sites';
|
||||
// import { CoreDomUtils } from '@services/utils/dom';
|
||||
// import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreCourseModuleDataFormatted, CoreCourseSectionFormatted } from '@features/course/services/course-helper';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreEventObserver, CoreEventPackageStatusChanged, CoreEvents } from '@singletons/events';
|
||||
import {
|
||||
CoreCourseHelper,
|
||||
CoreCourseModuleDataFormatted,
|
||||
CoreCourseSectionFormatted,
|
||||
} from '@features/course/services/course-helper';
|
||||
import { CoreCourse, CoreCourseModuleCompletionData } from '@features/course/services/course';
|
||||
import { CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
||||
// import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from '../../providers/module-prefetch-delegate';
|
||||
import {
|
||||
CoreCourseModulePrefetchDelegate,
|
||||
CoreCourseModulePrefetchHandler,
|
||||
} from '@features/course/services/module-prefetch-delegate';
|
||||
|
||||
/**
|
||||
* Component to display a module entry in a list of modules.
|
||||
|
@ -32,6 +39,7 @@ import { CoreCourseModuleHandlerButton } from '@features/course/services/module-
|
|||
@Component({
|
||||
selector: 'core-course-module',
|
||||
templateUrl: 'core-course-module.html',
|
||||
styleUrls: ['module.scss'],
|
||||
})
|
||||
export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||
|
||||
|
@ -51,7 +59,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
this.spinner = true; // Show spinner while calculating the status.
|
||||
|
||||
// Get current status to decide which icon should be shown.
|
||||
// @todo this.prefetchDelegate.getModuleStatus(this.module, this.courseId).then(this.showStatus.bind(this));
|
||||
this.calculateAndShowStatus();
|
||||
};
|
||||
|
||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
|
||||
|
@ -63,8 +71,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
||||
modNameTranslated = '';
|
||||
|
||||
// protected prefetchHandler: CoreCourseModulePrefetchHandler;
|
||||
// protected statusObserver?: CoreEventObserver;
|
||||
protected prefetchHandler?: CoreCourseModulePrefetchHandler;
|
||||
protected statusObserver?: CoreEventObserver;
|
||||
protected statusCalculated = false;
|
||||
protected isDestroyed = false;
|
||||
|
||||
|
@ -86,26 +94,27 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
||||
|
||||
if (this.module.handlerData.showDownloadButton) {
|
||||
// @todo Listen for changes on this module status, even if download isn't enabled.
|
||||
// this.prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(this.module);
|
||||
// this.canCheckUpdates = this.prefetchDelegate.canCheckUpdates();
|
||||
// Listen for changes on this module status, even if download isn't enabled.
|
||||
this.prefetchHandler = CoreCourseModulePrefetchDelegate.instance.getPrefetchHandlerFor(this.module);
|
||||
this.canCheckUpdates = CoreCourseModulePrefetchDelegate.instance.canCheckUpdates();
|
||||
|
||||
// this.statusObserver = this.eventsProvider.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => {
|
||||
// if (data.componentId === this.module.id && this.prefetchHandler &&
|
||||
// data.component === this.prefetchHandler.component) {
|
||||
this.statusObserver = CoreEvents.on<CoreEventPackageStatusChanged>(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => {
|
||||
if (!this.module || data.componentId != this.module.id || !this.prefetchHandler ||
|
||||
data.component != this.prefetchHandler.component) {
|
||||
return;
|
||||
}
|
||||
|
||||
// // Call determineModuleStatus to get the right status to display.
|
||||
// const status = this.prefetchDelegate.determineModuleStatus(this.module, data.status);
|
||||
// Call determineModuleStatus to get the right status to display.
|
||||
const status = CoreCourseModulePrefetchDelegate.instance.determineModuleStatus(this.module, data.status);
|
||||
|
||||
// if (this.downloadEnabled) {
|
||||
// // Download is enabled, show the status.
|
||||
// this.showStatus(status);
|
||||
// } else if (this.module.handlerData.updateStatus) {
|
||||
// // Download isn't enabled but the handler defines a updateStatus function, call it anyway.
|
||||
// this.module.handlerData.updateStatus(status);
|
||||
// }
|
||||
// }
|
||||
// }, this.sitesProvider.getCurrentSiteId());
|
||||
if (this.downloadEnabled) {
|
||||
// Download is enabled, show the status.
|
||||
this.showStatus(status);
|
||||
} else if (this.module.handlerData?.updateStatus) {
|
||||
// Download isn't enabled but the handler defines a updateStatus function, call it anyway.
|
||||
this.module.handlerData.updateStatus(status);
|
||||
}
|
||||
}, CoreSites.instance.getCurrentSiteId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,36 +147,39 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* @todo Download the module.
|
||||
* Download the module.
|
||||
*
|
||||
* @param refresh Whether it's refreshing.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
// download(refresh: boolean): void {
|
||||
// if (!this.prefetchHandler) {
|
||||
// return;
|
||||
// }
|
||||
async download(refresh: boolean): Promise<void> {
|
||||
if (!this.prefetchHandler || !this.module) {
|
||||
return;
|
||||
}
|
||||
|
||||
// // Show spinner since this operation might take a while.
|
||||
// this.spinner = true;
|
||||
// Show spinner since this operation might take a while.
|
||||
this.spinner = true;
|
||||
|
||||
// // Get download size to ask for confirm if it's high.
|
||||
// this.prefetchHandler.getDownloadSize(this.module, this.courseId, true).then((size) => {
|
||||
// return this.courseHelper.prefetchModule(this.prefetchHandler, this.module, size, this.courseId, refresh);
|
||||
// }).then(() => {
|
||||
// const eventData = {
|
||||
// sectionId: this.section.id,
|
||||
// moduleId: this.module.id,
|
||||
// courseId: this.courseId
|
||||
// };
|
||||
// this.statusChanged.emit(eventData);
|
||||
// }).catch((error) => {
|
||||
// // Error, hide spinner.
|
||||
// this.spinner = false;
|
||||
// if (!this.isDestroyed) {
|
||||
// this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
try {
|
||||
// Get download size to ask for confirm if it's high.
|
||||
const size = await this.prefetchHandler.getDownloadSize(this.module, this.courseId!, true);
|
||||
|
||||
await CoreCourseHelper.instance.prefetchModule(this.prefetchHandler, this.module, size, this.courseId!, refresh);
|
||||
|
||||
const eventData = {
|
||||
sectionId: this.section?.id,
|
||||
moduleId: this.module.id,
|
||||
courseId: this.courseId!,
|
||||
};
|
||||
this.statusChanged.emit(eventData);
|
||||
} catch (error) {
|
||||
// Error, hide spinner.
|
||||
this.spinner = false;
|
||||
if (!this.isDestroyed) {
|
||||
CoreDomUtils.instance.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show download buttons according to module status.
|
||||
|
@ -185,6 +197,21 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
this.module?.handlerData?.updateStatus?.(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and show module status.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async calculateAndShowStatus(): Promise<void> {
|
||||
if (!this.module || !this.courseId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const status = await CoreCourseModulePrefetchDelegate.instance.getModuleStatus(this.module, this.courseId);
|
||||
|
||||
this.showStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component destroyed.
|
||||
*/
|
||||
|
|
|
@ -12,16 +12,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
||||
import { CoreCourseComponentsModule } from './components/components.module';
|
||||
import { CoreCourseDirectivesModule } from './directives/directives.module';
|
||||
import { CoreCourseFormatModule } from './format/formats.module';
|
||||
import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA } from './services/database/course';
|
||||
import { SITE_SCHEMA as LOG_SITE_SCHEMA } from './services/database/log';
|
||||
import { SITE_SCHEMA as PREFETCH_SITE_SCHEMA } from './services/database/module-prefetch';
|
||||
import { CoreCourseIndexRoutingModule } from './pages/index/index-routing.module';
|
||||
import { CoreCourseModulePrefetchDelegate } from './services/module-prefetch-delegate';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
|
@ -43,14 +46,23 @@ const courseIndexRoutes: Routes = [
|
|||
CoreMainMenuTabRoutingModule.forChild(routes),
|
||||
CoreCourseFormatModule,
|
||||
CoreCourseComponentsModule,
|
||||
CoreCourseDirectivesModule,
|
||||
],
|
||||
exports: [CoreCourseIndexRoutingModule],
|
||||
providers: [
|
||||
{
|
||||
provide: CORE_SITE_SCHEMAS,
|
||||
useValue: [SITE_SCHEMA, OFFLINE_SITE_SCHEMA, LOG_SITE_SCHEMA],
|
||||
useValue: [SITE_SCHEMA, OFFLINE_SITE_SCHEMA, LOG_SITE_SCHEMA, PREFETCH_SITE_SCHEMA],
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
deps: [],
|
||||
useFactory: () => () => {
|
||||
CoreCourseModulePrefetchDelegate.instance.initialize();
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
export class CoreCourseModule {}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// (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 { NgModule } from '@angular/core';
|
||||
|
||||
import { CoreCourseDownloadModuleMainFileDirective } from './download-module-main-file';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCourseDownloadModuleMainFileDirective,
|
||||
],
|
||||
imports: [],
|
||||
exports: [
|
||||
CoreCourseDownloadModuleMainFileDirective,
|
||||
],
|
||||
})
|
||||
export class CoreCourseDirectivesModule {}
|
|
@ -0,0 +1,85 @@
|
|||
// (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 { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreCourse, CoreCourseModuleContentFile, CoreCourseWSModule } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
|
||||
/**
|
||||
* Directive to allow downloading and open the main file of a module.
|
||||
* When the item with this directive is clicked, the module will be downloaded (if needed) and opened.
|
||||
* This is meant for modules like mod_resource.
|
||||
*
|
||||
* This directive must receive either a module or a moduleId. If no files are provided, it will use module.contents.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[core-course-download-module-main-file]',
|
||||
})
|
||||
export class CoreCourseDownloadModuleMainFileDirective implements OnInit {
|
||||
|
||||
@Input() module?: CoreCourseWSModule; // The module.
|
||||
@Input() moduleId?: string | number; // The module ID. Required if module is not supplied.
|
||||
@Input() courseId?: string | number; // The course ID.
|
||||
@Input() component?: string; // Component to link the file to.
|
||||
@Input() componentId?: string | number; // Component ID to use in conjunction with the component. If not defined, use moduleId.
|
||||
@Input() files?: CoreCourseModuleContentFile[]; // List of files of the module. If not provided, use module.contents.
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef) {
|
||||
this.element = element.nativeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.element.addEventListener('click', async (ev: Event) => {
|
||||
if (!this.module && !this.moduleId) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
const courseId = typeof this.courseId == 'string' ? parseInt(this.courseId, 10) : this.courseId;
|
||||
|
||||
try {
|
||||
if (!this.module) {
|
||||
// Try to get the module from cache.
|
||||
this.moduleId = typeof this.moduleId == 'string' ? parseInt(this.moduleId, 10) : this.moduleId;
|
||||
this.module = await CoreCourse.instance.getModule(this.moduleId!, courseId);
|
||||
}
|
||||
|
||||
const componentId = this.componentId || module.id;
|
||||
|
||||
await CoreCourseHelper.instance.downloadModuleAndOpenFile(
|
||||
this.module,
|
||||
courseId ?? this.module.course!,
|
||||
this.component,
|
||||
componentId,
|
||||
this.files,
|
||||
);
|
||||
} catch (error) {
|
||||
CoreDomUtils.instance.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -28,20 +28,19 @@ import {
|
|||
} from '@features/course/services/course';
|
||||
import { CoreCourseHelper, CoreCourseSectionFormatted, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||
// import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import {
|
||||
CoreCourseOptionsDelegate,
|
||||
CoreCourseOptionsMenuHandlerToDisplay,
|
||||
} from '@features/course/services/course-options-delegate';
|
||||
// import { CoreCourseSyncProvider } from '../../providers/sync';
|
||||
// import { CoreCourseFormatComponent } from '../../components/format/format';
|
||||
import { CoreCourseFormatComponent } from '../../components/format/format';
|
||||
import {
|
||||
CoreEvents,
|
||||
CoreEventObserver,
|
||||
CoreEventCourseStatusChanged,
|
||||
CoreEventCompletionModuleViewedData,
|
||||
} from '@singletons/events';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreNavHelper } from '@services/nav-helper';
|
||||
|
||||
/**
|
||||
|
@ -54,7 +53,7 @@ import { CoreNavHelper } from '@services/nav-helper';
|
|||
export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild(IonContent) content?: IonContent;
|
||||
// @ViewChild(CoreCourseFormatComponent) formatComponent: CoreCourseFormatComponent;
|
||||
@ViewChild(CoreCourseFormatComponent) formatComponent?: CoreCourseFormatComponent;
|
||||
|
||||
course!: CoreCourseAnyCourseData;
|
||||
sections?: CoreCourseSectionFormatted[];
|
||||
|
@ -244,9 +243,9 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
|
||||
if (refresh) {
|
||||
// Invalidate the recently downloaded module list. To ensure info can be prefetched.
|
||||
// const modules = CoreCourse.instance.getSectionsModules(sections);
|
||||
const modules = CoreCourse.instance.getSectionsModules(sections);
|
||||
|
||||
// @todo await this.prefetchDelegate.invalidateModules(modules, this.course.id);
|
||||
await CoreCourseModulePrefetchDelegate.instance.invalidateModules(modules, this.course.id);
|
||||
}
|
||||
|
||||
let completionStatus: Record<string, CoreCourseCompletionActivityStatus> = {};
|
||||
|
@ -279,14 +278,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
|
||||
if (CoreCourseFormatDelegate.instance.canViewAllSections(this.course)) {
|
||||
// Add a fake first section (all sections).
|
||||
this.sections.unshift({
|
||||
id: CoreCourseProvider.ALL_SECTIONS_ID,
|
||||
name: Translate.instance.instant('core.course.allsections'),
|
||||
hasContent: true,
|
||||
summary: '',
|
||||
summaryformat: 1,
|
||||
modules: [],
|
||||
});
|
||||
this.sections.unshift(CoreCourseHelper.instance.createAllSectionsSection());
|
||||
}
|
||||
|
||||
// Get whether to show the refresher now that we have sections.
|
||||
|
@ -345,8 +337,8 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
// Do not call doRefresh on the format component if the refresher is defined in the format component
|
||||
// to prevent an inifinite loop.
|
||||
if (this.displayRefresher) {
|
||||
// @todo await CoreUtils.instance.ignoreErrors(this.formatComponent.doRefresh(refresher));
|
||||
if (this.displayRefresher && this.formatComponent) {
|
||||
await CoreUtils.instance.ignoreErrors(this.formatComponent.doRefresh(refresher));
|
||||
}
|
||||
|
||||
refresher?.detail.complete();
|
||||
|
@ -384,7 +376,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
promises.push(CoreCourseFormatDelegate.instance.invalidateData(this.course, this.sections || []));
|
||||
|
||||
if (this.sections) {
|
||||
// @todo promises.push(this.prefetchDelegate.invalidateCourseUpdates(this.course.id));
|
||||
promises.push(CoreCourseModulePrefetchDelegate.instance.invalidateCourseUpdates(this.course.id));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
@ -408,7 +400,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this.loadData(true, sync);
|
||||
|
||||
// @todo await this.formatComponent.doRefresh(undefined, undefined, true);
|
||||
await this.formatComponent?.doRefresh(undefined, undefined, true);
|
||||
} finally {
|
||||
this.dataLoaded = true;
|
||||
|
||||
|
@ -431,15 +423,15 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Prefetch the whole course.
|
||||
*/
|
||||
prefetchCourse(): void {
|
||||
async prefetchCourse(): Promise<void> {
|
||||
try {
|
||||
// @todo await CoreCourseHelper.instance.confirmAndPrefetchCourse(
|
||||
// this.prefetchCourseData,
|
||||
// this.course,
|
||||
// this.sections,
|
||||
// this.courseHandlers,
|
||||
// this.courseMenuHandlers,
|
||||
// );
|
||||
await CoreCourseHelper.instance.confirmAndPrefetchCourse(
|
||||
this.prefetchCourseData,
|
||||
this.course,
|
||||
this.sections,
|
||||
undefined,
|
||||
this.courseMenuHandlers,
|
||||
);
|
||||
} catch (error) {
|
||||
if (this.isDestroyed) {
|
||||
return;
|
||||
|
@ -497,14 +489,14 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
|||
* User entered the page.
|
||||
*/
|
||||
ionViewDidEnter(): void {
|
||||
// @todo this.formatComponent?.ionViewDidEnter();
|
||||
this.formatComponent?.ionViewDidEnter();
|
||||
}
|
||||
|
||||
/**
|
||||
* User left the page.
|
||||
*/
|
||||
ionViewDidLeave(): void {
|
||||
// @todo this.formatComponent?.ionViewDidLeave();
|
||||
this.formatComponent?.ionViewDidLeave();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,6 @@
|
|||
// 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.
|
||||
// @todo test delegate
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreDelegate, CoreDelegateHandler, CoreDelegateToDisplay } from '@classes/delegate';
|
||||
|
@ -178,7 +177,7 @@ export interface CoreCourseOptionsHandlerToDisplay extends CoreDelegateToDisplay
|
|||
* @param course The course.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
prefetch?(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void>;
|
||||
prefetch?(course: CoreCourseAnyCourseData): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -206,7 +205,7 @@ export interface CoreCourseOptionsMenuHandlerToDisplay {
|
|||
* @param course The course.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
prefetch?(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void>;
|
||||
prefetch?(course: CoreCourseAnyCourseData): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -109,7 +109,6 @@ export class CoreCourseProvider {
|
|||
*
|
||||
* @param courseId Course ID.
|
||||
* @param completion Completion status of the module.
|
||||
* @todo Add completion type.
|
||||
*/
|
||||
checkModuleCompletion(courseId: number, completion: CoreCourseModuleCompletionDataFormatted): void {
|
||||
if (completion && completion.tracking === 2 && completion.state === 0) {
|
||||
|
@ -830,7 +829,7 @@ export class CoreCourseProvider {
|
|||
* @return Promise resolved when loaded.
|
||||
*/
|
||||
async loadModuleContents(
|
||||
module: CoreCourseModuleData & CoreCourseModuleBasicInfo,
|
||||
module: CoreCourseModuleData,
|
||||
courseId?: number,
|
||||
sectionId?: number,
|
||||
preferCache?: boolean,
|
||||
|
@ -1412,14 +1411,13 @@ export type CoreCourseModuleContentFile = {
|
|||
filename: string; // Filename.
|
||||
filepath: string; // Filepath.
|
||||
filesize: number; // Filesize.
|
||||
fileurl?: string; // Downloadable file url.
|
||||
url?: string; // @deprecated. Use fileurl instead.
|
||||
fileurl: string; // Downloadable file url.
|
||||
content?: string; // Raw content, will be used when type is content.
|
||||
timecreated: number; // Time created.
|
||||
timemodified: number; // Time modified.
|
||||
sortorder: number; // Content sort order.
|
||||
mimetype?: string; // File mime type.
|
||||
isexternalfile?: boolean; // Whether is an external file.
|
||||
isexternalfile?: number; // Whether is an external file.
|
||||
repositorytype?: string; // The repository type for external files.
|
||||
userid: number; // User who added this content to moodle.
|
||||
author: string; // Content owner.
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// (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 { CoreSiteSchema } from '@services/sites';
|
||||
|
||||
/**
|
||||
* Database variables for CoreCourseModulePrefetchDelegate service.
|
||||
*/
|
||||
export const CHECK_UPDATES_TIMES_TABLE = 'check_updates_times';
|
||||
export const SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'CoreCourseModulePrefetchDelegate',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: CHECK_UPDATES_TIMES_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'courseId',
|
||||
type: 'INTEGER',
|
||||
primaryKey: true,
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
type: 'INTEGER',
|
||||
notNull: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export type CoreCourseCheckUpdatesDBRecord = {
|
||||
courseId: number;
|
||||
time: number;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
|||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreBlockCourseBlocksComponent } from '@features/block/components/course-blocks/course-blocks';
|
||||
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
|
||||
/**
|
||||
* Page that displays site home index.
|
||||
|
@ -59,7 +60,6 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
|||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
protected navCtrl: NavController,
|
||||
// @todo private prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@ -86,8 +86,8 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
|||
|
||||
const module = navParams['module'];
|
||||
if (module) {
|
||||
// @todo const modParams = navParams.get('modParams');
|
||||
// CoreCourseHelper.instance.openModule(module, this.siteHomeId, undefined, modParams);
|
||||
const modParams = navParams['modParams'];
|
||||
CoreCourseHelper.instance.openModule(module, this.siteHomeId, undefined, modParams);
|
||||
}
|
||||
|
||||
this.loadContent().finally(() => {
|
||||
|
@ -174,7 +174,7 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
|||
|
||||
if (this.section && this.section.modules) {
|
||||
// Invalidate modules prefetch data.
|
||||
// @todo promises.push(this.prefetchDelegate.invalidateModules(this.section.modules, this.siteHomeId));
|
||||
promises.push(CoreCourseModulePrefetchDelegate.instance.invalidateModules(this.section.modules, this.siteHomeId));
|
||||
}
|
||||
|
||||
if (this.courseBlocksComponent) {
|
||||
|
|
|
@ -160,40 +160,39 @@ export class CoreFileHelperProvider {
|
|||
onProgress({ calculating: true });
|
||||
}
|
||||
|
||||
try {
|
||||
await CoreFilepool.instance.shouldDownloadBeforeOpen(fixedUrl, file.filesize || 0);
|
||||
} catch (error) {
|
||||
// Start the download if in wifi, but return the URL right away so the file is opened.
|
||||
if (isWifi) {
|
||||
this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
||||
}
|
||||
|
||||
if (!this.isStateDownloaded(state) || isOnline) {
|
||||
// Not downloaded or online, return the online URL.
|
||||
const shouldDownloadFirst = await CoreFilepool.instance.shouldDownloadFileBeforeOpen(fixedUrl, file.filesize || 0);
|
||||
if (shouldDownloadFirst) {
|
||||
// Download the file first.
|
||||
if (state == CoreConstants.DOWNLOADING) {
|
||||
// It's already downloading, stop.
|
||||
return fixedUrl;
|
||||
} else {
|
||||
// Outdated but offline, so we return the local URL.
|
||||
return CoreFilepool.instance.getUrlByUrl(
|
||||
siteId,
|
||||
fileUrl,
|
||||
component,
|
||||
componentId,
|
||||
timemodified,
|
||||
false,
|
||||
false,
|
||||
file,
|
||||
);
|
||||
}
|
||||
|
||||
// Download and then return the local URL.
|
||||
return this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
||||
}
|
||||
|
||||
// Download the file first.
|
||||
if (state == CoreConstants.DOWNLOADING) {
|
||||
// It's already downloading, stop.
|
||||
// Start the download if in wifi, but return the URL right away so the file is opened.
|
||||
if (isWifi) {
|
||||
this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
||||
}
|
||||
|
||||
if (!this.isStateDownloaded(state) || isOnline) {
|
||||
// Not downloaded or online, return the online URL.
|
||||
return fixedUrl;
|
||||
} else {
|
||||
// Outdated but offline, so we return the local URL.
|
||||
return CoreFilepool.instance.getUrlByUrl(
|
||||
siteId,
|
||||
fileUrl,
|
||||
component,
|
||||
componentId,
|
||||
timemodified,
|
||||
false,
|
||||
false,
|
||||
file,
|
||||
);
|
||||
}
|
||||
|
||||
// Download and then return the local URL.
|
||||
return this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2763,13 +2763,7 @@ export class CoreFilepoolProvider {
|
|||
* @param url File online URL.
|
||||
* @param size File size.
|
||||
* @return Promise resolved if should download before open, rejected otherwise.
|
||||
* @description
|
||||
* Convenience function to check if a file should be downloaded before opening it.
|
||||
*
|
||||
* The default behaviour in the app is to download first and then open the local file in the following cases:
|
||||
* - The file is small (less than DOWNLOAD_THRESHOLD).
|
||||
* - The file cannot be streamed.
|
||||
* If the file is big and can be streamed, the promise returned by this function will be rejected.
|
||||
* @ddeprecated since 3.9.5. Please use shouldDownloadFileBeforeOpen instead.
|
||||
*/
|
||||
async shouldDownloadBeforeOpen(url: string, size: number): Promise<void> {
|
||||
if (size >= 0 && size <= CoreFilepoolProvider.DOWNLOAD_THRESHOLD) {
|
||||
|
@ -2784,6 +2778,32 @@ export class CoreFilepoolProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to check if a file should be downloaded before opening it.
|
||||
*
|
||||
* @param url File online URL.
|
||||
* @param size File size.
|
||||
* @return Promise resolved with boolean: whether file should be downloaded before opening it.
|
||||
* @description
|
||||
* Convenience function to check if a file should be downloaded before opening it.
|
||||
*
|
||||
* The default behaviour in the app is to download first and then open the local file in the following cases:
|
||||
* - The file is small (less than DOWNLOAD_THRESHOLD).
|
||||
* - The file cannot be streamed.
|
||||
* If the file is big and can be streamed, the promise returned by this function will be rejected.
|
||||
*/
|
||||
async shouldDownloadFileBeforeOpen(url: string, size: number): Promise<boolean> {
|
||||
if (size >= 0 && size <= CoreFilepoolProvider.DOWNLOAD_THRESHOLD) {
|
||||
// The file is small, download it.
|
||||
return true;
|
||||
}
|
||||
|
||||
const mimetype = await CoreUtils.instance.getMimeTypeFromUrl(url);
|
||||
|
||||
// If the file is streaming (audio or video), return false.
|
||||
return mimetype.indexOf('video') == -1 && mimetype.indexOf('audio') == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store package status.
|
||||
*
|
||||
|
|
|
@ -114,7 +114,7 @@ export class CoreUtilsProvider {
|
|||
* @param result Object where to put the properties. If not defined, a new object will be created.
|
||||
* @return The object.
|
||||
*/
|
||||
arrayToObject<T extends Record<string, unknown> | string>(
|
||||
arrayToObject<T>(
|
||||
array: T[],
|
||||
propertyName?: string,
|
||||
result: Record<string, T> = {},
|
||||
|
|
Loading…
Reference in New Issue