forked from EVOgeek/Vmeda.Online
		
	Merge pull request #3395 from dpalou/MOBILE-4081
MOBILE-4081 core: Remove most .bind() usage
This commit is contained in:
		
						commit
						22f97aa04e
					
				
							
								
								
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -13492,7 +13492,7 @@ | ||||
|     "concat-map": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", | ||||
|       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" | ||||
|       "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" | ||||
|     }, | ||||
|     "concat-stream": { | ||||
|       "version": "1.6.2", | ||||
| @ -14379,9 +14379,9 @@ | ||||
|       "integrity": "sha512-FU0Lw1jZpuKOgG4v80LrfMAOIMCGfAVPumn7AwaX9S1iU/X3OPZUyoKUgP09q4bxL35IeNPkqNWVKYduAXZ1sg==" | ||||
|     }, | ||||
|     "cordova-plugin-file": { | ||||
|       "version": "7.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-7.0.0.tgz", | ||||
|       "integrity": "sha512-mSwy9GE5pHq2ZHhu/wYk/VhrwR5VLk+XQsk3+IiiFmDgcPsrVIyELkM2FZKX09cC6i+bJVTFVKUlwteSStj3ow==" | ||||
|       "version": "6.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-6.0.2.tgz", | ||||
|       "integrity": "sha512-m7cughw327CjONN/qjzsTpSesLaeybksQh420/gRuSXJX5Zt9NfgsSbqqKDon6jnQ9Mm7h7imgyO2uJ34XMBtA==" | ||||
|     }, | ||||
|     "cordova-plugin-file-opener2": { | ||||
|       "version": "3.0.5", | ||||
| @ -27427,7 +27427,7 @@ | ||||
|     "properties-parser": { | ||||
|       "version": "0.3.1", | ||||
|       "resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz", | ||||
|       "integrity": "sha512-AkSQxQAviJ89x4FIxOyHGfO3uund0gvYo7lfD0E+Gp7gFQKrTNgtoYQklu8EhrfHVZUzTwKGZx2r/KDSfnljcA==", | ||||
|       "integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=", | ||||
|       "requires": { | ||||
|         "string.prototype.codepointat": "^0.2.0" | ||||
|       } | ||||
|  | ||||
| @ -99,7 +99,7 @@ | ||||
|     "cordova-plugin-chooser": "^1.3.2", | ||||
|     "cordova-plugin-customurlscheme": "^5.0.2", | ||||
|     "cordova-plugin-device": "^2.1.0", | ||||
|     "cordova-plugin-file": "^7.0.0", | ||||
|     "cordova-plugin-file": "6.0.2", | ||||
|     "cordova-plugin-file-opener2": "^3.0.5", | ||||
|     "cordova-plugin-geolocation": "^4.1.0", | ||||
|     "cordova-plugin-ionic-keyboard": "^2.2.0", | ||||
|  | ||||
| @ -280,7 +280,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem | ||||
|                 loadCategoryNames: showCategories, | ||||
|                 readingStrategy: this.isDirty ? CoreSitesReadingStrategy.PREFER_NETWORK : loadWatcher.getReadingStrategy(), | ||||
|             }), | ||||
|             this.coursesHaveMeaningfulChanges.bind(this), | ||||
|             (prevCourses, newCourses) => this.coursesHaveMeaningfulChanges(prevCourses, newCourses), | ||||
|         ); | ||||
| 
 | ||||
|         this.hasCourses = this.allCourses.length > 0; | ||||
| @ -532,7 +532,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem | ||||
|                             CoreCourses.getEnrolledCoursesByCustomFieldObservable(customFilterName, customFilterValue, { | ||||
|                                 readingStrategy: loadWatcher.getReadingStrategy(), | ||||
|                             }), | ||||
|                             this.customFilterCoursesHaveMeaningfulChanges.bind(this), | ||||
|                             (prevCourses, newCourses) => this.customFilterCoursesHaveMeaningfulChanges(prevCourses, newCourses), | ||||
|                         ) | ||||
|                         : | ||||
|                         await CoreCourses.getEnrolledCoursesByCustomField(customFilterName, customFilterValue); | ||||
|  | ||||
| @ -20,8 +20,7 @@ import { | ||||
|     CoreCourseOptionsHandler, | ||||
|     CoreCourseOptionsHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreFilepool } from '@services/filepool'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { CoreWSFile } from '@services/ws'; | ||||
| @ -83,7 +82,7 @@ export class AddonBlogCourseOptionHandlerService implements CoreCourseOptionsHan | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         const siteId = CoreSites.getCurrentSiteId(); | ||||
| 
 | ||||
|         const result = await AddonBlog.getEntries({ courseid: course.id }); | ||||
|  | ||||
| @ -111,14 +111,14 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { | ||||
|         // Refresh data if this calendar event is synchronized automatically.
 | ||||
|         this.syncObserver = CoreEvents.on( | ||||
|             AddonCalendarSyncProvider.AUTO_SYNCED, | ||||
|             this.checkSyncResult.bind(this, false), | ||||
|             (data) => this.checkSyncResult(false, data), | ||||
|             this.currentSiteId, | ||||
|         ); | ||||
| 
 | ||||
|         // Refresh data if calendar events are synchronized manually but not by this page.
 | ||||
|         this.manualSyncObserver = CoreEvents.on( | ||||
|             AddonCalendarSyncProvider.MANUAL_SYNCED, | ||||
|             this.checkSyncResult.bind(this, true), | ||||
|             (data) => this.checkSyncResult(true, data), | ||||
|             this.currentSiteId, | ||||
|         ); | ||||
| 
 | ||||
|  | ||||
| @ -55,7 +55,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     async syncAllEvents(siteId?: string, force = false): Promise<void> { | ||||
|         await this.syncOnSites('all calendar events', this.syncAllEventsFunc.bind(this, force), siteId); | ||||
|         await this.syncOnSites('all calendar events', (siteId) => this.syncAllEventsFunc(force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -21,8 +21,7 @@ import { | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { AddonCompetency } from '../competency'; | ||||
| import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreFilterHelper } from '@features/filter/services/filter-helper'; | ||||
| import { ContextLevel } from '@/core/constants'; | ||||
| import { ADDON_COMPETENCY_COMPETENCIES_PAGE } from '@addons/competency/competency.module'; | ||||
| @ -94,7 +93,7 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         // Get the competencies in the course.
 | ||||
|         const competencies = await AddonCompetency.getCourseCompetencies(course.id, undefined, undefined, true); | ||||
| 
 | ||||
|  | ||||
| @ -19,7 +19,7 @@ import { | ||||
|     CoreCourseOptionsHandler, | ||||
|     CoreCourseOptionsHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { AddonCourseCompletion } from '../coursecompletion'; | ||||
| 
 | ||||
| @ -77,7 +77,7 @@ export class AddonCourseCompletionCourseOptionHandlerService implements CoreCour | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         try { | ||||
|             await AddonCourseCompletion.getCompletion(course.id, undefined, { | ||||
|                 getFromCache: false, | ||||
|  | ||||
| @ -74,7 +74,7 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider<AddonMessage | ||||
|     syncAllDiscussions(siteId?: string, onlyDeviceOffline: boolean = false): Promise<void> { | ||||
|         const syncFunctionLog = 'all discussions' + (onlyDeviceOffline ? ' (Only offline)' : ''); | ||||
| 
 | ||||
|         return this.syncOnSites(syncFunctionLog, this.syncAllDiscussionsFunc.bind(this, onlyDeviceOffline), siteId); | ||||
|         return this.syncOnSites(syncFunctionLog, (siteId) => this.syncAllDiscussionsFunc(onlyDeviceOffline, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -108,7 +108,7 @@ export class AddonModAssignSyncProvider extends CoreCourseActivitySyncBaseProvid | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllAssignments(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all assignments', this.syncAllAssignmentsFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all assignments', (siteId) => this.syncAllAssignmentsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -222,7 +222,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchAssign.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchAssign(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -58,7 +58,7 @@ export class AddonModChatPrefetchHandlerService extends CoreCourseActivityPrefet | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchChat.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchChat(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -59,7 +59,7 @@ export class AddonModChoiceSyncProvider extends CoreCourseActivitySyncBaseProvid | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllChoices(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all choices', this.syncAllChoicesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all choices', (siteId) => this.syncAllChoicesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -39,7 +39,7 @@ export class AddonModChoicePrefetchHandlerService extends CoreCourseActivityPref | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number, single?: boolean): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchChoice.bind(this, module, courseId, !!single)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchChoice(module, courseId, !!single, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -95,7 +95,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|         database: AddonModDataData; | ||||
|         title: string; | ||||
|         group: number; | ||||
|         gotoEntry: (a: number) => void; | ||||
|         gotoEntry: (entryId: number) => void; | ||||
|     }; | ||||
| 
 | ||||
|     // Data for found records translation.
 | ||||
| @ -372,7 +372,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|                 database: this.database!, | ||||
|                 title: this.module.name, | ||||
|                 group: this.selectedGroup, | ||||
|                 gotoEntry: this.gotoEntry.bind(this), | ||||
|                 gotoEntry: (entryId) => this.gotoEntry(entryId), | ||||
|             }; | ||||
|         } else if (!this.search.searching) { | ||||
|             // Empty and no searching.
 | ||||
|  | ||||
| @ -405,7 +405,7 @@ export class AddonModDataEditPage implements OnInit { | ||||
|             form: this.editForm, | ||||
|             database: this.database, | ||||
|             errors: this.errors, | ||||
|             onFieldInit: this.onFieldInit.bind(this), | ||||
|             onFieldInit: (data) => this.onFieldInit(data), | ||||
|         }; | ||||
| 
 | ||||
|         let template = AddonModDataHelper.getTemplate(this.database!, AddonModDataTemplateType.ADD, this.fieldsArray); | ||||
|  | ||||
| @ -116,7 +116,7 @@ export class AddonModDataOfflineProvider { | ||||
|         const site = await CoreSites.getSite(siteId); | ||||
|         const entries = await site.getDb().getAllRecords<AddonModDataEntryDBRecord>(DATA_ENTRY_TABLE); | ||||
| 
 | ||||
|         return entries.map(this.parseRecord.bind(this)); | ||||
|         return entries.map((entry) => this.parseRecord(entry)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -134,7 +134,7 @@ export class AddonModDataOfflineProvider { | ||||
|             'timemodified', | ||||
|         ); | ||||
| 
 | ||||
|         return entries.map(this.parseRecord.bind(this)); | ||||
|         return entries.map((entry) => this.parseRecord(entry)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -177,7 +177,7 @@ export class AddonModDataOfflineProvider { | ||||
|             { dataid: dataId, entryid: entryId }, | ||||
|         ); | ||||
| 
 | ||||
|         return entries.map(this.parseRecord.bind(this)); | ||||
|         return entries.map((entry) => this.parseRecord(entry)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -66,7 +66,7 @@ export class AddonModDataSyncProvider extends CoreCourseActivitySyncBaseProvider | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllDatabases(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all databases', this.syncAllDatabasesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all databases', (siteId) => this.syncAllDatabasesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -207,7 +207,7 @@ export class AddonModDataPrefetchHandlerService extends CoreCourseActivityPrefet | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchDatabase.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchDatabase(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -65,7 +65,7 @@ export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProv | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllFeedbacks(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all feedbacks', this.syncAllFeedbacksFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all feedbacks', (siteId) => this.syncAllFeedbacksFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -213,7 +213,7 @@ export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProv | ||||
|         responses.sort((a, b) => a.page - b.page); | ||||
| 
 | ||||
|         const orderedData = responses.map((data) => ({ | ||||
|             function: this.processPage.bind(this, feedback, data, siteId, timemodified, result), | ||||
|             function: () => this.processPage(feedback, data, siteId, timemodified, result), | ||||
|             blocking: true, | ||||
|         })); | ||||
| 
 | ||||
|  | ||||
| @ -114,7 +114,7 @@ export class AddonModFeedbackPrefetchHandlerService extends CoreCourseActivityPr | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchFeedback.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchFeedback(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -238,11 +238,11 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|         // Listen for discussions added. When a discussion is added, we reload the data.
 | ||||
|         this.newDiscObserver = CoreEvents.on( | ||||
|             AddonModForumProvider.NEW_DISCUSSION_EVENT, | ||||
|             this.eventReceived.bind(this, true), | ||||
|             (data) => this.eventReceived(true, data), | ||||
|         ); | ||||
|         this.replyObserver = CoreEvents.on( | ||||
|             AddonModForumProvider.REPLY_DISCUSSION_EVENT, | ||||
|             this.eventReceived.bind(this, false), | ||||
|             (data) => this.eventReceived(false, data), | ||||
|         ); | ||||
|         this.changeDiscObserver = CoreEvents.on(AddonModForumProvider.CHANGE_DISCUSSION_EVENT, data => { | ||||
|             if (!this.forum) { | ||||
|  | ||||
| @ -71,7 +71,7 @@ export class AddonModForumSyncProvider extends CoreCourseActivitySyncBaseProvide | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     async syncAllForums(siteId?: string, force?: boolean): Promise<void> { | ||||
|         await this.syncOnSites('all forums', this.syncAllForumsFunc.bind(this, !!force), siteId); | ||||
|         await this.syncOnSites('all forums', (siteId) => this.syncAllForumsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -204,7 +204,7 @@ export class AddonModForumPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number, single?: boolean): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchForum.bind(this, module, courseId, single)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchForum(module, courseId, !!single, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -43,7 +43,7 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|     onlineEntries: AddonModGlossaryEntry[] = []; | ||||
|     offlineEntries: AddonModGlossaryOfflineEntry[] = []; | ||||
| 
 | ||||
|     protected fetchFunction?: (options?: AddonModGlossaryGetEntriesOptions) => AddonModGlossaryGetEntriesWSResponse; | ||||
|     protected fetchFunction?: (options?: AddonModGlossaryGetEntriesOptions) => Promise<AddonModGlossaryGetEntriesWSResponse>; | ||||
|     protected fetchInvalidate?: () => Promise<void>; | ||||
| 
 | ||||
|     constructor(courseId: number, cmId: number, glossaryPathPrefix: string) { | ||||
| @ -162,17 +162,18 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.fetchFunction = AddonModGlossary.getEntriesBySearch.bind( | ||||
|             AddonModGlossary.instance, | ||||
|             this.glossary.id, | ||||
|         const glossaryId = this.glossary.id; | ||||
| 
 | ||||
|         this.fetchFunction = (options) => AddonModGlossary.getEntriesBySearch( | ||||
|             glossaryId, | ||||
|             query, | ||||
|             true, | ||||
|             'CONCEPT', | ||||
|             'ASC', | ||||
|             options, | ||||
|         ); | ||||
|         this.fetchInvalidate = AddonModGlossary.invalidateEntriesBySearch.bind( | ||||
|             AddonModGlossary.instance, | ||||
|             this.glossary.id, | ||||
|         this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesBySearch( | ||||
|             glossaryId, | ||||
|             query, | ||||
|             true, | ||||
|             'CONCEPT', | ||||
| @ -210,6 +211,7 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             throw new Error('Can\'t switch entries mode without a glossary!'); | ||||
|         } | ||||
| 
 | ||||
|         const glossaryId = this.glossary.id; | ||||
|         this.fetchMode = mode; | ||||
|         this.isSearch = false; | ||||
|         this.setDirty(true); | ||||
| @ -218,16 +220,15 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             case 'author_all': | ||||
|                 // Browse by author.
 | ||||
|                 this.viewMode = 'author'; | ||||
|                 this.fetchFunction = AddonModGlossary.getEntriesByAuthor.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchFunction = (options) => AddonModGlossary.getEntriesByAuthor( | ||||
|                     glossaryId, | ||||
|                     'ALL', | ||||
|                     'LASTNAME', | ||||
|                     'ASC', | ||||
|                     options, | ||||
|                 ); | ||||
|                 this.fetchInvalidate = AddonModGlossary.invalidateEntriesByAuthor.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesByAuthor( | ||||
|                     glossaryId, | ||||
|                     'ALL', | ||||
|                     'LASTNAME', | ||||
|                     'ASC', | ||||
| @ -237,14 +238,13 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             case 'cat_all': | ||||
|                 // Browse by category.
 | ||||
|                 this.viewMode = 'cat'; | ||||
|                 this.fetchFunction = AddonModGlossary.getEntriesByCategory.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchFunction = (options) => AddonModGlossary.getEntriesByCategory( | ||||
|                     glossaryId, | ||||
|                     AddonModGlossaryProvider.SHOW_ALL_CATEGORIES, | ||||
|                     options, | ||||
|                 ); | ||||
|                 this.fetchInvalidate = AddonModGlossary.invalidateEntriesByCategory.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesByCategory( | ||||
|                     glossaryId, | ||||
|                     AddonModGlossaryProvider.SHOW_ALL_CATEGORIES, | ||||
|                 ); | ||||
|                 break; | ||||
| @ -252,15 +252,14 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             case 'newest_first': | ||||
|                 // Newest first.
 | ||||
|                 this.viewMode = 'date'; | ||||
|                 this.fetchFunction = AddonModGlossary.getEntriesByDate.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchFunction = (options) => AddonModGlossary.getEntriesByDate( | ||||
|                     glossaryId, | ||||
|                     'CREATION', | ||||
|                     'DESC', | ||||
|                     options, | ||||
|                 ); | ||||
|                 this.fetchInvalidate = AddonModGlossary.invalidateEntriesByDate.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesByDate( | ||||
|                     glossaryId, | ||||
|                     'CREATION', | ||||
|                     'DESC', | ||||
|                 ); | ||||
| @ -269,15 +268,14 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|             case 'recently_updated': | ||||
|                 // Recently updated.
 | ||||
|                 this.viewMode = 'date'; | ||||
|                 this.fetchFunction = AddonModGlossary.getEntriesByDate.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchFunction = (options) => AddonModGlossary.getEntriesByDate( | ||||
|                     glossaryId, | ||||
|                     'UPDATE', | ||||
|                     'DESC', | ||||
|                     options, | ||||
|                 ); | ||||
|                 this.fetchInvalidate = AddonModGlossary.invalidateEntriesByDate.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesByDate( | ||||
|                     glossaryId, | ||||
|                     'UPDATE', | ||||
|                     'DESC', | ||||
|                 ); | ||||
| @ -288,14 +286,13 @@ export class AddonModGlossaryEntriesSource extends CoreRoutedItemsManagerSource< | ||||
|                 // Consider it is 'letter_all'.
 | ||||
|                 this.viewMode = 'letter'; | ||||
|                 this.fetchMode = 'letter_all'; | ||||
|                 this.fetchFunction = AddonModGlossary.getEntriesByLetter.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchFunction = (options) => AddonModGlossary.getEntriesByLetter( | ||||
|                     glossaryId, | ||||
|                     'ALL', | ||||
|                     options, | ||||
|                 ); | ||||
|                 this.fetchInvalidate = AddonModGlossary.invalidateEntriesByLetter.bind( | ||||
|                     AddonModGlossary.instance, | ||||
|                     this.glossary.id, | ||||
|                 this.fetchInvalidate = () => AddonModGlossary.invalidateEntriesByLetter( | ||||
|                     glossaryId, | ||||
|                     'ALL', | ||||
|                 ); | ||||
|                 break; | ||||
|  | ||||
| @ -53,7 +53,7 @@ export class AddonModGlossarySyncProvider extends CoreCourseActivitySyncBaseProv | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllGlossaries(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all glossaries', this.syncAllGlossariesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all glossaries', (siteId) => this.syncAllGlossariesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -759,7 +759,7 @@ export class AddonModGlossaryProvider { | ||||
|         const promises: Promise<void>[] = []; | ||||
| 
 | ||||
|         if (!onlyEntriesList) { | ||||
|             promises.push(this.fetchAllEntries(this.getEntriesByLetter.bind(this, glossary.id, 'ALL'), { | ||||
|             promises.push(this.fetchAllEntries((options) => this.getEntriesByLetter(glossary.id, 'ALL', options), { | ||||
|                 cmId: glossary.coursemodule, | ||||
|                 readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE, | ||||
|                 siteId, | ||||
| @ -993,7 +993,7 @@ export class AddonModGlossaryProvider { | ||||
| 
 | ||||
|             // If we get here, there's no offline entry with this name, check online.
 | ||||
|             // Get entries from the cache.
 | ||||
|             const entries = await this.fetchAllEntries(this.getEntriesByLetter.bind(glossaryId, 'ALL'), { | ||||
|             const entries = await this.fetchAllEntries((options) => this.getEntriesByLetter(glossaryId, 'ALL', options), { | ||||
|                 cmId: options.cmId, | ||||
|                 readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE, | ||||
|                 siteId: options.siteId, | ||||
|  | ||||
| @ -45,7 +45,7 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr | ||||
|             const glossary = await AddonModGlossary.getGlossary(courseId, module.id); | ||||
| 
 | ||||
|             const entries = await AddonModGlossary.fetchAllEntries( | ||||
|                 AddonModGlossary.getEntriesByLetter.bind(AddonModGlossary.instance, glossary.id, 'ALL'), | ||||
|                 (options) => AddonModGlossary.getEntriesByLetter(glossary.id, 'ALL', options), | ||||
|                 { | ||||
|                     cmId: module.id, | ||||
|                 }, | ||||
| @ -96,7 +96,7 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchGlossary.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchGlossary(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -125,42 +125,42 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr | ||||
|                     break; | ||||
|                 case 'cat': | ||||
|                     promises.push(AddonModGlossary.fetchAllEntries( | ||||
|                         AddonModGlossary.getEntriesByCategory.bind( | ||||
|                             AddonModGlossary.instance, | ||||
|                         (newOptions) => AddonModGlossary.getEntriesByCategory( | ||||
|                             glossary.id, | ||||
|                             AddonModGlossaryProvider.SHOW_ALL_CATEGORIES, | ||||
|                             newOptions, | ||||
|                         ), | ||||
|                         options, | ||||
|                     )); | ||||
|                     break; | ||||
|                 case 'date': | ||||
|                     promises.push(AddonModGlossary.fetchAllEntries( | ||||
|                         AddonModGlossary.getEntriesByDate.bind( | ||||
|                             AddonModGlossary.instance, | ||||
|                         (newOptions) => AddonModGlossary.getEntriesByDate( | ||||
|                             glossary.id, | ||||
|                             'CREATION', | ||||
|                             'DESC', | ||||
|                             newOptions, | ||||
|                         ), | ||||
|                         options, | ||||
|                     )); | ||||
|                     promises.push(AddonModGlossary.fetchAllEntries( | ||||
|                         AddonModGlossary.getEntriesByDate.bind( | ||||
|                             AddonModGlossary.instance, | ||||
|                         (newOptions) => AddonModGlossary.getEntriesByDate( | ||||
|                             glossary.id, | ||||
|                             'UPDATE', | ||||
|                             'DESC', | ||||
|                             newOptions, | ||||
|                         ), | ||||
|                         options, | ||||
|                     )); | ||||
|                     break; | ||||
|                 case 'author': | ||||
|                     promises.push(AddonModGlossary.fetchAllEntries( | ||||
|                         AddonModGlossary.getEntriesByAuthor.bind( | ||||
|                             AddonModGlossary.instance, | ||||
|                         (newOptions) => AddonModGlossary.getEntriesByAuthor( | ||||
|                             glossary.id, | ||||
|                             'ALL', | ||||
|                             'LASTNAME', | ||||
|                             'ASC', | ||||
|                             newOptions, | ||||
|                         ), | ||||
|                         options, | ||||
|                     )); | ||||
| @ -171,7 +171,7 @@ export class AddonModGlossaryPrefetchHandlerService extends CoreCourseActivityPr | ||||
| 
 | ||||
|         // Fetch all entries to get information from.
 | ||||
|         promises.push(AddonModGlossary.fetchAllEntries( | ||||
|             AddonModGlossary.getEntriesByLetter.bind(AddonModGlossary.instance, glossary.id, 'ALL'), | ||||
|             (newOptions) => AddonModGlossary.getEntriesByLetter(glossary.id, 'ALL', newOptions), | ||||
|             options, | ||||
|         ).then((entries) => { | ||||
|             const promises: Promise<unknown>[] = []; | ||||
|  | ||||
| @ -98,7 +98,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv | ||||
|         this.siteCanDownload = this.site.canDownloadFiles() && !CoreH5P.isOfflineDisabledInSite(); | ||||
| 
 | ||||
|         // Listen for messages from the iframe.
 | ||||
|         this.messageListenerFunction = this.onIframeMessage.bind(this); | ||||
|         this.messageListenerFunction = (event) => this.onIframeMessage(event); | ||||
|         window.addEventListener('message', this.messageListenerFunction); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -48,7 +48,7 @@ export class AddonModH5PActivitySyncProvider extends CoreCourseActivitySyncBaseP | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllActivities(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('H5P activities', this.syncAllActivitiesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('H5P activities', (siteId) => this.syncAllActivitiesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -77,7 +77,7 @@ export class AddonModH5PActivityPrefetchHandlerService extends CoreCourseActivit | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchActivity.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchActivity(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -285,12 +285,13 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|                 this.offline = true; | ||||
|             } | ||||
| 
 | ||||
|             const lessonId = this.lesson.id; | ||||
|             const options = { | ||||
|                 cmId: this.cmId, | ||||
|                 readingStrategy: this.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK, | ||||
|             }; | ||||
|             this.accessInfo = await this.callFunction<AddonModLessonGetAccessInformationWSResponse>( | ||||
|                 AddonModLesson.getAccessInformation.bind(AddonModLesson.instance, this.lesson.id, options), | ||||
|                 () => AddonModLesson.getAccessInformation(lessonId, options), | ||||
|                 options, | ||||
|             ); | ||||
| 
 | ||||
| @ -321,7 +322,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|                     readingStrategy: this.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK, | ||||
|                 }; | ||||
|                 promises.push(this.callFunction<AddonModLessonLessonWSData>( | ||||
|                     AddonModLesson.getLessonWithPassword.bind(AddonModLesson.instance, this.lesson.id, options), | ||||
|                     () => AddonModLesson.getLessonWithPassword(lessonId, options), | ||||
|                     options, | ||||
|                 ).then((lesson) => { | ||||
|                     this.lesson = lesson; | ||||
| @ -373,17 +374,22 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async finishRetake(outOfTime?: boolean): Promise<void> { | ||||
|         if (!this.lesson) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const lesson = this.lesson; | ||||
|         this.messages = []; | ||||
| 
 | ||||
|         if (this.offline && CoreNetwork.isOnline()) { | ||||
|             // Offline mode but the app is online. Try to sync the data.
 | ||||
|             const result = await CoreUtils.ignoreErrors( | ||||
|                 AddonModLessonSync.syncLesson(this.lesson!.id, true, true), | ||||
|                 AddonModLessonSync.syncLesson(lesson.id, true, true), | ||||
|             ); | ||||
| 
 | ||||
|             if (result?.warnings?.length) { | ||||
|                 // Some data was deleted. Check if the retake has changed.
 | ||||
|                 const info = await AddonModLesson.getAccessInformation(this.lesson!.id, { | ||||
|                 const info = await AddonModLesson.getAccessInformation(lesson.id, { | ||||
|                     cmId: this.cmId, | ||||
|                 }); | ||||
| 
 | ||||
| @ -411,11 +417,11 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|             accessInfo: this.accessInfo, | ||||
|         }; | ||||
|         const data = await this.callFunction<AddonModLessonFinishRetakeResponse>( | ||||
|             AddonModLesson.finishRetake.bind(AddonModLesson.instance, this.lesson, this.courseId, options), | ||||
|             () => AddonModLesson.finishRetake(lesson, this.courseId, options), | ||||
|             options, | ||||
|         ); | ||||
| 
 | ||||
|         this.title = this.lesson!.name; | ||||
|         this.title = lesson.name; | ||||
|         this.eolData = data.data; | ||||
|         this.messages = this.messages.concat(data.messages); | ||||
|         this.processData = undefined; | ||||
| @ -512,13 +518,14 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async loadMenu(): Promise<void> { | ||||
|         if (this.loadingMenu) { | ||||
|         if (this.loadingMenu || !this.lesson) { | ||||
|             // Already loading.
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             this.loadingMenu = true; | ||||
|             const lessonId = this.lesson.id; | ||||
|             const options = { | ||||
|                 password: this.password, | ||||
|                 cmId: this.cmId, | ||||
| @ -526,7 +533,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|             }; | ||||
| 
 | ||||
|             const pages = await this.callFunction<AddonModLessonGetPagesPageWSData[]>( | ||||
|                 AddonModLesson.getPages.bind(AddonModLesson.instance, this.lesson!.id, options), | ||||
|                 () => AddonModLesson.getPages(lessonId, options), | ||||
|                 options, | ||||
|             ); | ||||
| 
 | ||||
| @ -548,8 +555,11 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|         if (pageId == AddonModLessonProvider.LESSON_EOL) { | ||||
|             // End of lesson reached.
 | ||||
|             return this.finishRetake(); | ||||
|         } else if (!this.lesson) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const lesson = this.lesson; | ||||
|         const options = { | ||||
|             password: this.password, | ||||
|             review: this.review, | ||||
| @ -562,7 +572,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|         }; | ||||
| 
 | ||||
|         const data = await this.callFunction<AddonModLessonGetPageDataWSResponse>( | ||||
|             AddonModLesson.getPageData.bind(AddonModLesson.instance, this.lesson, pageId, options), | ||||
|             () => AddonModLesson.getPageData(lesson, pageId, options), | ||||
|             options, | ||||
|         ); | ||||
| 
 | ||||
| @ -615,8 +625,14 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async processPage(data: CoreFormFields, formSubmitted?: boolean): Promise<void> { | ||||
|         if (!this.lesson || !this.pageData) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.loaded = false; | ||||
| 
 | ||||
|         const lesson = this.lesson; | ||||
|         const pageData = this.pageData; | ||||
|         const options: AddonModLessonProcessPageOptions = { | ||||
|             password: this.password, | ||||
|             review: this.review, | ||||
| @ -627,11 +643,10 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
| 
 | ||||
|         try { | ||||
|             const result = await this.callFunction<AddonModLessonProcessPageResponse>( | ||||
|                 AddonModLesson.processPage.bind( | ||||
|                     AddonModLesson.instance, | ||||
|                     this.lesson, | ||||
|                 () => AddonModLesson.processPage( | ||||
|                     lesson, | ||||
|                     this.courseId, | ||||
|                     this.pageData, | ||||
|                     pageData, | ||||
|                     data, | ||||
|                     options, | ||||
|                 ), | ||||
| @ -646,7 +661,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             if (!this.offline && !this.review && AddonModLesson.isLessonOffline(this.lesson!)) { | ||||
|             if (!this.offline && !this.review && AddonModLesson.isLessonOffline(lesson)) { | ||||
|                 // Lesson allows offline and the user changed some data in server. Update cached data.
 | ||||
|                 const retake = this.accessInfo!.attemptscount; | ||||
|                 const options = { | ||||
| @ -656,9 +671,9 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
| 
 | ||||
|                 // Update in background the list of content pages viewed or question attempts.
 | ||||
|                 if (AddonModLesson.isQuestionPage(this.pageData?.page?.type || -1)) { | ||||
|                     AddonModLesson.getQuestionsAttemptsOnline(this.lesson!.id, retake, options); | ||||
|                     AddonModLesson.getQuestionsAttemptsOnline(lesson.id, retake, options); | ||||
|                 } else { | ||||
|                     AddonModLesson.getContentPagesViewedOnline(this.lesson!.id, retake, options); | ||||
|                     AddonModLesson.getContentPagesViewedOnline(lesson.id, retake, options); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| @ -673,7 +688,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|             this.processData = result; | ||||
|             this.processDataButtons = []; | ||||
| 
 | ||||
|             if (this.lesson!.review && !result.correctanswer && !result.noanswer && !result.isessayquestion && | ||||
|             if (lesson.review && !result.correctanswer && !result.noanswer && !result.isessayquestion && | ||||
|                     !result.maxattemptsreached && !result.reviewmode) { | ||||
|                 // User can try again, show button to do so.
 | ||||
|                 this.processDataButtons.push({ | ||||
| @ -683,11 +698,11 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave { | ||||
|             } | ||||
| 
 | ||||
|             // Button to continue.
 | ||||
|             if (this.lesson!.review && !result.correctanswer && !result.noanswer && !result.isessayquestion && | ||||
|             if (lesson.review && !result.correctanswer && !result.noanswer && !result.isessayquestion && | ||||
|                     !result.maxattemptsreached) { | ||||
|                 /* If both the "Yes, I'd like to try again" and "No, I just want to go on to the next question" point to the | ||||
|                     same page then don't show the "No, I just want to go on to the next question" button. It's confusing. */ | ||||
|                 if (this.pageData!.page!.id != result.newpageid) { | ||||
|                 if (pageData.page?.id != result.newpageid) { | ||||
|                     // Button to continue the lesson (the page to go is configured by the teacher).
 | ||||
|                     this.processDataButtons.push({ | ||||
|                         label: 'addon.mod_lesson.reviewquestioncontinue', | ||||
|  | ||||
| @ -225,7 +225,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number, single?: boolean): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchLesson.bind(this, module, courseId, !!single)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchLesson(module, courseId, !!single, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -122,7 +122,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllLessons(siteId?: string, force = false): Promise<void> { | ||||
|         return this.syncOnSites('all lessons', this.syncAllLessonsFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all lessons', (siteId) => this.syncAllLessonsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -333,7 +333,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid | ||||
|         attempts.sort((a, b) => a.timemodified - b.timemodified); | ||||
| 
 | ||||
|         const promisesData = attempts.map((attempt) => ({ | ||||
|             function: this.sendAttempt.bind(this, lesson, passwordData.password, attempt, result, siteId), | ||||
|             function: () => this.sendAttempt(lesson, passwordData.password ?? '', attempt, result, siteId), | ||||
|             blocking: true, | ||||
|         })); | ||||
| 
 | ||||
|  | ||||
| @ -278,7 +278,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchQuiz.bind(this, module, courseId, !!single, canStart)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchQuiz(module, courseId, !!single, canStart, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -180,7 +180,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllQuizzes(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all quizzes', this.syncAllQuizzesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all quizzes', (siteId) => this.syncAllQuizzesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -70,7 +70,10 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase | ||||
|         sectionId?: number, | ||||
|         forCoursePage?: boolean, | ||||
|     ): Promise<CoreCourseModuleHandlerData> { | ||||
|         const updateStatus = (status: string): void => { | ||||
|         const openWithPicker = CoreFileHelper.defaultIsOpenWithPicker(); | ||||
| 
 | ||||
|         const handlerData = await super.getData(module, courseId, sectionId, forCoursePage); | ||||
|         handlerData.updateStatus = (status) => { | ||||
|             if (!handlerData.buttons) { | ||||
|                 return; | ||||
|             } | ||||
| @ -78,10 +81,6 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase | ||||
|             handlerData.buttons[0].hidden = status !== CoreConstants.DOWNLOADED || | ||||
|                 AddonModResourceHelper.isDisplayedInIframe(module); | ||||
|         }; | ||||
|         const openWithPicker = CoreFileHelper.defaultIsOpenWithPicker(); | ||||
| 
 | ||||
|         const handlerData = await super.getData(module, courseId, sectionId, forCoursePage); | ||||
|         handlerData.updateStatus = updateStatus.bind(this); | ||||
|         handlerData.buttons = [{ | ||||
|             hidden: true, | ||||
|             icon: openWithPicker ? 'fas-share-square' : 'fas-file', | ||||
|  | ||||
| @ -883,7 +883,7 @@ export class AddonModScormDataModel12 { | ||||
|                             // Store data.
 | ||||
|                             if (this.errorCode == '0') { | ||||
|                                 if (this.scorm.autocommit && !this.timeout) { | ||||
|                                     this.timeout = window.setTimeout(this.LMSCommit.bind(this), 60000, ['']); | ||||
|                                     this.timeout = window.setTimeout(() => this.LMSCommit(''), 60000); | ||||
|                                 } | ||||
| 
 | ||||
|                                 const range = this.dataModel[this.scoId][elementModel].range; | ||||
|  | ||||
| @ -175,7 +175,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy { | ||||
| 
 | ||||
|             if (this.offline) { | ||||
|                 // Wait a bit to make sure data is stored.
 | ||||
|                 setTimeout(this.refreshToc.bind(this), 100); | ||||
|                 setTimeout(() => this.refreshToc(), 100); | ||||
|             } else { | ||||
|                 this.refreshToc(); | ||||
|             } | ||||
|  | ||||
| @ -50,7 +50,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|         return this.prefetchPackage( | ||||
|             module, | ||||
|             courseId, | ||||
|             this.downloadOrPrefetchScorm.bind(this, module, courseId, true, false, onProgress), | ||||
|             (siteId) => this.downloadOrPrefetchScorm(module, courseId, true, false, onProgress, siteId), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
| @ -126,7 +126,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|                 scorm.coursemodule, | ||||
|                 undefined, | ||||
|                 undefined, | ||||
|                 this.downloadProgress.bind(this, true, onProgress), | ||||
|                 (event: ProgressEvent<EventTarget>) => this.downloadProgress(true, onProgress, event), | ||||
|             ); | ||||
|         } else { | ||||
|             await CoreFilepool.downloadUrl( | ||||
| @ -136,7 +136,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|                 this.component, | ||||
|                 scorm.coursemodule, | ||||
|                 undefined, | ||||
|                 this.downloadProgress.bind(this, true, onProgress), | ||||
|                 (event: ProgressEvent<EventTarget>) => this.downloadProgress(true, onProgress, event), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
| @ -147,7 +147,11 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|         onProgress && onProgress({ message: 'core.unzipping' }); | ||||
| 
 | ||||
|         // Unzip and delete the zip when finished.
 | ||||
|         await CoreFile.unzipFile(zipPath, dirPath, this.downloadProgress.bind(this, false, onProgress)); | ||||
|         await CoreFile.unzipFile( | ||||
|             zipPath, | ||||
|             dirPath, | ||||
|             (event: ProgressEvent<EventTarget>) => this.downloadProgress(false, onProgress, event), | ||||
|         ); | ||||
| 
 | ||||
|         await CoreUtils.ignoreErrors(CoreFilepool.removeFileByUrl(siteId, packageUrl)); | ||||
|     } | ||||
| @ -371,7 +375,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe | ||||
|         return this.prefetchPackage( | ||||
|             module, | ||||
|             courseId, | ||||
|             this.downloadOrPrefetchScorm.bind(this, module, courseId, single, true, onProgress), | ||||
|             (siteId) => this.downloadOrPrefetchScorm(module, courseId, !!single, true, onProgress, siteId), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -445,7 +445,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllScorms(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all SCORMs', this.syncAllScormsFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all SCORMs', (siteId) => this.syncAllScormsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -68,7 +68,7 @@ export class AddonModSurveyPrefetchHandlerService extends CoreCourseActivityPref | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchSurvey.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchSurvey(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -60,7 +60,7 @@ export class AddonModSurveySyncProvider extends CoreCourseActivitySyncBaseProvid | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllSurveys(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all surveys', this.syncAllSurveysFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all surveys', (siteId) => this.syncAllSurveysFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -140,7 +140,7 @@ export class AddonModWikiPrefetchHandlerService extends CoreCourseActivityPrefet | ||||
|         return this.prefetchPackage( | ||||
|             module, | ||||
|             courseId, | ||||
|             this.prefetchWiki.bind(this, module, courseId, !!single, downloadTime), | ||||
|             (siteId) => this.prefetchWiki(module, courseId, !!single, downloadTime, siteId), | ||||
|             siteId, | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @ -73,7 +73,7 @@ export class AddonModWikiSyncProvider extends CoreSyncBaseProvider<AddonModWikiS | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllWikis(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all wikis', this.syncAllWikisFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all wikis', (siteId) => this.syncAllWikisFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -135,8 +135,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe | ||||
|                 await this.load(); | ||||
|                 this.obsInvalidated = CoreEvents.on( | ||||
|                     AddonModWorkshopProvider.ASSESSMENT_INVALIDATED, | ||||
|                     this.load.bind(this), | ||||
| 
 | ||||
|                     () => this.load(), | ||||
|                     CoreSites.getCurrentSiteId(), | ||||
|                 ); | ||||
|             } catch (error) { | ||||
|  | ||||
| @ -205,7 +205,7 @@ export class AddonModWorkshopPrefetchHandlerService extends CoreCourseActivityPr | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(module: CoreCourseAnyModuleData, courseId: number): Promise<void> { | ||||
|         return this.prefetchPackage(module, courseId, this.prefetchWorkshop.bind(this, module, courseId)); | ||||
|         return this.prefetchPackage(module, courseId, (siteId) => this.prefetchWorkshop(module, courseId, siteId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -141,7 +141,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopSubmissionDBRecord>(SUBMISSIONS_TABLE); | ||||
| 
 | ||||
|         return records.map(this.parseSubmissionRecord.bind(this)); | ||||
|         return records.map((record) => this.parseSubmissionRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -160,7 +160,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopSubmissionDBRecord>(SUBMISSIONS_TABLE, conditions); | ||||
| 
 | ||||
|         return records.map(this.parseSubmissionRecord.bind(this)); | ||||
|         return records.map((record) => this.parseSubmissionRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -273,7 +273,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopAssessmentDBRecord>(ASSESSMENTS_TABLE); | ||||
| 
 | ||||
|         return records.map(this.parseAssessmentRecord.bind(this)); | ||||
|         return records.map((record) => this.parseAssessmentRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -292,7 +292,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopAssessmentDBRecord>(ASSESSMENTS_TABLE, conditions); | ||||
| 
 | ||||
|         return records.map(this.parseAssessmentRecord.bind(this)); | ||||
|         return records.map((record) => this.parseAssessmentRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -388,7 +388,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopEvaluateSubmissionDBRecord>(EVALUATE_SUBMISSIONS_TABLE); | ||||
| 
 | ||||
|         return records.map(this.parseEvaluateSubmissionRecord.bind(this)); | ||||
|         return records.map((record) => this.parseEvaluateSubmissionRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -408,7 +408,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
|         const records = | ||||
|             await site.getDb().getRecords<AddonModWorkshopEvaluateSubmissionDBRecord>(EVALUATE_SUBMISSIONS_TABLE, conditions); | ||||
| 
 | ||||
|         return records.map(this.parseEvaluateSubmissionRecord.bind(this)); | ||||
|         return records.map((record) => this.parseEvaluateSubmissionRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -518,7 +518,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
| 
 | ||||
|         const records = await site.getDb().getRecords<AddonModWorkshopEvaluateAssessmentDBRecord>(EVALUATE_ASSESSMENTS_TABLE); | ||||
| 
 | ||||
|         return records.map(this.parseEvaluateAssessmentRecord.bind(this)); | ||||
|         return records.map((record) => this.parseEvaluateAssessmentRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -538,7 +538,7 @@ export class AddonModWorkshopOfflineProvider { | ||||
|         const records = | ||||
|             await site.getDb().getRecords<AddonModWorkshopEvaluateAssessmentDBRecord>(EVALUATE_ASSESSMENTS_TABLE, conditions); | ||||
| 
 | ||||
|         return records.map(this.parseEvaluateAssessmentRecord.bind(this)); | ||||
|         return records.map((record) => this.parseEvaluateAssessmentRecord(record)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -73,7 +73,7 @@ export class AddonModWorkshopSyncProvider extends CoreSyncBaseProvider<AddonModW | ||||
|      * @return Promise resolved when the sync is done. | ||||
|      */ | ||||
|     syncAllWorkshops(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all workshops', this.syncAllWorkshopsFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all workshops', (siteId) => this.syncAllWorkshopsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -19,8 +19,7 @@ import { | ||||
|     CoreCourseOptionsHandler, | ||||
|     CoreCourseOptionsHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { AddonNotes } from '../notes'; | ||||
| 
 | ||||
| @ -73,7 +72,7 @@ export class AddonNotesCourseOptionHandlerService implements CoreCourseOptionsHa | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         await AddonNotes.getNotes(course.id, undefined, true); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -45,7 +45,7 @@ export class AddonNotesSyncProvider extends CoreSyncBaseProvider<AddonNotesSyncR | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllNotes(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all notes', this.syncAllNotesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all notes', (siteId) => this.syncAllNotesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -183,7 +183,7 @@ export class AddonNotificationsNotificationPage implements OnInit, OnDestroy { | ||||
|             actions.push({ | ||||
|                 message: 'core.view', | ||||
|                 icon: 'fas-eye', | ||||
|                 action: this.openInBrowser.bind(this), | ||||
|                 action: (siteId) => this.openInBrowser(siteId), | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -55,8 +55,8 @@ export class AddonQbehaviourDeferredCBMHandlerService implements CoreQuestionBeh | ||||
|             question, | ||||
|             componentId, | ||||
|             siteId, | ||||
|             this.isCompleteResponse.bind(this), | ||||
|             this.isSameResponse.bind(this), | ||||
|             (...args) => this.isCompleteResponse(...args), | ||||
|             (...args) => this.isSameResponse(...args), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -39,7 +39,7 @@ export class CoreSortedDelegate< | ||||
|     constructor(delegateName: string) { | ||||
|         super(delegateName, true); | ||||
| 
 | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, this.clearSortedHandlers.bind(this)); | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, () => this.clearSortedHandlers()); | ||||
|         CoreEvents.on(CoreEvents.SITE_POLICY_AGREED, (data) => { | ||||
|             if (data.siteId === CoreSites.getCurrentSiteId()) { | ||||
|                 // Clear loaded handlers when policy is agreed. The CoreDelegate class will load them again.
 | ||||
| @ -47,7 +47,7 @@ export class CoreSortedDelegate< | ||||
|             } | ||||
|         }); | ||||
|         // Clear loaded handlers on login, there could be an invalid list loaded when user reconnects after token expired.
 | ||||
|         CoreEvents.on(CoreEvents.LOGIN, this.clearSortedHandlers.bind(this)); | ||||
|         CoreEvents.on(CoreEvents.LOGIN, () => this.clearSortedHandlers()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -95,9 +95,9 @@ export class CoreDelegate<HandlerType extends CoreDelegateHandler> { | ||||
| 
 | ||||
|         if (listenSiteEvents) { | ||||
|             // Update handlers on this cases.
 | ||||
|             CoreEvents.on(CoreEvents.LOGIN, this.updateHandlers.bind(this)); | ||||
|             CoreEvents.on(CoreEvents.SITE_UPDATED, this.updateHandlers.bind(this)); | ||||
|             CoreEvents.on(CoreEvents.SITE_PLUGINS_LOADED, this.updateHandlers.bind(this)); | ||||
|             CoreEvents.on(CoreEvents.LOGIN, () => this.updateHandlers()); | ||||
|             CoreEvents.on(CoreEvents.SITE_UPDATED, () => this.updateHandlers()); | ||||
|             CoreEvents.on(CoreEvents.SITE_PLUGINS_LOADED, () => this.updateHandlers()); | ||||
|             CoreEvents.on(CoreEvents.SITE_POLICY_AGREED, (data) => { | ||||
|                 if (data.siteId === CoreSites.getCurrentSiteId()) { | ||||
|                     this.updateHandlers(); | ||||
|  | ||||
| @ -29,8 +29,8 @@ export class CorePromisedValue<T = unknown> extends CorePromise<T> { | ||||
|         const promisedValue = new CorePromisedValue<T>(); | ||||
| 
 | ||||
|         promise | ||||
|             .then(promisedValue.resolve.bind(promisedValue)) | ||||
|             .catch(promisedValue.reject.bind(promisedValue)); | ||||
|             .then(value => promisedValue.resolve(value)) | ||||
|             .catch(error => promisedValue.reject(error)); | ||||
| 
 | ||||
|         return promisedValue; | ||||
|     } | ||||
|  | ||||
| @ -994,7 +994,7 @@ export class CoreSite { | ||||
|             this.processRequestQueue(); | ||||
|         } else if (!this.requestQueueTimeout) { | ||||
|             this.requestQueueTimeout = window.setTimeout( | ||||
|                 this.processRequestQueue.bind(this), | ||||
|                 () => this.processRequestQueue(), | ||||
|                 CoreConstants.CONFIG.wsrequestqueuedelay, | ||||
|             ); | ||||
|         } | ||||
|  | ||||
| @ -95,7 +95,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft | ||||
|     tabAction: CoreTabsRoleTab<T>; | ||||
| 
 | ||||
|     constructor(element: ElementRef) { | ||||
|         this.backButtonFunction = this.backButtonClicked.bind(this); | ||||
|         this.backButtonFunction = (event) => this.backButtonClicked(event); | ||||
| 
 | ||||
|         this.tabAction = new CoreTabsRoleTab(this); | ||||
| 
 | ||||
|  | ||||
| @ -73,7 +73,7 @@ export class CoreContextMenuPopoverComponent { | ||||
|                 this.closeMenu(item); | ||||
|             } | ||||
| 
 | ||||
|             item.action.emit(this.closeMenu.bind(this, item)); | ||||
|             item.action.emit(() => this.closeMenu(item)); | ||||
|         } else if (item.closeOnClick && (item.href || (!!item.onClosed && item.onClosed.observers.length > 0))) { | ||||
|             this.closeMenu(item); | ||||
|         } | ||||
|  | ||||
| @ -103,7 +103,7 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | ||||
|         } | ||||
| 
 | ||||
|         this.loadingMore = true; | ||||
|         this.action.emit(this.complete.bind(this)); | ||||
|         this.action.emit(() => this.complete()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -112,7 +112,7 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | ||||
|     complete(): void { | ||||
|         if (this.position == 'top') { | ||||
|             // Wait a bit before allowing loading more, otherwise it could be re-triggered automatically when it shouldn't.
 | ||||
|             setTimeout(this.completeLoadMore.bind(this), 400); | ||||
|             setTimeout(() => this.completeLoadMore(), 400); | ||||
|         } else { | ||||
|             this.completeLoadMore(); | ||||
|         } | ||||
|  | ||||
| @ -64,7 +64,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { | ||||
|     constructor(el: ElementRef<HTMLElement>) { | ||||
|         this.element = el.nativeElement; | ||||
| 
 | ||||
|         this.element.addEventListener('click', this.elementClicked.bind(this)); | ||||
|         this.element.addEventListener('click', (event) => this.elementClicked(event)); | ||||
|         this.uniqueId = 'collapsible-item-' + CoreUtils.getUniqueId('CoreCollapsibleItemDirective'); | ||||
|         this.element.id = this.uniqueId; | ||||
|     } | ||||
|  | ||||
| @ -116,7 +116,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
| 
 | ||||
|         this.afterRender = new EventEmitter<void>(); | ||||
| 
 | ||||
|         this.element.addEventListener('click', this.elementClicked.bind(this)); | ||||
|         this.element.addEventListener('click', (event) => this.elementClicked(event)); | ||||
| 
 | ||||
|         this.siteId = this.siteId || CoreSites.getCurrentSiteId(); | ||||
|     } | ||||
|  | ||||
| @ -80,7 +80,7 @@ export class CoreSupressEventsDirective implements OnInit { | ||||
| 
 | ||||
|         // Suppress the events.
 | ||||
|         for (const evName of events) { | ||||
|             this.element.addEventListener(evName, this.stopBubble.bind(this)); | ||||
|             this.element.addEventListener(evName, (event) => this.stopBubble(event)); | ||||
|         } | ||||
| 
 | ||||
|         // Now listen to "click" events.
 | ||||
|  | ||||
| @ -44,7 +44,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider<CoreCommentsS | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllComments(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('all comments', this.syncAllCommentsFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('all comments', (siteId) => this.syncAllCommentsFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -179,7 +179,7 @@ export class CoreContentLinksDelegateService { | ||||
|         for (const name in this.handlers) { | ||||
|             const handler = this.handlers[name]; | ||||
|             const checkAll = handler.checkAllUsers; | ||||
|             const isEnabledFn = this.isHandlerEnabled.bind(this, handler, relativeUrl, params, courseId); | ||||
|             const isEnabledFn = (siteId: string) => this.isHandlerEnabled(handler, relativeUrl, params, courseId, siteId); | ||||
| 
 | ||||
|             if (!handler.handles(relativeUrl)) { | ||||
|                 // Invalid handler or it doesn't handle the URL. Stop.
 | ||||
| @ -282,7 +282,7 @@ export class CoreContentLinksDelegateService { | ||||
|         handler: CoreContentLinksHandler, | ||||
|         url: string, | ||||
|         params: Record<string, string>, | ||||
|         courseId: number, | ||||
|         courseId: number | undefined, | ||||
|         siteId: string, | ||||
|     ): Promise<boolean> { | ||||
| 
 | ||||
|  | ||||
| @ -65,21 +65,18 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe | ||||
|      * Prefetch the module, setting package status at start and finish. | ||||
|      * | ||||
|      * Example usage from a child instance: | ||||
|      *     return this.prefetchPackage(module, courseId, single, this.prefetchModule.bind(this, otherParam), siteId); | ||||
|      * | ||||
|      * Then the function "prefetchModule" will receive params: | ||||
|      *     prefetchModule(module, courseId, single, siteId, someParam, anotherParam) | ||||
|      *     return this.prefetchPackage(module, courseId, (siteId) => this.prefetchModule(module, otherParam, siteId), siteId); | ||||
|      * | ||||
|      * @param module Module. | ||||
|      * @param courseId Course ID the module belongs to. | ||||
|      * @param downloadFn Function to perform the prefetch. Please check the documentation of prefetchFunction. | ||||
|      * @param downloadFn Function to perform the prefetch. It can return a string to be stored as the package "extra" data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the module has been downloaded. Data returned is not reliable. | ||||
|      */ | ||||
|     async prefetchPackage( | ||||
|         module: CoreCourseAnyModuleData, | ||||
|         courseId: number, | ||||
|         downloadFunction: (siteId: string) => Promise<string>, | ||||
|         downloadFunction: (siteId: string) => Promise<string | void>, | ||||
|         siteId?: string, | ||||
|     ): Promise<void> { | ||||
|         siteId = siteId || CoreSites.getCurrentSiteId(); | ||||
| @ -104,14 +101,14 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe | ||||
|      * | ||||
|      * @param module Module. | ||||
|      * @param courseId Course ID the module belongs to. | ||||
|      * @param downloadFn Function to perform the prefetch. Please check the documentation of prefetchFunction. | ||||
|      * @param downloadFn Function to perform the prefetch. It can return a string to be stored as the package "extra" data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the module has been downloaded. Data returned is not reliable. | ||||
|      */ | ||||
|     protected async changeStatusAndPrefetch( | ||||
|         module: CoreCourseAnyModuleData, | ||||
|         courseId: number | undefined, | ||||
|         downloadFunction: (siteId: string) => Promise<string>, | ||||
|         downloadFunction: (siteId: string) => Promise<string | void>, | ||||
|         siteId: string, | ||||
|     ): Promise<void> { | ||||
|         try { | ||||
|  | ||||
| @ -90,7 +90,7 @@ export interface CoreCourseOptionsHandler extends CoreDelegateHandler { | ||||
|      * @param course The course. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     prefetch?(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void>; | ||||
|     prefetch?(course: CoreCourseAnyCourseData): Promise<void>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -452,7 +452,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate<CoreCourseOpt | ||||
|                 handlersToDisplay.push({ | ||||
|                     data: data, | ||||
|                     priority: handler.priority || 0, | ||||
|                     prefetch: handler.prefetch && handler.prefetch.bind(handler), | ||||
|                     prefetch: async (course) => await handler.prefetch?.(course), | ||||
|                     name: handler.name, | ||||
|                 }); | ||||
| 
 | ||||
|  | ||||
| @ -61,7 +61,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo | ||||
|      * Initialize. | ||||
|      */ | ||||
|     initialize(): void { | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, this.clearStatusCache.bind(this)); | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, () => this.clearStatusCache()); | ||||
| 
 | ||||
|         CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => { | ||||
|             this.updateStatusCache(data.status, data.component, data.componentId); | ||||
|  | ||||
| @ -51,7 +51,7 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider<CoreCourseSyncR | ||||
|      * @return Promise resolved if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncAllCourses(siteId?: string, force?: boolean): Promise<void> { | ||||
|         return this.syncOnSites('courses', this.syncAllCoursesFunc.bind(this, !!force), siteId); | ||||
|         return this.syncOnSites('courses', (siteId) => this.syncAllCoursesFunc(!!force, siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -171,11 +171,11 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|         this.setContent(this.control?.value); | ||||
|         this.originalContent = this.control?.value; | ||||
|         this.lastDraft = this.control?.value; | ||||
|         this.editorElement.onchange = this.onChange.bind(this); | ||||
|         this.editorElement.onkeyup = this.onChange.bind(this); | ||||
|         this.editorElement.onpaste = this.onChange.bind(this); | ||||
|         this.editorElement.oninput = this.onChange.bind(this); | ||||
|         this.editorElement.onkeydown = this.moveCursor.bind(this); | ||||
|         this.editorElement.onchange = () => this.onChange(); | ||||
|         this.editorElement.onkeyup = () => this.onChange(); | ||||
|         this.editorElement.onpaste = () => this.onChange(); | ||||
|         this.editorElement.oninput = () => this.onChange(); | ||||
|         this.editorElement.onkeydown = event => this.moveCursor(event); | ||||
| 
 | ||||
|         // Use paragraph on enter.
 | ||||
|         document.execCommand('DefaultParagraphSeparator', false, 'p'); | ||||
| @ -258,7 +258,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|             this.windowResized(); | ||||
|         }, 50); | ||||
| 
 | ||||
|         document.addEventListener('selectionchange', this.selectionChangeFunction = this.updateToolbarStyles.bind(this)); | ||||
|         document.addEventListener('selectionchange', this.selectionChangeFunction = () => this.updateToolbarStyles()); | ||||
| 
 | ||||
|         this.keyboardObserver = CoreEvents.on(CoreEvents.KEYBOARD_CHANGE, () => { | ||||
|             // Opening or closing the keyboard also calls the resize function, but sometimes the resize is called too soon.
 | ||||
|  | ||||
| @ -47,8 +47,8 @@ export class GeolocationMock extends Geolocation { | ||||
|     watchPosition(options?: GeolocationOptions): Observable<Geoposition> { | ||||
|         return new Observable<Geoposition>((subscriber: Subscriber<Geoposition>): TeardownLogic => { | ||||
|             const watchId = navigator.geolocation.watchPosition( | ||||
|                 subscriber.next.bind(subscriber), | ||||
|                 subscriber.error.bind(subscriber), | ||||
|                 position => subscriber.next(<Geoposition> <unknown> position), | ||||
|                 error => subscriber.error(error), | ||||
|                 options, | ||||
|             ); | ||||
| 
 | ||||
|  | ||||
| @ -145,7 +145,7 @@ export class CoreFileUploaderDelegateService extends CoreDelegate<CoreFileUpload | ||||
|     constructor() { | ||||
|         super('CoreFileUploaderDelegate', true); | ||||
| 
 | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, this.clearSiteHandlers.bind(this)); | ||||
|         CoreEvents.on(CoreEvents.LOGOUT, () => this.clearSiteHandlers()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -218,6 +218,7 @@ export class CoreFilterHelperProvider { | ||||
|                 return CoreFilterDelegate.getEnabledFilters(contextLevel, instanceId); | ||||
|             } | ||||
| 
 | ||||
|             const courseId = options.courseId; | ||||
|             let hasFilters = true; | ||||
| 
 | ||||
|             if (contextLevel == 'system' || (contextLevel == 'course' && instanceId == site.getSiteHomeId())) { | ||||
| @ -233,20 +234,20 @@ export class CoreFilterHelperProvider { | ||||
| 
 | ||||
|             options.filter = true; | ||||
| 
 | ||||
|             if (contextLevel == 'module' && options.courseId) { | ||||
|             if (contextLevel == 'module' && courseId) { | ||||
|                 // Get all the modules filters with a single call to decrease the number of WS calls.
 | ||||
|                 const getFilters = this.getCourseModulesContexts.bind(this, options.courseId, siteId); | ||||
|                 const getFilters = () => this.getCourseModulesContexts(courseId, siteId); | ||||
| 
 | ||||
|                 return this.getCacheableFilters(contextLevel, instanceId, getFilters, options, site); | ||||
| 
 | ||||
|             } else if (contextLevel == 'course') { | ||||
|                 // If enrolled, get all enrolled courses filters with a single call to decrease number of WS calls.
 | ||||
|                 const getFilters = this.getCourseContexts.bind(this, instanceId, siteId); | ||||
|                 const getFilters = () => this.getCourseContexts(instanceId, siteId); | ||||
| 
 | ||||
|                 return this.getCacheableFilters(contextLevel, instanceId, getFilters, options, site); | ||||
|             } else if (contextLevel == 'block' && options.courseId && CoreCourse.canGetCourseBlocks(site)) { | ||||
|             } else if (contextLevel == 'block' && courseId && CoreCourse.canGetCourseBlocks(site)) { | ||||
|                 // Get all the course blocks filters with a single call to decrease number of WS calls.
 | ||||
|                 const getFilters = this.getBlocksContexts.bind(this, options.courseId, siteId); | ||||
|                 const getFilters = () => this.getBlocksContexts(courseId, siteId); | ||||
| 
 | ||||
|                 return this.getCacheableFilters(contextLevel, instanceId, getFilters, options, site); | ||||
|             } | ||||
|  | ||||
| @ -19,8 +19,7 @@ import { | ||||
|     CoreCourseOptionsHandler, | ||||
|     CoreCourseOptionsHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreCourses, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourses, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { CoreGrades } from '../grades'; | ||||
| 
 | ||||
| @ -34,11 +33,7 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa | ||||
|     priority = 400; | ||||
| 
 | ||||
|     /** | ||||
|      * Should invalidate the data to determine if the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param courseId The course ID. | ||||
|      * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @return Promise resolved when done. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise<void> { | ||||
|         if (navOptions && navOptions.grades !== undefined) { | ||||
| @ -50,21 +45,14 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the handler is enabled on a site level. | ||||
|      * | ||||
|      * @return Whether or not the handler is enabled on a site level. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async isEnabled(): Promise<boolean> { | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Whether or not the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param courseId The course ID. | ||||
|      * @param accessData Access type and data. Default, guest, ... | ||||
|      * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @return True or promise resolved with true if enabled. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     isEnabledForCourse( | ||||
|         courseId: number, | ||||
| @ -94,12 +82,9 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. | ||||
|      * | ||||
|      * @param course The course. | ||||
|      * @return Promise resolved when done. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         try { | ||||
|             await CoreGrades.getCourseGradesTable(course.id, undefined, undefined, true); | ||||
|         } catch (error) { | ||||
|  | ||||
| @ -493,31 +493,24 @@ export class CoreH5PContentValidator { | ||||
|                 } | ||||
| 
 | ||||
|                 // Find semantics for name=key.
 | ||||
|                 let found = false; | ||||
|                 let validateFunction: undefined | ((...args: unknown[]) => unknown); | ||||
|                 let field: CoreH5PSemantics | undefined; | ||||
|                 const field = semantics.fields.find(field => field.name === key); | ||||
|                 let value: unknown = null; | ||||
| 
 | ||||
|                 for (const field of semantics.fields) { | ||||
|                     if (field.name == key) { | ||||
|                         if (semantics.optional) { | ||||
|                             field.optional = true; | ||||
|                         } | ||||
|                         validateFunction = this[this.typeMap[field.type || '']].bind(this); | ||||
|                         found = true; | ||||
|                         break; | ||||
|                 if (field) { | ||||
|                     if (semantics.optional) { | ||||
|                         field.optional = true; | ||||
|                     } | ||||
| 
 | ||||
|                     const validateFunction = this[this.typeMap[field.type || '']].bind(this); | ||||
|                     if (validateFunction) { | ||||
|                         value = await validateFunction(groupObject[key], field); | ||||
| 
 | ||||
|                         groupObject[key] = value; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (found && validateFunction) { | ||||
|                     const val = await validateFunction(groupObject[key], field); | ||||
| 
 | ||||
|                     groupObject[key] = val; | ||||
|                     if (val === null) { | ||||
|                         delete groupObject[key]; | ||||
|                     } | ||||
|                 } else { | ||||
|                     // Something exists in content that does not have a corresponding semantics field. Remove it.
 | ||||
|                     delete groupObject.key; | ||||
|                 if (value === null) { | ||||
|                     delete groupObject[key]; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|  | ||||
| @ -92,7 +92,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { | ||||
|     tabAction: CoreMainMenuRoleTab; | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.backButtonFunction = this.backButtonClicked.bind(this); | ||||
|         this.backButtonFunction = (event) => this.backButtonClicked(event); | ||||
|         this.tabAction = new CoreMainMenuRoleTab(this); | ||||
|         this.logger = CoreLogger.getInstance('CoreMainMenuPage'); | ||||
| 
 | ||||
|  | ||||
| @ -50,7 +50,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | ||||
|     protected resizeListener?: CoreEventObserver; | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.langObserver = CoreEvents.on(CoreEvents.LANGUAGE_CHANGED, this.loadCustomMenuItems.bind(this)); | ||||
|         this.langObserver = CoreEvents.on(CoreEvents.LANGUAGE_CHANGED, () => this.loadCustomMenuItems()); | ||||
| 
 | ||||
|         this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async () => { | ||||
|             this.customItems = await CoreMainMenu.getCustomMenuItems(); | ||||
|  | ||||
| @ -84,9 +84,9 @@ export class CoreSettingsHelperProvider { | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             CoreEvents.on(CoreEvents.LOGIN, applySiteScheme.bind(this)); | ||||
|             CoreEvents.on(CoreEvents.LOGIN, () => applySiteScheme()); | ||||
| 
 | ||||
|             CoreEvents.on(CoreEvents.SITE_UPDATED, applySiteScheme.bind(this)); | ||||
|             CoreEvents.on(CoreEvents.SITE_UPDATED, () => applySiteScheme()); | ||||
| 
 | ||||
|             CoreEvents.on(CoreEvents.LOGOUT, () => { | ||||
|                 // Reset color scheme settings.
 | ||||
|  | ||||
| @ -19,8 +19,7 @@ import { | ||||
|     CoreCourseOptionsHandlerData, | ||||
|     CoreCourseOptionsMenuHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreCourseAnyCourseDataWithOptions } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourseAnyCourseDataWithOptions } from '@features/courses/services/courses'; | ||||
| import { | ||||
|     CoreSitePlugins, | ||||
|     CoreSitePluginsContent, | ||||
| @ -107,7 +106,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         const args = { | ||||
|             courseid: course.id, | ||||
|         }; | ||||
|  | ||||
| @ -56,7 +56,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp | ||||
| 
 | ||||
|         if (initResult?.jsResult && initResult.jsResult.supportsFeature) { | ||||
|             // The init result defines a function to check if a feature is supported, use it.
 | ||||
|             this.supportsFeature = initResult.jsResult.supportsFeature.bind(initResult.jsResult); | ||||
|             this.supportsFeature = (feature) => initResult.jsResult.supportsFeature(feature); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -58,7 +58,7 @@ export class CoreSitePluginsModulePrefetchHandler extends CoreCourseActivityPref | ||||
|         return this.prefetchPackage( | ||||
|             module, | ||||
|             courseId, | ||||
|             this.downloadPrefetchPlugin.bind(this, module, courseId, false, dirPath, siteId), | ||||
|             (siteId) => this.downloadPrefetchPlugin(module, courseId, false, dirPath, siteId), | ||||
|             siteId, | ||||
|         ); | ||||
|     } | ||||
| @ -226,7 +226,7 @@ export class CoreSitePluginsModulePrefetchHandler extends CoreCourseActivityPref | ||||
|         return this.prefetchPackage( | ||||
|             module, | ||||
|             courseId, | ||||
|             this.downloadPrefetchPlugin.bind(this, module, courseId, true, dirPath), | ||||
|             (siteId) => this.downloadPrefetchPlugin(module, courseId, true, dirPath, siteId), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -108,11 +108,13 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck { | ||||
|             this.jsData = Object.assign(this.data, CoreSitePlugins.createDataForJS(this.initResult, result)); | ||||
| 
 | ||||
|             // Pass some methods as jsData so they can be called from the template too.
 | ||||
|             this.jsData.fetchContent = this.fetchContent.bind(this); | ||||
|             this.jsData.openContent = this.openContent.bind(this); | ||||
|             this.jsData.refreshContent = this.refreshContent.bind(this); | ||||
|             this.jsData.updateContent = this.updateContent.bind(this); | ||||
|             this.jsData.updateModuleCourseContent = this.updateModuleCourseContent.bind(this); | ||||
|             this.jsData.fetchContent = refresh => this.fetchContent(refresh); | ||||
|             this.jsData.openContent = (title, args, component, method, jsData, preSets, ptrEnabled) => | ||||
|                 this.openContent(title, args, component, method, jsData, preSets, ptrEnabled); | ||||
|             this.jsData.refreshContent = showSpinner => this.refreshContent(showSpinner); | ||||
|             this.jsData.updateContent = (args, component, method, jsData, preSets) => | ||||
|                 this.updateContent(args, component, method, jsData, preSets); | ||||
|             this.jsData.updateModuleCourseContent = (cmId, alreadyFetched) => this.updateModuleCourseContent(cmId, alreadyFetched); | ||||
| 
 | ||||
|             this.onContentLoaded.emit({ refresh: !!refresh, success: true }); | ||||
|         } catch (error) { | ||||
|  | ||||
| @ -362,7 +362,7 @@ export class CoreSitePluginsHelperProvider { | ||||
|             plugin.parsedHandlers = CoreTextUtils.parseJSON( | ||||
|                 plugin.handlers, | ||||
|                 null, | ||||
|                 this.logger.error.bind(this.logger, 'Error parsing site plugin handlers'), | ||||
|                 error => this.logger.error('Error parsing site plugin handlers', error), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
| @ -370,7 +370,7 @@ export class CoreSitePluginsHelperProvider { | ||||
|             plugin.parsedLang = CoreTextUtils.parseJSON( | ||||
|                 plugin.lang, | ||||
|                 null, | ||||
|                 this.logger.error.bind(this.logger, 'Error parsing site plugin lang'), | ||||
|                 error => this.logger.error('Error parsing site plugin lang', error), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -468,7 +468,7 @@ export class CoreSitePluginsProvider { | ||||
|             plugin.parsedHandlers = CoreTextUtils.parseJSON( | ||||
|                 plugin.handlers, | ||||
|                 null, | ||||
|                 this.logger.error.bind(this.logger, 'Error parsing site plugin handlers'), | ||||
|                 error => this.logger.error('Error parsing site plugin handlers', error), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -19,8 +19,7 @@ import { | ||||
|     CoreCourseOptionsHandler, | ||||
|     CoreCourseOptionsHandlerData, | ||||
| } from '@features/course/services/course-options-delegate'; | ||||
| import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; | ||||
| import { CoreCourseAnyCourseData, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; | ||||
| import { PARTICIPANTS_PAGE_NAME } from '@features/user/user.module'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { CoreUser } from '../user'; | ||||
| @ -35,11 +34,7 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand | ||||
|     priority = 600; | ||||
| 
 | ||||
|     /** | ||||
|      * Should invalidate the data to determine if the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param courseId The course ID. | ||||
|      * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @return Promise resolved when done. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise<void> { | ||||
|         if (navOptions && navOptions.participants !== undefined) { | ||||
| @ -51,21 +46,14 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the handler is enabled on a site level. | ||||
|      * | ||||
|      * @return Whether or not the handler is enabled on a site level. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     isEnabled(): Promise<boolean> { | ||||
|         return Promise.resolve(true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Whether or not the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param courseId The course ID. | ||||
|      * @param accessData Access type and data. Default, guest, ... | ||||
|      * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @return True or promise resolved with true if enabled. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     isEnabledForCourse( | ||||
|         courseId: number, | ||||
| @ -95,12 +83,9 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. | ||||
|      * | ||||
|      * @param course The course. | ||||
|      * @return Promise resolved when done. | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async prefetch(course: CoreEnrolledCourseDataWithExtraInfoAndOptions): Promise<void> { | ||||
|     async prefetch(course: CoreCourseAnyCourseData): Promise<void> { | ||||
|         let offset = 0; | ||||
|         let canLoadMore = true; | ||||
| 
 | ||||
|  | ||||
| @ -41,7 +41,7 @@ export class CoreUserSyncProvider extends CoreSyncBaseProvider<string[]> { | ||||
|      * @return Promise resolved with warnings if sync is successful, rejected if sync fails. | ||||
|      */ | ||||
|     syncPreferences(siteId?: string): Promise<void> { | ||||
|         return this.syncOnSites('all user preferences', this.syncSitePreferences.bind(this), siteId); | ||||
|         return this.syncOnSites('all user preferences', (siteId) => this.syncSitePreferences(siteId), siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -834,9 +834,9 @@ export class CoreFileProvider { | ||||
|             return this.copyOrMoveExternalFile(from, to, copy); | ||||
|         } | ||||
| 
 | ||||
|         const moveCopyFn: MoveCopyFunction = copy ? | ||||
|             (isDir ? File.copyDir.bind(File.instance) : File.copyFile.bind(File.instance)) : | ||||
|             (isDir ? File.moveDir.bind(File.instance) : File.moveFile.bind(File.instance)); | ||||
|         const moveCopyFn: MoveCopyFunction = (...args) => copy ? | ||||
|             (isDir ? File.copyDir(...args) : File.copyFile(...args)) : | ||||
|             (isDir ? File.moveDir(...args) : File.moveFile(...args)); | ||||
| 
 | ||||
|         await this.init(); | ||||
| 
 | ||||
| @ -854,14 +854,16 @@ export class CoreFileProvider { | ||||
|         try { | ||||
|             const entry = await moveCopyFn(this.basePath, from, this.basePath, to); | ||||
| 
 | ||||
|             return entry; | ||||
|             return <FileEntry | DirectoryEntry> entry; | ||||
|         } catch (error) { | ||||
|             // The copy can fail if the path has encoded characters. Try again if that's the case.
 | ||||
|             const decodedFrom = decodeURI(from); | ||||
|             const decodedTo = decodeURI(to); | ||||
| 
 | ||||
|             if (from != decodedFrom || to != decodedTo) { | ||||
|                 return moveCopyFn(this.basePath, decodedFrom, this.basePath, decodedTo); | ||||
|                 const entry = await moveCopyFn(this.basePath, decodedFrom, this.basePath, decodedTo); | ||||
| 
 | ||||
|                 return <FileEntry | DirectoryEntry> entry; | ||||
|             } else { | ||||
|                 return Promise.reject(error); | ||||
|             } | ||||
| @ -1307,4 +1309,4 @@ export class CoreFileProvider { | ||||
| 
 | ||||
| export const CoreFile = makeSingleton(CoreFileProvider); | ||||
| 
 | ||||
| type MoveCopyFunction = (path: string, dirName: string, newPath: string, newDirName: string) => Promise<FileEntry | DirectoryEntry>; | ||||
| type MoveCopyFunction = (path: string, name: string, newPath: string, newName: string) => Promise<Entry>; | ||||
|  | ||||
| @ -293,7 +293,7 @@ export class CoreLangProvider { | ||||
|      * @return Translated month names. | ||||
|      */ | ||||
|     getMonthNames(): string[] { | ||||
|         return moment.months().map(this.capitalize.bind(this)); | ||||
|         return moment.months().map(month => this.capitalize(month)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -302,7 +302,7 @@ export class CoreLangProvider { | ||||
|      * @return Translated month short names. | ||||
|      */ | ||||
|     getMonthShortNames(): string[] { | ||||
|         return moment.monthsShort().map(this.capitalize.bind(this)); | ||||
|         return moment.monthsShort().map(month => this.capitalize(month)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -311,7 +311,7 @@ export class CoreLangProvider { | ||||
|      * @return Translated day names. | ||||
|      */ | ||||
|     getDayNames(): string[] { | ||||
|         return moment.weekdays().map(this.capitalize.bind(this)); | ||||
|         return moment.weekdays().map(weekDay => this.capitalize(weekDay)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -320,7 +320,7 @@ export class CoreLangProvider { | ||||
|      * @return Translated day short names. | ||||
|      */ | ||||
|     getDayShortNames(): string[] { | ||||
|         return moment.weekdaysShort().map(this.capitalize.bind(this)); | ||||
|         return moment.weekdaysShort().map(weekDay => this.capitalize(weekDay)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -74,7 +74,7 @@ export class CoreScreenService { | ||||
|         }), {} as Record<Breakpoint, boolean>)); | ||||
| 
 | ||||
|         this._layoutObservable = this.breakpointsObservable.pipe( | ||||
|             map(this.calculateLayout.bind(this)), | ||||
|             map(breakpoints => this.calculateLayout(breakpoints)), | ||||
|             distinctUntilChanged<CoreScreenLayout>(), | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @ -398,7 +398,7 @@ export class CoreIframeUtilsProvider { | ||||
| 
 | ||||
|             // Add click listener to the link, this way if the iframe has added a listener to the link it will be executed first.
 | ||||
|             link.treated = true; | ||||
|             link.addEventListener('click', this.linkClicked.bind(this, link, element)); | ||||
|             link.addEventListener('click', event => this.linkClicked(link, element, event)); | ||||
|         }, { | ||||
|             capture: true, // Use capture to fix this listener not called if the element clicked is too deep in the DOM.
 | ||||
|         }); | ||||
| @ -468,7 +468,7 @@ export class CoreIframeUtilsProvider { | ||||
|      */ | ||||
|     protected async linkClicked( | ||||
|         link: CoreIframeHTMLAnchorElement | {href: string; target?: string; originalHref?: string}, | ||||
|         element?: HTMLFrameElement | HTMLObjectElement, | ||||
|         element?: CoreFrameElement, | ||||
|         event?: Event, | ||||
|     ): Promise<void> { | ||||
|         if (event && event.defaultPrevented) { | ||||
| @ -554,7 +554,7 @@ export class CoreIframeUtilsProvider { | ||||
|         userScriptWindow.WKUserScript?.addScript({ id: 'CoreIframeUtilsLinksScript', file: linksPath }); | ||||
| 
 | ||||
|         // Handle post messages received by iframes.
 | ||||
|         window.addEventListener('message', this.handleIframeMessage.bind(this)); | ||||
|         window.addEventListener('message', (event) => this.handleIframeMessage(event)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -488,7 +488,7 @@ export class CoreUtilsProvider { | ||||
|      */ | ||||
|     async filterEnabledSites<P extends unknown[]>( | ||||
|         siteIds: string[], | ||||
|         isEnabledFn: (siteId, ...args: P) => boolean | Promise<boolean>, | ||||
|         isEnabledFn: (siteId: string, ...args: P) => boolean | Promise<boolean>, | ||||
|         checkAll?: boolean, | ||||
|         ...args: P | ||||
|     ): Promise<string[]> { | ||||
|  | ||||
| @ -908,7 +908,7 @@ export class CoreWSProvider { | ||||
|         const data = CoreTextUtils.parseJSON<any>( | ||||
|             success.response, | ||||
|             null, | ||||
|             this.logger.error.bind(this.logger, 'Error parsing response from upload', success.response), | ||||
|             error => this.logger.error('Error parsing response from upload', success.response, error), | ||||
|         ); | ||||
| 
 | ||||
|         if (data === null) { | ||||
|  | ||||
| @ -86,15 +86,15 @@ export class CoreLogger { | ||||
| 
 | ||||
|         return new CoreLogger( | ||||
|             // eslint-disable-next-line no-console
 | ||||
|             CoreLogger.prepareLogFn(console.log.bind(console), className), | ||||
|             CoreLogger.prepareLogFn((...data) => console.log(...data), className), | ||||
|             // eslint-disable-next-line no-console
 | ||||
|             CoreLogger.prepareLogFn(console.info.bind(console), className), | ||||
|             CoreLogger.prepareLogFn((...data) => console.info(...data), className), | ||||
|             // eslint-disable-next-line no-console
 | ||||
|             CoreLogger.prepareLogFn(console.warn.bind(console), className), | ||||
|             CoreLogger.prepareLogFn((...data) => console.warn(...data), className), | ||||
|             // eslint-disable-next-line no-console
 | ||||
|             CoreLogger.prepareLogFn(console.debug.bind(console), className), | ||||
|             CoreLogger.prepareLogFn((...data) => console.debug(...data), className), | ||||
|             // eslint-disable-next-line no-console
 | ||||
|             CoreLogger.prepareLogFn(console.error.bind(console), className), | ||||
|             CoreLogger.prepareLogFn((...data) => console.error(...data), className), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user