From c5a0c8c6ea71aa7122ce098cedab0694d61b1988 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 6 Apr 2020 14:45:03 +0200 Subject: [PATCH 001/166] MOBILE-3389 lang: Add missing lang strings to langindex --- scripts/langindex.json | 13 ++++++++++++- src/assets/lang/en.json | 12 ++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index b8e6572af..212d23e5c 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1707,7 +1707,17 @@ "core.login.emailnotmatch": "local_moodlemobileapp", "core.login.erroraccesscontrolalloworigin": "local_moodlemobileapp", "core.login.errordeletesite": "local_moodlemobileapp", + "core.login.errorexampleurl": "local_moodlemobileapp", "core.login.errorupdatesite": "local_moodlemobileapp", + "core.login.faqcannotconnectanswer": "local_moodlemobileapp", + "core.login.faqcannotconnectquestion": "local_moodlemobileapp", + "core.login.faqsetupsiteanswer": "local_moodlemobileapp", + "core.login.faqsetupsitelinktitle": "local_moodlemobileapp", + "core.login.faqsetupsitequestion": "local_moodlemobileapp", + "core.login.faqtestappanswer": "local_moodlemobileapp", + "core.login.faqtestappquestion": "local_moodlemobileapp", + "core.login.faqwhatisurlanswer": "local_moodlemobileapp", + "core.login.faqwhatisurlquestion": "local_moodlemobileapp", "core.login.findyoursite": "local_moodlemobileapp", "core.login.firsttime": "moodle", "core.login.forcepasswordchangenotice": "moodle", @@ -1736,7 +1746,6 @@ "core.login.mobileservicesnotenabled": "local_moodlemobileapp", "core.login.mustconfirm": "moodle", "core.login.newaccount": "moodle", - "core.login.newsitedescription": "local_moodlemobileapp", "core.login.notloggedin": "local_moodlemobileapp", "core.login.password": "moodle", "core.login.passwordforgotten": "moodle", @@ -1816,6 +1825,7 @@ "core.more": "moodle", "core.mygroups": "group", "core.name": "moodle", + "core.needhelp": "local_moodlemobileapp", "core.networkerroriframemsg": "local_moodlemobileapp", "core.networkerrormsg": "local_moodlemobileapp", "core.never": "moodle", @@ -2090,6 +2100,7 @@ "core.warningofflinedatadeleted": "local_moodlemobileapp", "core.whatisyourage": "moodle", "core.wheredoyoulive": "moodle", + "core.whoissiteadmin": "local_moodlemobileapp", "core.whoops": "local_moodlemobileapp", "core.whyisthishappening": "local_moodlemobileapp", "core.whyisthisrequired": "moodle", diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index d9af5a22e..3561e6111 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1707,7 +1707,17 @@ "core.login.emailnotmatch": "Emails do not match", "core.login.erroraccesscontrolalloworigin": "The cross-origin call you're trying to perform has been rejected. Please check https://docs.moodle.org/dev/Moodle_Mobile_development_using_Chrome_or_Chromium", "core.login.errordeletesite": "An error occurred while deleting this site. Please try again.", + "core.login.errorexampleurl": "The URL https://campus.example.edu is only an example URL, it's not a real site. Please use the URL of your school or organization's site.", "core.login.errorupdatesite": "An error occurred while updating the site's token.", + "core.login.faqcannotconnectanswer": "Please, contact your site administrator.", + "core.login.faqcannotconnectquestion": "I typed my site address correctly but I still can't connect.", + "core.login.faqsetupsiteanswer": "Visit {{$link}} to check out the different options you have to create your own Moodle site.", + "core.login.faqsetupsitelinktitle": "Get started.", + "core.login.faqsetupsitequestion": "I want to set up my own Moodle site.", + "core.login.faqtestappanswer": "To test the app in a Moodle Demo Site, type \"teacher\" or \"student\" in the \"Your site address\" field and click the \"Connect!\" button.", + "core.login.faqtestappquestion": "I just want to test the app, what can I do?", + "core.login.faqwhatisurlanswer": "

Every organisation or school has their own custom address for their Moodle site.

To find the address of the Moodle site you want to connect to, do the following:

  1. Open a web browser and go to your school's or organisation's Moodle site login page
  2. At the top of the page, on the address bar, you will see the URL of your Moodle site. E.g. \"campus.example.edu\".{{$image}}
  3. Copy the address (do not copy the /login and what comes after), paste it into the Moodle App and click \"Connect!\"
  4. Now you can log into your site, using your username and password
  5. ", + "core.login.faqwhatisurlquestion": "What is the URL of my Moodle site? How can I find my school’s site?", "core.login.findyoursite": "Find your site", "core.login.firsttime": "Is this your first time here?", "core.login.forcepasswordchangenotice": "You must change your password to proceed.", @@ -1815,6 +1825,7 @@ "core.more": "more", "core.mygroups": "My groups", "core.name": "Name", + "core.needhelp": "Need help?", "core.networkerroriframemsg": "This content is not available offline. Please connect to the internet and try again.", "core.networkerrormsg": "There was a problem connecting to the site. Please check your connection and try again.", "core.never": "Never", @@ -2089,6 +2100,7 @@ "core.warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}", "core.whatisyourage": "What is your age?", "core.wheredoyoulive": "In which country do you live?", + "core.whoissiteadmin": "\"Site Administrators\" are the people who manage the Moodle at your school/university/company or learning organisation. If you don't know how to contact them, please contact your teachers/trainers.", "core.whoops": "Oops!", "core.whyisthishappening": "Why is this happening?", "core.whyisthisrequired": "Why is this required?", From 5395ef18f14c1bde78b979a87406458a66119a15 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 8 Apr 2020 12:26:43 +0200 Subject: [PATCH 002/166] MOBILE-3390 database: Support URL force name and autolink --- .../component/addon-mod-data-field-url.html | 5 ++- .../mod/data/fields/url/component/url.ts | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/addon/mod/data/fields/url/component/addon-mod-data-field-url.html b/src/addon/mod/data/fields/url/component/addon-mod-data-field-url.html index 90283fe72..7d2c37bec 100644 --- a/src/addon/mod/data/fields/url/component/addon-mod-data-field-url.html +++ b/src/addon/mod/data/fields/url/component/addon-mod-data-field-url.html @@ -4,4 +4,7 @@ -{{value.content}} \ No newline at end of file + + {{ displayValue }} + {{ displayValue }} + \ No newline at end of file diff --git a/src/addon/mod/data/fields/url/component/url.ts b/src/addon/mod/data/fields/url/component/url.ts index 14dd7f62b..175f12096 100644 --- a/src/addon/mod/data/fields/url/component/url.ts +++ b/src/addon/mod/data/fields/url/component/url.ts @@ -24,6 +24,9 @@ import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin- }) export class AddonModDataFieldUrlComponent extends AddonModDataFieldPluginComponent { + protected autoLink = false; + protected displayValue = ''; + constructor(protected fb: FormBuilder) { super(fb); } @@ -43,4 +46,36 @@ export class AddonModDataFieldUrlComponent extends AddonModDataFieldPluginCompon this.addControl('f_' + this.field.id, value); } + + /** + * Calculate data for show or list mode. + */ + protected calculateShowListData(): void { + if (!this.value || !this.value.content) { + return; + } + + const url = this.value.content; + const text = this.field.param2 || this.value.content1; // Param2 forces the text to display. + + this.autoLink = parseInt(this.field.param1, 10) === 1; + + if (this.autoLink) { + this.displayValue = text || url; + } else { + // No auto link, always display the URL. + this.displayValue = url; + } + } + + /** + * Update value being shown. + */ + protected updateValue(value: any): void { + super.updateValue(value); + + if (this.isShowOrListMode()) { + this.calculateShowListData(); + } + } } From df79abe1e83439edc953286537c740c3ba5d4d06 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Phuc Date: Wed, 8 Apr 2020 19:02:54 +0700 Subject: [PATCH 003/166] MOBILE-3134 Site add-ons: Update context menu when file is downloaded --- src/core/constants.ts | 6 + .../course/classes/main-resource-component.ts | 2 + src/core/course/providers/helper.ts | 12 ++ src/providers/filepool.ts | 154 +++++++++++++----- 4 files changed, 134 insertions(+), 40 deletions(-) diff --git a/src/core/constants.ts b/src/core/constants.ts index c9784ccc3..4c4d55357 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -68,6 +68,12 @@ export class CoreConstants { static OUTDATED = 'outdated'; static NOT_DOWNLOADABLE = 'notdownloadable'; + // File status constants. + static FILE_DOWNLOAD = 'download'; + static FILE_DOWNLOADING = 'downloading'; + static FILE_DELETED = 'deleted'; + static FILE_OUTDATE = 'outdated'; + // Constants from Moodle's resourcelib. static RESOURCELIB_DISPLAY_AUTO = 0; // Try the best way. static RESOURCELIB_DISPLAY_EMBED = 1; // Display using object tag. diff --git a/src/core/course/classes/main-resource-component.ts b/src/core/course/classes/main-resource-component.ts index 50f432894..e568fec05 100644 --- a/src/core/course/classes/main-resource-component.ts +++ b/src/core/course/classes/main-resource-component.ts @@ -49,6 +49,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, protected isDestroyed; // Whether the component is destroyed, used when calling fillContextMenu. protected contextMenuStatusObserver; // Observer of package status changed, used when calling fillContextMenu. + protected contextFileStatusObserver; // Observer of file status changed, used when calling fillContextMenu. protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents. protected isCurrentView: boolean; // Whether the component is in the current view. @@ -285,6 +286,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, ngOnDestroy(): void { this.isDestroyed = true; this.contextMenuStatusObserver && this.contextMenuStatusObserver.off(); + this.contextFileStatusObserver && this.contextFileStatusObserver.off(); } /** diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 7fbc8b740..8309ab106 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -827,6 +827,18 @@ export class CoreCourseHelperProvider { } }, this.sitesProvider.getCurrentSiteId()); } + + if (typeof instance.contextFileStatusObserver == 'undefined' && component) { + const componentFileChangeStatusEvent = CoreFilepoolProvider.getComponentEventName( + this.sitesProvider.getCurrentSiteId(), component, module.id); + instance.contextFileStatusObserver = this.eventsProvider.on(componentFileChangeStatusEvent, (data) => { + if (((data.action == CoreConstants.FILE_DOWNLOAD && data.success == true) || + data.action == CoreConstants.FILE_DELETED) && + moduleInfo.status != CoreConstants.DOWNLOADING) { + this.fillContextMenu(instance, module, courseId, true, component); + } + }, this.sitesProvider.getCurrentSiteId()); + } }); } diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index a4faa08f3..6e8385969 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -596,7 +596,7 @@ export class CoreFilepoolProvider { // Check if the queue is running. this.checkQueueProcessing(); - this.notifyFileDownloading(siteId, fileId); + this.notifyFileDownloading(siteId, fileId, link ? [link] : []); return this.getQueuePromise(siteId, fileId, true, onProgress); } @@ -877,6 +877,17 @@ export class CoreFilepoolProvider { }); } + /** + * Prepare links from component and componentId. + * + * @param component The component to link the file to. + * @param componentId An ID to use in conjunction with the component. + * @return Resolved means yes, rejected means no. + */ + createFileLinks(component: string, componentId: string | number): any[] { + return [{ component: component, componentId: this.fixComponentId(componentId) }]; + } + /** * Given the current status of a list of packages and the status of one of the packages, * determine the new status for the list of packages. The status of a list of packages is: @@ -1197,14 +1208,14 @@ export class CoreFilepoolProvider { if (typeof fileObject === 'undefined') { // We do not have the file, download and add to pool. - this.notifyFileDownloading(siteId, fileId); + this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); } else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) && this.appProvider.isOnline() && !ignoreStale) { // The file is outdated, force the download and update it. - this.notifyFileDownloading(siteId, fileId); + this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); } @@ -1220,14 +1231,14 @@ export class CoreFilepoolProvider { return response; }, () => { // The file was not found in the pool, weird. - this.notifyFileDownloading(siteId, fileId); + this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); }); }, () => { // The file is not in the pool just yet. - this.notifyFileDownloading(siteId, fileId); + this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); }).then((response) => { @@ -1236,11 +1247,11 @@ export class CoreFilepoolProvider { // Ignore errors. }); } - this.notifyFileDownloaded(siteId, fileId); + this.notifyFileDownloaded(siteId, fileId, this.createFileLinks(component, componentId)); return response; }, (err) => { - this.notifyFileDownloadError(siteId, fileId); + this.notifyFileDownloadError(siteId, fileId, this.createFileLinks(component, componentId)); return Promise.reject(err); }); @@ -1393,6 +1404,18 @@ export class CoreFilepoolProvider { }); } + /** + * Get the name of the event used to notify file status to component (CoreEventsProvider). + * + * @param siteId The site ID. + * @param component The component name. + * @param componentId The component ID. + * @return Event name. + */ + static getComponentEventName(siteId: string, component: string, componentId: string | number): string { + return 'ComponentEventFileChangeStatus:' + siteId + ':' + component + ':' + componentId; + } + /** * Convenience function to get component files. * @@ -2439,14 +2462,35 @@ export class CoreFilepoolProvider { return !!entry.isexternalfile || (entry.revision < 1 && !entry.timemodified); } + /** + * Notify a file has been changed status to Component. + * + * @param siteId The site ID. + * @param fileId The file ID. + * @param fileStatus The file status after changed + * @param links The links to the Components + */ + protected notifyFileStatusToComponents(siteId: string, fileId: string, fileStatus: any, links: any[]): void { + fileStatus.fileId = fileId; + links.forEach((link) => { + this.eventsProvider.trigger(CoreFilepoolProvider.getComponentEventName(siteId, link.component, link.componentId), + fileStatus, siteId); + }); + } + /** * Notify a file has been deleted. * * @param siteId The site ID. * @param fileId The file ID. + * @param links The links to components. */ - protected notifyFileDeleted(siteId: string, fileId: string): void { - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'deleted' }); + protected notifyFileDeleted(siteId: string, fileId: string, links: any[]): void { + const fileStatus = { + action: CoreConstants.FILE_DELETED + }; + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); + this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); } /** @@ -2454,9 +2498,15 @@ export class CoreFilepoolProvider { * * @param siteId The site ID. * @param fileId The file ID. + * @param links The links to components. */ - protected notifyFileDownloaded(siteId: string, fileId: string): void { - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: true }); + protected notifyFileDownloaded(siteId: string, fileId: string, links: any[]): void { + const fileStatus = { + action: CoreConstants.FILE_DOWNLOAD, + success: true + }; + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); + this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); } /** @@ -2464,9 +2514,15 @@ export class CoreFilepoolProvider { * * @param siteId The site ID. * @param fileId The file ID. + * @param links The links to components. */ - protected notifyFileDownloadError(siteId: string, fileId: string): void { - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: false }); + protected notifyFileDownloadError(siteId: string, fileId: string, links: any[]): void { + const fileStatus = { + action: CoreConstants.FILE_DOWNLOAD, + success: false + }; + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); + this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); } /** @@ -2474,9 +2530,15 @@ export class CoreFilepoolProvider { * * @param siteId The site ID. * @param fileId The file ID. + * @param links The links to components. */ - protected notifyFileDownloading(siteId: string, fileId: string): void { - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'downloading' }); + protected notifyFileDownloading(siteId: string, fileId: string, links: any[]): void { + const fileStatus = { + action: CoreConstants.FILE_DOWNLOADING + }; + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); + this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + } /** @@ -2484,9 +2546,14 @@ export class CoreFilepoolProvider { * * @param siteId The site ID. * @param fileId The file ID. + * @param links The links to components. */ - protected notifyFileOutdated(siteId: string, fileId: string): void { - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'outdated' }); + protected notifyFileOutdated(siteId: string, fileId: string, links: any[]): void { + const fileStatus = { + action: CoreConstants.FILE_OUTDATE + }; + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); + this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); } /** @@ -2612,7 +2679,7 @@ export class CoreFilepoolProvider { }).finally(() => { this.treatQueueDeferred(siteId, fileId, true); }); - this.notifyFileDownloaded(siteId, fileId); + this.notifyFileDownloaded(siteId, fileId, links); return; } @@ -2627,7 +2694,7 @@ export class CoreFilepoolProvider { }); this.treatQueueDeferred(siteId, fileId, true); - this.notifyFileDownloaded(siteId, fileId); + this.notifyFileDownloaded(siteId, fileId, links); // Wait for the item to be removed from queue before resolving the promise. // If the item could not be removed from queue we still resolve the promise. @@ -2677,12 +2744,12 @@ export class CoreFilepoolProvider { // Consider this as a silent error, never reject the promise here. }).then(() => { this.treatQueueDeferred(siteId, fileId, false, errorMessage); - this.notifyFileDownloadError(siteId, fileId); + this.notifyFileDownloadError(siteId, fileId, links); }); } else { // We considered the file as legit but did not get it, failure. this.treatQueueDeferred(siteId, fileId, false, errorMessage); - this.notifyFileDownloadError(siteId, fileId); + this.notifyFileDownloadError(siteId, fileId, links); return Promise.reject(errorObject); } @@ -2730,30 +2797,37 @@ export class CoreFilepoolProvider { // If file not found, use the path without extension. return path; }).then((path) => { - const promises = []; + const conditions = { + fileId: fileId + }; - // Remove entry from filepool store. - promises.push(db.deleteRecords(this.FILES_TABLE, { fileId: fileId })); + // Get links to components to notify to them before remove. + return db.getRecords(this.LINKS_TABLE, conditions).then((links) => { + const promises = []; - // Remove links. - promises.push(db.deleteRecords(this.LINKS_TABLE, { fileId: fileId })); + // Remove entry from filepool store. + promises.push(db.deleteRecords(this.FILES_TABLE, conditions)); - // Remove the file. - if (this.fileProvider.isAvailable()) { - promises.push(this.fileProvider.removeFile(path).catch((error) => { - if (error && error.code == 1) { - // Not found, ignore error since maybe it was deleted already. - } else { - return Promise.reject(error); - } - })); - } + // Remove links. + promises.push(db.deleteRecords(this.LINKS_TABLE, conditions)); - return Promise.all(promises).then(() => { - this.notifyFileDeleted(siteId, fileId); + // Remove the file. + if (this.fileProvider.isAvailable()) { + promises.push(this.fileProvider.removeFile(path).catch((error) => { + if (error && error.code == 1) { + // Not found, ignore error since maybe it was deleted already. + } else { + return Promise.reject(error); + } + })); + } - return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => { - // Ignore errors. + return Promise.all(promises).then(() => { + this.notifyFileDeleted(siteId, fileId, links); + + return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => { + // Ignore errors. + }); }); }); }); From 8c38f3a2166e2929905f059106beff2624a1a90d Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 9 Apr 2020 08:59:39 +0200 Subject: [PATCH 004/166] MOBILE-3134 filepool: Fix issues when handling componentId --- src/core/constants.ts | 8 +- src/core/course/providers/helper.ts | 17 +-- src/providers/filepool.ts | 166 ++++++++++++++++++---------- 3 files changed, 122 insertions(+), 69 deletions(-) diff --git a/src/core/constants.ts b/src/core/constants.ts index 4c4d55357..f498ff8a9 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -69,10 +69,10 @@ export class CoreConstants { static NOT_DOWNLOADABLE = 'notdownloadable'; // File status constants. - static FILE_DOWNLOAD = 'download'; - static FILE_DOWNLOADING = 'downloading'; - static FILE_DELETED = 'deleted'; - static FILE_OUTDATE = 'outdated'; + static FILE_ACTION_DOWNLOAD = 'download'; + static FILE_ACTION_DOWNLOADING = 'downloading'; + static FILE_ACTION_DELETED = 'deleted'; + static FILE_ACTION_OUTDATED = 'outdated'; // Constants from Moodle's resourcelib. static RESOURCELIB_DISPLAY_AUTO = 0; // Try the best way. diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 8309ab106..c2b34853f 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -800,6 +800,8 @@ export class CoreCourseHelperProvider { * @return Promise resolved when done. */ fillContextMenu(instance: any, module: any, courseId: number, invalidateCache?: boolean, component?: string): Promise { + const siteId = this.sitesProvider.getCurrentSiteId(); + return this.getModulePrefetchInfo(module, courseId, invalidateCache, component).then((moduleInfo) => { instance.size = moduleInfo.size > 0 ? moduleInfo.sizeReadable : 0; instance.prefetchStatusIcon = moduleInfo.statusIcon; @@ -825,19 +827,20 @@ export class CoreCourseHelperProvider { if (data.componentId == module.id && data.component == component) { this.fillContextMenu(instance, module, courseId, false, component); } - }, this.sitesProvider.getCurrentSiteId()); + }, siteId); } if (typeof instance.contextFileStatusObserver == 'undefined' && component) { - const componentFileChangeStatusEvent = CoreFilepoolProvider.getComponentEventName( - this.sitesProvider.getCurrentSiteId(), component, module.id); + const componentFileChangeStatusEvent = CoreFilepoolProvider.getComponentEventName(siteId, component, module.id); + instance.contextFileStatusObserver = this.eventsProvider.on(componentFileChangeStatusEvent, (data) => { - if (((data.action == CoreConstants.FILE_DOWNLOAD && data.success == true) || - data.action == CoreConstants.FILE_DELETED) && - moduleInfo.status != CoreConstants.DOWNLOADING) { + + if (((data.action == CoreConstants.FILE_ACTION_DOWNLOAD && data.success == true) || + data.action == CoreConstants.FILE_ACTION_DELETED) && + instance.prefetchStatus != CoreConstants.DOWNLOADING) { this.fillContextMenu(instance, module, courseId, true, component); } - }, this.sitesProvider.getCurrentSiteId()); + }, siteId); } }); } diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index 6e8385969..6235c973a 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -144,7 +144,7 @@ export interface CoreFilepoolQueueEntry { /** * File links (to link the file to components and componentIds). */ - links?: any[]; + links?: CoreFilepoolComponentLink[]; } /** @@ -197,6 +197,21 @@ export interface CoreFilepoolPackageEntry { extra?: string; } +/** + * A component link. + */ +export interface CoreFilepoolComponentLink { + /** + * Link's component. + */ + component: string; + + /** + * Link's componentId. + */ + componentId?: string | number; +} + /* * Factory for handling downloading files and retrieve downloaded files. * @@ -495,7 +510,7 @@ export class CoreFilepoolProvider { * @param links Array of objects containing the component and optionally componentId. * @return Promise resolved on success. */ - protected addFileLinks(siteId: string, fileId: string, links: any[]): Promise { + protected addFileLinks(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): Promise { const promises = []; links.forEach((link) => { promises.push(this.addFileLink(siteId, fileId, link.component, link.componentId)); @@ -575,7 +590,9 @@ export class CoreFilepoolProvider { * @return Promise resolved when the file is downloaded. */ protected async addToQueue(siteId: string, fileId: string, url: string, priority: number, revision: number, - timemodified: number, filePath: string, onProgress?: (event: any) => any, options: any = {}, link?: any): Promise { + timemodified: number, filePath: string, onProgress?: (event: any) => any, options: any = {}, + link?: CoreFilepoolComponentLink): Promise { + await this.dbReady; this.logger.debug(`Adding ${fileId} to the queue`); @@ -623,7 +640,6 @@ export class CoreFilepoolProvider { await this.dbReady; let fileId, - link, queueDeferred; if (!this.fileProvider.isAvailable()) { @@ -651,12 +667,7 @@ export class CoreFilepoolProvider { const primaryKey = { siteId: siteId, fileId: fileId }; // Set up the component. - if (typeof component != 'undefined') { - link = { - component: component, - componentId: this.fixComponentId(componentId) - }; - } + const link = this.createComponentLink(component, componentId); // Retrieve the queue deferred now if it exists. // This is to prevent errors if file is removed from queue while we're checking if the file is in queue. @@ -866,7 +877,7 @@ export class CoreFilepoolProvider { return this.sitesProvider.getSiteDb(siteId).then((db) => { const conditions = { component: component, - componentId: componentId || '' + componentId: this.fixComponentId(componentId) }; return db.countRecords(this.LINKS_TABLE, conditions).then((count) => { @@ -878,14 +889,31 @@ export class CoreFilepoolProvider { } /** - * Prepare links from component and componentId. + * Prepare a component link. * * @param component The component to link the file to. * @param componentId An ID to use in conjunction with the component. - * @return Resolved means yes, rejected means no. + * @return Link, null if nothing to link. */ - createFileLinks(component: string, componentId: string | number): any[] { - return [{ component: component, componentId: this.fixComponentId(componentId) }]; + protected createComponentLink(component: string, componentId?: string | number): CoreFilepoolComponentLink { + if (typeof component != 'undefined' && component != null) { + return { component: component, componentId: this.fixComponentId(componentId) }; + } + + return null; + } + + /** + * Prepare list of links from component and componentId. + * + * @param component The component to link the file to. + * @param componentId An ID to use in conjunction with the component. + * @return Links. + */ + protected createComponentLinks(component: string, componentId?: string | number): CoreFilepoolComponentLink[] { + const link = this.createComponentLink(component, componentId); + + return link ? [link] : []; } /** @@ -1204,18 +1232,20 @@ export class CoreFilepoolProvider { options.revision = revision || this.getRevisionFromUrl(fileUrl); fileId = this.getFileIdByUrl(fileUrl); + const links = this.createComponentLinks(component, componentId); + return this.hasFileInPool(siteId, fileId).then((fileObject) => { if (typeof fileObject === 'undefined') { // We do not have the file, download and add to pool. - this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloading(siteId, fileId, links); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); } else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) && this.appProvider.isOnline() && !ignoreStale) { // The file is outdated, force the download and update it. - this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloading(siteId, fileId, links); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); } @@ -1231,14 +1261,14 @@ export class CoreFilepoolProvider { return response; }, () => { // The file was not found in the pool, weird. - this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloading(siteId, fileId, links); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); }); }, () => { // The file is not in the pool just yet. - this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloading(siteId, fileId, links); return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); }).then((response) => { @@ -1247,11 +1277,11 @@ export class CoreFilepoolProvider { // Ignore errors. }); } - this.notifyFileDownloaded(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloaded(siteId, fileId, links); return response; }, (err) => { - this.notifyFileDownloadError(siteId, fileId, this.createFileLinks(component, componentId)); + this.notifyFileDownloadError(siteId, fileId, links); return Promise.reject(err); }); @@ -1413,7 +1443,7 @@ export class CoreFilepoolProvider { * @return Event name. */ static getComponentEventName(siteId: string, component: string, componentId: string | number): string { - return 'ComponentEventFileChangeStatus:' + siteId + ':' + component + ':' + componentId; + return 'CoreFilepoolComponentFile:' + siteId + ':' + component + ':' + componentId; } /** @@ -1427,10 +1457,16 @@ export class CoreFilepoolProvider { protected getComponentFiles(db: SQLiteDB, component: string, componentId?: string | number): Promise { const conditions = { component: component, - componentId: componentId || '' + componentId: this.fixComponentId(componentId) }; - return db.getRecords(this.LINKS_TABLE, conditions); + return db.getRecords(this.LINKS_TABLE, conditions).then((items) => { + items.forEach((item) => { + item.componentId = this.fixComponentId(item.componentId); + }); + + return items; + }); } /** @@ -1539,6 +1575,12 @@ export class CoreFilepoolProvider { protected getFileLinks(siteId: string, fileId: string): Promise { return this.sitesProvider.getSiteDb(siteId).then((db) => { return db.getRecords(this.LINKS_TABLE, { fileId: fileId }); + }).then((items) => { + items.forEach((item) => { + item.componentId = this.fixComponentId(item.componentId); + }); + + return items; }); } @@ -2463,18 +2505,17 @@ export class CoreFilepoolProvider { } /** - * Notify a file has been changed status to Component. + * Notify an action performed on a file to a list of components. * * @param siteId The site ID. - * @param fileId The file ID. - * @param fileStatus The file status after changed - * @param links The links to the Components + * @param eventData The event data. + * @param links The links to the components. */ - protected notifyFileStatusToComponents(siteId: string, fileId: string, fileStatus: any, links: any[]): void { - fileStatus.fileId = fileId; + protected notifyFileActionToComponents(siteId: string, eventData: any, links: CoreFilepoolComponentLink[]): void { + links.forEach((link) => { this.eventsProvider.trigger(CoreFilepoolProvider.getComponentEventName(siteId, link.component, link.componentId), - fileStatus, siteId); + eventData, siteId); }); } @@ -2485,12 +2526,14 @@ export class CoreFilepoolProvider { * @param fileId The file ID. * @param links The links to components. */ - protected notifyFileDeleted(siteId: string, fileId: string, links: any[]): void { - const fileStatus = { - action: CoreConstants.FILE_DELETED + protected notifyFileDeleted(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { + const data = { + fileId: fileId, + action: CoreConstants.FILE_ACTION_DELETED }; - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); - this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); + this.notifyFileActionToComponents(siteId, data, links); } /** @@ -2500,13 +2543,15 @@ export class CoreFilepoolProvider { * @param fileId The file ID. * @param links The links to components. */ - protected notifyFileDownloaded(siteId: string, fileId: string, links: any[]): void { - const fileStatus = { - action: CoreConstants.FILE_DOWNLOAD, + protected notifyFileDownloaded(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { + const data = { + fileId: fileId, + action: CoreConstants.FILE_ACTION_DOWNLOAD, success: true }; - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); - this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); + this.notifyFileActionToComponents(siteId, data, links); } /** @@ -2516,13 +2561,15 @@ export class CoreFilepoolProvider { * @param fileId The file ID. * @param links The links to components. */ - protected notifyFileDownloadError(siteId: string, fileId: string, links: any[]): void { - const fileStatus = { - action: CoreConstants.FILE_DOWNLOAD, + protected notifyFileDownloadError(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { + const data = { + fileId: fileId, + action: CoreConstants.FILE_ACTION_DOWNLOAD, success: false }; - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); - this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); + this.notifyFileActionToComponents(siteId, data, links); } /** @@ -2532,12 +2579,14 @@ export class CoreFilepoolProvider { * @param fileId The file ID. * @param links The links to components. */ - protected notifyFileDownloading(siteId: string, fileId: string, links: any[]): void { - const fileStatus = { - action: CoreConstants.FILE_DOWNLOADING + protected notifyFileDownloading(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { + const data = { + fileId: fileId, + action: CoreConstants.FILE_ACTION_DOWNLOADING }; - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); - this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); + this.notifyFileActionToComponents(siteId, data, links); } @@ -2548,12 +2597,13 @@ export class CoreFilepoolProvider { * @param fileId The file ID. * @param links The links to components. */ - protected notifyFileOutdated(siteId: string, fileId: string, links: any[]): void { - const fileStatus = { - action: CoreConstants.FILE_OUTDATE + protected notifyFileOutdated(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { + const data = { + action: CoreConstants.FILE_ACTION_OUTDATED }; - this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus); - this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links); + + this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); + this.notifyFileActionToComponents(siteId, data, links); } /** @@ -2801,8 +2851,8 @@ export class CoreFilepoolProvider { fileId: fileId }; - // Get links to components to notify to them before remove. - return db.getRecords(this.LINKS_TABLE, conditions).then((links) => { + // Get links to components to notify them after remove. + return this.getFileLinks(siteId, fileId).then((links) => { const promises = []; // Remove entry from filepool store. From 254107075b3c38451863f6fe07166ea15536b083 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 9 Apr 2020 10:29:00 +0200 Subject: [PATCH 005/166] MOBILE-3134 folder: Fix componentId and description in folder --- .../index/addon-mod-folder-index.html | 6 +-- .../mod/folder/components/index/index.ts | 40 ++++++++++--------- src/addon/mod/folder/pages/index/index.html | 4 +- src/addon/mod/folder/pages/index/index.ts | 8 ++-- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/addon/mod/folder/components/index/addon-mod-folder-index.html b/src/addon/mod/folder/components/index/addon-mod-folder-index.html index 03eb3838a..4627aaeba 100644 --- a/src/addon/mod/folder/components/index/addon-mod-folder-index.html +++ b/src/addon/mod/folder/components/index/addon-mod-folder-index.html @@ -4,7 +4,7 @@ - + @@ -17,11 +17,11 @@ - +

    {{file.name}}

    - +
    diff --git a/src/addon/mod/folder/components/index/index.ts b/src/addon/mod/folder/components/index/index.ts index 922ec3836..622acb449 100644 --- a/src/addon/mod/folder/components/index/index.ts +++ b/src/addon/mod/folder/components/index/index.ts @@ -29,7 +29,8 @@ import { AddonModFolderHelperProvider } from '../../providers/helper'; templateUrl: 'addon-mod-folder-index.html', }) export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceComponent { - @Input() path: string; // For subfolders. Use the path instead of a boolean so Angular detects them as different states. + @Input() folderInstance?: any; // The mod_folder instance. + @Input() subfolder?: any; // Subfolder to show. component = AddonModFolderProvider.COMPONENT; canGetFolder: boolean; @@ -48,9 +49,9 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo this.canGetFolder = this.folderProvider.isGetFolderWSAvailable(); - if (this.path) { + if (this.subfolder) { // Subfolder. Use module param. - this.showModuleData(this.module, this.module.contents); + this.showModuleData(this.subfolder.contents); this.loaded = true; this.refreshIcon = 'refresh'; } else { @@ -77,15 +78,14 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo } /** - * Convenience function to set scope data using module. - * @param module Module to show. + * Convenience function to set data to display. + * + * @param folderContents Contents to show. */ - protected showModuleData(module: any, folderContents: any): void { - this.description = module.intro || module.description; + protected showModuleData(folderContents: any): void { + this.description = this.folderInstance ? this.folderInstance.intro : this.module.description; - this.dataRetrieved.emit(module); - - if (this.path) { + if (this.subfolder) { // Subfolder. this.contents = folderContents; } else { @@ -107,25 +107,29 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo promise = this.folderProvider.getFolder(this.courseId, this.module.id).then((folder) => { return this.courseProvider.loadModuleContents(this.module, this.courseId, undefined, false, refresh).then(() => { folderContents = this.module.contents; + this.folderInstance = folder; return folder; }); }); } else { - promise = this.courseProvider.getModule(this.module.id, this.courseId).then((folder) => { - if (!folder.contents.length && this.module.contents.length && !this.appProvider.isOnline()) { + promise = this.courseProvider.getModule(this.module.id, this.courseId).then((module) => { + if (!module.contents.length && this.module.contents.length && !this.appProvider.isOnline()) { // The contents might be empty due to a cached data. Use the old ones. - folder.contents = this.module.contents; + module.contents = this.module.contents; } - this.module = folder; - folderContents = folder.contents; + this.module = module; + folderContents = module.contents; - return folder; + return module; }); } - return promise.then((folder) => { - this.showModuleData(folder, folderContents); + return promise.then(() => { + + this.dataRetrieved.emit(this.folderInstance || this.module); + + this.showModuleData(folderContents); }).finally(() => { this.fillContextMenu(refresh); }); diff --git a/src/addon/mod/folder/pages/index/index.html b/src/addon/mod/folder/pages/index/index.html index c435f6866..27f9f1509 100644 --- a/src/addon/mod/folder/pages/index/index.html +++ b/src/addon/mod/folder/pages/index/index.html @@ -8,9 +8,9 @@ - + - + diff --git a/src/addon/mod/folder/pages/index/index.ts b/src/addon/mod/folder/pages/index/index.ts index 74c63b22e..a64d7b499 100644 --- a/src/addon/mod/folder/pages/index/index.ts +++ b/src/addon/mod/folder/pages/index/index.ts @@ -30,13 +30,15 @@ export class AddonModFolderIndexPage { title: string; module: any; courseId: number; - path: string; + folderInstance: any; + subfolder: any; constructor(navParams: NavParams) { this.module = navParams.get('module') || {}; this.courseId = navParams.get('courseId'); - this.path = navParams.get('path'); - this.title = this.module.name; + this.folderInstance = navParams.get('folderInstance'); + this.subfolder = navParams.get('subfolder'); + this.title = this.subfolder ? this.subfolder.name : this.module.name; } /** From e109f42d4e89e876f35869a9e3fbcf308a025499 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 20 Mar 2020 10:30:38 +0100 Subject: [PATCH 006/166] MOBILE-3101 core: Install Ionic WebView plugin --- config.xml | 1 + package-lock.json | 17 +++++++++++++---- package.json | 4 +++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/config.xml b/config.xml index 6f949ffa9..cc8259460 100644 --- a/config.xml +++ b/config.xml @@ -178,6 +178,7 @@ + diff --git a/package-lock.json b/package-lock.json index 88471ab97..36872c57b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1366,7 +1366,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "" + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -2675,6 +2676,11 @@ "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-keyboard/-/cordova-plugin-ionic-keyboard-2.1.3.tgz", "integrity": "sha512-6ucQ6FdlLdBm8kJfFnzozmBTjru/0xekHP/dAhjoCZggkGRlgs8TsUJFkxa/bV+qi7Dlo50JjmpE4UMWAO+aOQ==" }, + "cordova-plugin-ionic-webview": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-4.1.3.tgz", + "integrity": "sha512-hlrUF0kLjjEkZmpYlLJO0NnXmVjMmQ3MOZVXm1ytDihLPKHklYCOpCvjA5Wz3hJrPD1shFEsqi/SPnp873AsdQ==" + }, "cordova-plugin-local-notification": { "version": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#0bb96b757fb484553ceabf35a59802f7983a2836", "from": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle" @@ -6672,7 +6678,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "micromatch": { @@ -11323,7 +11330,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "" + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -13484,7 +13492,8 @@ }, "kind-of": { "version": "6.0.2", - "resolved": "", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "micromatch": { diff --git a/package.json b/package.json index bd1de5e56..2d3f35c34 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "cordova-plugin-globalization": "1.11.0", "cordova-plugin-inappbrowser": "3.2.0", "cordova-plugin-ionic-keyboard": "2.1.3", + "cordova-plugin-ionic-webview": "4.1.3", "cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle", "cordova-plugin-media-capture": "3.0.3", "cordova-plugin-network-information": "2.0.2", @@ -185,7 +186,8 @@ }, "cordova-plugin-geolocation": { "GEOLOCATION_USAGE_DESCRIPTION": "To locate you" - } + }, + "cordova-plugin-ionic-webview": {} } }, "main": "desktop/electron.js", From 98dcb3ae16db61843810bdaac729596898cbdf2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 14 Apr 2020 12:16:09 +0200 Subject: [PATCH 007/166] MOBILE-3363 settings: Allow auto dark mode on iOS --- src/core/settings/pages/general/general.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/settings/pages/general/general.ts b/src/core/settings/pages/general/general.ts index 76b680088..2ddc61e0c 100644 --- a/src/core/settings/pages/general/general.ts +++ b/src/core/settings/pages/general/general.ts @@ -14,7 +14,6 @@ import { Component, ViewChild } from '@angular/core'; import { IonicPage, Segment } from 'ionic-angular'; -import { CoreAppProvider } from '@providers/app'; import { CoreConstants } from '@core/constants'; import { CoreConfigProvider } from '@providers/config'; import { CoreFileProvider } from '@providers/file'; @@ -49,10 +48,14 @@ export class CoreSettingsGeneralPage { selectedScheme: string; colorSchemeDisabled: boolean; - constructor(private appProvider: CoreAppProvider, private configProvider: CoreConfigProvider, fileProvider: CoreFileProvider, - private eventsProvider: CoreEventsProvider, private langProvider: CoreLangProvider, - private domUtils: CoreDomUtilsProvider, private pushNotificationsProvider: CorePushNotificationsProvider, - localNotificationsProvider: CoreLocalNotificationsProvider, private settingsHelper: CoreSettingsHelper) { + constructor(protected configProvider: CoreConfigProvider, + fileProvider: CoreFileProvider, + protected eventsProvider: CoreEventsProvider, + protected langProvider: CoreLangProvider, + protected domUtils: CoreDomUtilsProvider, + protected pushNotificationsProvider: CorePushNotificationsProvider, + localNotificationsProvider: CoreLocalNotificationsProvider, + protected settingsHelper: CoreSettingsHelper) { // Get the supported languages. const languages = CoreConfigConstants.languages; @@ -72,9 +75,8 @@ export class CoreSettingsGeneralPage { } else { let defaultColorScheme = 'light'; - // Auto is not working on iOS right now until we update Webkit. - if (!this.appProvider.isIOS() && (window.matchMedia('(prefers-color-scheme: dark)').matches || - window.matchMedia('(prefers-color-scheme: light)').matches)) { + if (window.matchMedia('(prefers-color-scheme: dark)').matches || + window.matchMedia('(prefers-color-scheme: light)').matches) { this.colorSchemes.push('auto'); defaultColorScheme = 'auto'; } From 1eb8a045af0539edb93fd1d84b4ba8c7f23406bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 14 Apr 2020 12:32:41 +0200 Subject: [PATCH 008/166] MOBILE-3363 styles: Style dark mode action sheet buttons --- src/app/app.scss | 3 ++- src/core/login/login.scss | 6 ++++++ src/theme/dark.scss | 1 + src/theme/variables.scss | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/app.scss b/src/app/app.scss index cc99bbfa8..a75d033d7 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -666,11 +666,12 @@ ion-app.app-root { overflow: auto; } - .action-sheet-wrapper { + ion-action-sheet .action-sheet-wrapper .action-sheet-container { .action-sheet-button.action-sheet-cancel { color: $core-action-sheet-cancel-color; @include darkmode() { color: $core-dark-action-sheet-cancel-color; + background-color: $black; } } .action-sheet-selected { diff --git a/src/core/login/login.scss b/src/core/login/login.scss index d0bc7225b..7dce8dd70 100644 --- a/src/core/login/login.scss +++ b/src/core/login/login.scss @@ -30,6 +30,12 @@ ion-app.app-root page-core-login-site { border-color: $core-dark-login-box-background-border; color: $core-dark-login-box-text-color; } + + .item { + @include darkmode() { + background: $core-dark-login-box-background-color; + } + } } .core-sitename, .core-siteurl { diff --git a/src/theme/dark.scss b/src/theme/dark.scss index 7e065f077..94ce2b6b1 100644 --- a/src/theme/dark.scss +++ b/src/theme/dark.scss @@ -23,6 +23,7 @@ ion-app.app-root { &.action-sheet-selected { color: $core-color; + background-color: $black; } &.activated { background-color: $black; diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 15002db6f..aefe54083 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -90,7 +90,7 @@ $inverted-contrast: $primary !default; $primary-dark: lighten($primary, 10%) !default; $secondary-dark: mix($secondary, white, 20%) !default; -$danger-dark: mix($danger, white, 20%) !default; +$danger-dark: mix($danger, white, 80%) !default; $warning-dark: mix($warning, white, 20%) !default; $success-dark: mix($success, white, 20%) !default; $info-dark: mix($info, white, 20%) !default; From 8910fc7f5ac3ef7f8230a7f563658c0d1852f04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 17 Apr 2020 13:43:42 +0200 Subject: [PATCH 009/166] MOBILE-3370 blocks: Add support for block_activity_results --- scripts/langindex.json | 1 + .../activityresults/activityresults.module.ts | 38 ++++++++++++++ .../activityresults/activityresults.scss | 31 +++++++++++ src/addon/block/activityresults/lang/en.json | 3 ++ .../providers/block-handler.ts | 51 +++++++++++++++++++ src/app/app.module.ts | 2 + src/assets/lang/en.json | 1 + 7 files changed, 127 insertions(+) create mode 100644 src/addon/block/activityresults/activityresults.module.ts create mode 100644 src/addon/block/activityresults/activityresults.scss create mode 100644 src/addon/block/activityresults/lang/en.json create mode 100644 src/addon/block/activityresults/providers/block-handler.ts diff --git a/scripts/langindex.json b/scripts/langindex.json index 212d23e5c..68829253c 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -27,6 +27,7 @@ "addon.badges.version": "badges", "addon.badges.warnexpired": "badges", "addon.block_activitymodules.pluginname": "block_activity_modules", + "addon.block_activityresults.pluginname": "block_activity_results", "addon.block_badges.pluginname": "block_badges", "addon.block_blogmenu.pluginname": "block_blog_menu", "addon.block_blogrecent.pluginname": "block_blog_recent", diff --git a/src/addon/block/activityresults/activityresults.module.ts b/src/addon/block/activityresults/activityresults.module.ts new file mode 100644 index 000000000..3c0ee74d3 --- /dev/null +++ b/src/addon/block/activityresults/activityresults.module.ts @@ -0,0 +1,38 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreBlockDelegate } from '@core/block/providers/delegate'; +import { AddonBlockActivityResultsHandler } from './providers/block-handler'; + +@NgModule({ + declarations: [ + ], + imports: [ + IonicModule, + TranslateModule.forChild() + ], + exports: [ + ], + providers: [ + AddonBlockActivityResultsHandler + ] +}) +export class AddonBlockActivityResultsModule { + constructor(blockDelegate: CoreBlockDelegate, blockHandler: AddonBlockActivityResultsHandler) { + blockDelegate.registerHandler(blockHandler); + } +} diff --git a/src/addon/block/activityresults/activityresults.scss b/src/addon/block/activityresults/activityresults.scss new file mode 100644 index 000000000..b76cb85a9 --- /dev/null +++ b/src/addon/block/activityresults/activityresults.scss @@ -0,0 +1,31 @@ +.addon-block-activity-results core-block-pre-rendered { + ion-item.core-block-content { + table.grades { + @include text-align('start'); + width: 100%; + + .number { + @include text-align('start'); + width: 10%; + } + + .name { + @include text-align('start'); + width: 77%; + } + + .grade { + @include text-align('end'); + } + + caption { + @include text-align('start'); + padding-top: .75rem; + padding-bottom: .75rem; + color: $gray-darker; + font-weight: bold; + font-size: 18px; + } + } + } +} \ No newline at end of file diff --git a/src/addon/block/activityresults/lang/en.json b/src/addon/block/activityresults/lang/en.json new file mode 100644 index 000000000..4dd6abbb7 --- /dev/null +++ b/src/addon/block/activityresults/lang/en.json @@ -0,0 +1,3 @@ +{ + "pluginname": "Activity results" +} \ No newline at end of file diff --git a/src/addon/block/activityresults/providers/block-handler.ts b/src/addon/block/activityresults/providers/block-handler.ts new file mode 100644 index 000000000..8553cb3a4 --- /dev/null +++ b/src/addon/block/activityresults/providers/block-handler.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable, Injector } from '@angular/core'; + +import { CoreBlockHandlerData } from '@core/block/providers/delegate'; +import { CoreBlockPreRenderedComponent } from '@core/block/components/pre-rendered-block/pre-rendered-block'; +import { CoreBlockBaseHandler } from '@core/block/classes/base-block-handler'; + +/** + * Block handler. + */ +@Injectable() +export class AddonBlockActivityResultsHandler extends CoreBlockBaseHandler { + name = 'AddonBlockActivityResults'; + blockName = 'activity_results'; + + constructor() { + super(); + } + + /** + * Returns the data needed to render the block. + * + * @param injector Injector. + * @param block The block to render. + * @param contextLevel The context where the block will be used. + * @param instanceId The instance ID associated with the context level. + * @return Data or promise resolved with the data. + */ + getDisplayData(injector: Injector, block: any, contextLevel: string, instanceId: number) + : CoreBlockHandlerData | Promise { + + return { + title: 'addon.block_activityresults.pluginname', + class: 'addon-block-activity-results', + component: CoreBlockPreRenderedComponent + }; + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 81fdb84a7..e38469ce8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -98,6 +98,7 @@ import { AddonCourseCompletionModule } from '@addon/coursecompletion/coursecompl import { AddonUserProfileFieldModule } from '@addon/userprofilefield/userprofilefield.module'; import { AddonFilesModule } from '@addon/files/files.module'; import { AddonBlockActivityModulesModule } from '@addon/block/activitymodules/activitymodules.module'; +import { AddonBlockActivityResultsModule } from '@addon/block/activityresults/activityresults.module'; import { AddonBlockBadgesModule } from '@addon/block/badges/badges.module'; import { AddonBlockBlogMenuModule } from '@addon/block/blogmenu/blogmenu.module'; import { AddonBlockBlogTagsModule } from '@addon/block/blogtags/blogtags.module'; @@ -245,6 +246,7 @@ export const WP_PROVIDER: any = null; AddonUserProfileFieldModule, AddonFilesModule, AddonBlockActivityModulesModule, + AddonBlockActivityResultsModule, AddonBlockBadgesModule, AddonBlockBlogMenuModule, AddonBlockBlogRecentModule, diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 3561e6111..6a229b1b1 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -27,6 +27,7 @@ "addon.badges.version": "Version", "addon.badges.warnexpired": "(This badge has expired!)", "addon.block_activitymodules.pluginname": "Activities", + "addon.block_activityresults.pluginname": "Activity results", "addon.block_badges.pluginname": "Latest badges", "addon.block_blogmenu.pluginname": "Blog menu", "addon.block_blogrecent.pluginname": "Recent blog entries", From df906f91e9de415ead2744c9c4a7ca82500a4066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 17 Apr 2020 16:07:57 +0200 Subject: [PATCH 010/166] MOBILE-3346 workshop: Show current user assessments when closed --- .../workshop/pages/submission/submission.ts | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index aab6470db..245d320ac 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -234,16 +234,16 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { this.canDelete = !assessment; } - assessment.userid = assessment.reviewerid; - assessment = this.workshopHelper.realGradeValue(this.workshop, assessment); - - if (this.currentUserId == assessment.userid) { - this.ownAssessment = assessment; - assessment.ownAssessment = true; - } + assessment = this.parseAssessment(assessment); this.submissionInfo.reviewedby = [assessment]; })); + } else if (this.workshop.phase == AddonModWorkshopProvider.PHASE_CLOSED && this.userId == this.currentUserId) { + this.workshopProvider.getSubmissionAssessments(this.workshopId, this.submissionId).then((assessments) => { + this.submissionInfo.reviewedby = assessments.map((assessment) => { + return this.parseAssessment(assessment); + }); + }); } if (this.canAddFeedback || this.workshop.phase == AddonModWorkshopProvider.PHASE_CLOSED) { @@ -324,6 +324,24 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { }); } + /** + * Parse assessment to be shown. + * + * @param assessment Original assessment. + * @return Parsed assessment. + */ + protected parseAssessment(assessment: any): any { + assessment.userid = assessment.reviewerid; + assessment = this.workshopHelper.realGradeValue(this.workshop, assessment); + + if (this.currentUserId == assessment.userid) { + this.ownAssessment = assessment; + assessment.ownAssessment = true; + } + + return assessment; + } + /** * Force leaving the page, without checking for changes. */ From 8e9a841a8c843836520be0f42055da9999be3bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 20 Apr 2020 12:21:53 +0200 Subject: [PATCH 011/166] MOBILE-2870 feedback: Solve cut buttons in columns --- .../index/addon-mod-feedback-index.html | 10 +++++----- src/addon/mod/feedback/pages/form/form.html | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html b/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html index 4355c5310..90eccec51 100644 --- a/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html +++ b/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html @@ -108,18 +108,18 @@ - - - - - diff --git a/src/addon/mod/feedback/pages/form/form.html b/src/addon/mod/feedback/pages/form/form.html index adb569d88..99b805762 100644 --- a/src/addon/mod/feedback/pages/form/form.html +++ b/src/addon/mod/feedback/pages/form/form.html @@ -67,20 +67,20 @@ - - - - - - @@ -98,14 +98,14 @@ - - - - From 9f325e163f45809ec25850438abf03bdb3ee75a5 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 9 Apr 2020 15:25:23 +0200 Subject: [PATCH 012/166] MOBILE-3134 core: Debounce calls to update size in activity --- scripts/langindex.json | 1 + .../index/addon-mod-assign-index.html | 2 +- .../index/addon-mod-book-index.html | 2 +- .../index/addon-mod-choice-index.html | 2 +- .../index/addon-mod-data-index.html | 2 +- .../index/addon-mod-feedback-index.html | 2 +- .../index/addon-mod-folder-index.html | 2 +- .../index/addon-mod-forum-index.html | 2 +- .../index/addon-mod-glossary-index.html | 2 +- .../index/addon-mod-imscp-index.html | 2 +- .../index/addon-mod-lesson-index.html | 2 +- .../index/addon-mod-page-index.html | 2 +- .../index/addon-mod-quiz-index.html | 2 +- .../index/addon-mod-resource-index.html | 2 +- .../index/addon-mod-scorm-index.html | 2 +- .../index/addon-mod-survey-index.html | 2 +- .../index/addon-mod-wiki-index.html | 2 +- .../index/addon-mod-workshop-index.html | 2 +- src/assets/lang/en.json | 1 + src/core/constants.ts | 6 - .../course/classes/main-resource-component.ts | 12 +- src/core/course/lang/en.json | 1 + src/core/course/providers/helper.ts | 51 ++++++-- .../providers/module-prefetch-delegate.ts | 11 +- .../core-siteplugins-module-index.html | 2 +- src/providers/events.ts | 1 + src/providers/filepool.ts | 123 +++++++++++++----- src/providers/utils/utils.ts | 23 ++++ 28 files changed, 193 insertions(+), 73 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index 212d23e5c..504e2bc4d 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1390,6 +1390,7 @@ "core.course.allsections": "local_moodlemobileapp", "core.course.askadmintosupport": "local_moodlemobileapp", "core.course.availablespace": "local_moodlemobileapp", + "core.course.cannotdeletewhiledownloading": "local_moodlemobileapp", "core.course.confirmdeletemodulefiles": "local_moodlemobileapp", "core.course.confirmdownload": "local_moodlemobileapp", "core.course.confirmdownloadunknownsize": "local_moodlemobileapp", diff --git a/src/addon/mod/assign/components/index/addon-mod-assign-index.html b/src/addon/mod/assign/components/index/addon-mod-assign-index.html index 467f9e49d..ee087a9df 100644 --- a/src/addon/mod/assign/components/index/addon-mod-assign-index.html +++ b/src/addon/mod/assign/components/index/addon-mod-assign-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/book/components/index/addon-mod-book-index.html b/src/addon/mod/book/components/index/addon-mod-book-index.html index 6fcc9f70d..cfd0ff551 100644 --- a/src/addon/mod/book/components/index/addon-mod-book-index.html +++ b/src/addon/mod/book/components/index/addon-mod-book-index.html @@ -9,7 +9,7 @@ - + diff --git a/src/addon/mod/choice/components/index/addon-mod-choice-index.html b/src/addon/mod/choice/components/index/addon-mod-choice-index.html index 762ad5066..bc5de5829 100644 --- a/src/addon/mod/choice/components/index/addon-mod-choice-index.html +++ b/src/addon/mod/choice/components/index/addon-mod-choice-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/data/components/index/addon-mod-data-index.html b/src/addon/mod/data/components/index/addon-mod-data-index.html index 200fb4387..af4a82ad6 100644 --- a/src/addon/mod/data/components/index/addon-mod-data-index.html +++ b/src/addon/mod/data/components/index/addon-mod-data-index.html @@ -12,7 +12,7 @@ - + diff --git a/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html b/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html index 4355c5310..b491576c5 100644 --- a/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html +++ b/src/addon/mod/feedback/components/index/addon-mod-feedback-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/folder/components/index/addon-mod-folder-index.html b/src/addon/mod/folder/components/index/addon-mod-folder-index.html index 4627aaeba..2aa7976f3 100644 --- a/src/addon/mod/folder/components/index/addon-mod-folder-index.html +++ b/src/addon/mod/folder/components/index/addon-mod-folder-index.html @@ -6,7 +6,7 @@ - + diff --git a/src/addon/mod/forum/components/index/addon-mod-forum-index.html b/src/addon/mod/forum/components/index/addon-mod-forum-index.html index e941c514a..7e7935ae6 100644 --- a/src/addon/mod/forum/components/index/addon-mod-forum-index.html +++ b/src/addon/mod/forum/components/index/addon-mod-forum-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/glossary/components/index/addon-mod-glossary-index.html b/src/addon/mod/glossary/components/index/addon-mod-glossary-index.html index 235c51297..0c01a1288 100644 --- a/src/addon/mod/glossary/components/index/addon-mod-glossary-index.html +++ b/src/addon/mod/glossary/components/index/addon-mod-glossary-index.html @@ -14,7 +14,7 @@ - + diff --git a/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html b/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html index 35cbae509..6be152d02 100644 --- a/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html +++ b/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html @@ -9,7 +9,7 @@ - + diff --git a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html index f7ac672e0..834abcf38 100644 --- a/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html +++ b/src/addon/mod/lesson/components/index/addon-mod-lesson-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/page/components/index/addon-mod-page-index.html b/src/addon/mod/page/components/index/addon-mod-page-index.html index 378796f11..12f6ddbd3 100644 --- a/src/addon/mod/page/components/index/addon-mod-page-index.html +++ b/src/addon/mod/page/components/index/addon-mod-page-index.html @@ -6,7 +6,7 @@ - + diff --git a/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html b/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html index 88de59576..ec8685448 100644 --- a/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html +++ b/src/addon/mod/quiz/components/index/addon-mod-quiz-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/resource/components/index/addon-mod-resource-index.html b/src/addon/mod/resource/components/index/addon-mod-resource-index.html index 7d2e36a94..9fcfdaa83 100644 --- a/src/addon/mod/resource/components/index/addon-mod-resource-index.html +++ b/src/addon/mod/resource/components/index/addon-mod-resource-index.html @@ -6,7 +6,7 @@ - + diff --git a/src/addon/mod/scorm/components/index/addon-mod-scorm-index.html b/src/addon/mod/scorm/components/index/addon-mod-scorm-index.html index a9fcfd058..cd5e6b01a 100644 --- a/src/addon/mod/scorm/components/index/addon-mod-scorm-index.html +++ b/src/addon/mod/scorm/components/index/addon-mod-scorm-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/survey/components/index/addon-mod-survey-index.html b/src/addon/mod/survey/components/index/addon-mod-survey-index.html index 42c41ddd0..eb101c594 100644 --- a/src/addon/mod/survey/components/index/addon-mod-survey-index.html +++ b/src/addon/mod/survey/components/index/addon-mod-survey-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/addon/mod/wiki/components/index/addon-mod-wiki-index.html b/src/addon/mod/wiki/components/index/addon-mod-wiki-index.html index e043a6299..44a57c1ca 100644 --- a/src/addon/mod/wiki/components/index/addon-mod-wiki-index.html +++ b/src/addon/mod/wiki/components/index/addon-mod-wiki-index.html @@ -19,7 +19,7 @@ - + diff --git a/src/addon/mod/workshop/components/index/addon-mod-workshop-index.html b/src/addon/mod/workshop/components/index/addon-mod-workshop-index.html index 3ce7e2c32..c10216d25 100644 --- a/src/addon/mod/workshop/components/index/addon-mod-workshop-index.html +++ b/src/addon/mod/workshop/components/index/addon-mod-workshop-index.html @@ -7,7 +7,7 @@ - + diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 3561e6111..3c3ea32d7 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1390,6 +1390,7 @@ "core.course.allsections": "All sections", "core.course.askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.", "core.course.availablespace": " You currently have about {{available}} free space.", + "core.course.cannotdeletewhiledownloading": "Files cannot be deleted while the activity is being downloaded. Please wait for the download to finish.", "core.course.confirmdeletemodulefiles": "Are you sure you want to delete these files?", "core.course.confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?", "core.course.confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?", diff --git a/src/core/constants.ts b/src/core/constants.ts index f498ff8a9..c9784ccc3 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -68,12 +68,6 @@ export class CoreConstants { static OUTDATED = 'outdated'; static NOT_DOWNLOADABLE = 'notdownloadable'; - // File status constants. - static FILE_ACTION_DOWNLOAD = 'download'; - static FILE_ACTION_DOWNLOADING = 'downloading'; - static FILE_ACTION_DELETED = 'deleted'; - static FILE_ACTION_OUTDATED = 'outdated'; - // Constants from Moodle's resourcelib. static RESOURCELIB_DISPLAY_AUTO = 0; // Try the best way. static RESOURCELIB_DISPLAY_EMBED = 1; // Display using object tag. diff --git a/src/core/course/classes/main-resource-component.ts b/src/core/course/classes/main-resource-component.ts index e568fec05..1bbff628d 100644 --- a/src/core/course/classes/main-resource-component.ts +++ b/src/core/course/classes/main-resource-component.ts @@ -261,9 +261,17 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, /** * Confirm and remove downloaded files. + * + * @param done Function to call when done. */ - removeFiles(): void { - this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId); + removeFiles(done?: () => void): void { + if (this.prefetchStatus == CoreConstants.DOWNLOADING) { + this.domUtils.showAlertTranslated(null, 'core.course.cannotdeletewhiledownloading'); + + return; + } + + this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId, done); } /** diff --git a/src/core/course/lang/en.json b/src/core/course/lang/en.json index 2fe5518e9..69cbe5cf9 100644 --- a/src/core/course/lang/en.json +++ b/src/core/course/lang/en.json @@ -5,6 +5,7 @@ "allsections": "All sections", "askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.", "availablespace": " You currently have about {{available}} free space.", + "cannotdeletewhiledownloading": "Files cannot be deleted while the activity is being downloaded. Please wait for the download to finish.", "confirmdeletemodulefiles": "Are you sure you want to delete these files?", "confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?", "confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?", diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index c2b34853f..b93d3191b 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -13,12 +13,12 @@ // limitations under the License. import { Injectable, Injector } from '@angular/core'; -import { NavController } from 'ionic-angular'; +import { NavController, Loading } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreEventsProvider } from '@providers/events'; import { CoreFileProvider } from '@providers/file'; -import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreFilepoolProvider, CoreFilepoolComponentFileEventData } from '@providers/filepool'; import { CoreFileHelperProvider } from '@providers/file-helper'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -408,16 +408,29 @@ export class CoreCourseHelperProvider { * * @param module Module to remove the files. * @param courseId Course ID the module belongs to. + * @param done Function to call when done. It will close the context menu. * @return Promise resolved when done. */ - confirmAndRemoveFiles(module: any, courseId: number): Promise { - return this.domUtils.showDeleteConfirm('core.course.confirmdeletemodulefiles').then(() => { - return this.prefetchDelegate.removeModuleFiles(module, courseId); - }).catch((error) => { + async confirmAndRemoveFiles(module: any, courseId: number, done?: () => void): Promise { + let modal: Loading; + + try { + + await this.domUtils.showDeleteConfirm('core.course.confirmdeletemodulefiles'); + + modal = this.domUtils.showModalLoading(); + + await this.prefetchDelegate.removeModuleFiles(module, courseId); + + done && done(); + + } catch (error) { if (error) { this.domUtils.showErrorModal(error); } - }); + } finally { + modal && modal.dismiss(); + } } /** @@ -831,15 +844,27 @@ export class CoreCourseHelperProvider { } if (typeof instance.contextFileStatusObserver == 'undefined' && component) { - const componentFileChangeStatusEvent = CoreFilepoolProvider.getComponentEventName(siteId, component, module.id); + // Debounce the update size function to prevent too many calls when downloading or deleting a whole activity. + const debouncedUpdateSize = this.utils.debounce(() => { + this.prefetchDelegate.getModuleDownloadedSize(module, courseId).then((moduleSize) => { + instance.size = moduleSize > 0 ? this.textUtils.bytesToSize(moduleSize, 2) : 0; + }); + }, 1000); - instance.contextFileStatusObserver = this.eventsProvider.on(componentFileChangeStatusEvent, (data) => { + instance.contextFileStatusObserver = this.eventsProvider.on(CoreEventsProvider.COMPONENT_FILE_ACTION, + (data: CoreFilepoolComponentFileEventData) => { - if (((data.action == CoreConstants.FILE_ACTION_DOWNLOAD && data.success == true) || - data.action == CoreConstants.FILE_ACTION_DELETED) && - instance.prefetchStatus != CoreConstants.DOWNLOADING) { - this.fillContextMenu(instance, module, courseId, true, component); + if (data.component != component || data.componentId != module.id) { + // The event doesn't belong to this component, ignore. + return; } + + if (!this.filepoolProvider.isFileEventDownloadedOrDeleted(data)) { + return; + } + + // Update the module size. + debouncedUpdateSize(); }, siteId); } }); diff --git a/src/core/course/providers/module-prefetch-delegate.ts b/src/core/course/providers/module-prefetch-delegate.ts index 6e05b283b..ef0c1ad04 100644 --- a/src/core/course/providers/module-prefetch-delegate.ts +++ b/src/core/course/providers/module-prefetch-delegate.ts @@ -15,7 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreEventsProvider } from '@providers/events'; import { CoreFileProvider } from '@providers/file'; -import { CoreFilepoolProvider } from '@providers/filepool'; +import { CoreFilepoolProvider, CoreFilepoolComponentFileEventData } from '@providers/filepool'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; @@ -276,6 +276,15 @@ export class CoreCourseModulePrefetchDelegate extends CoreDelegate { eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => { this.updateStatusCache(data.status, data.component, data.componentId); }, this.sitesProvider.getCurrentSiteId()); + + // If a file inside a module is downloaded/deleted, clear the corresponding cache. + eventsProvider.on(CoreEventsProvider.COMPONENT_FILE_ACTION, (data: CoreFilepoolComponentFileEventData) => { + if (!this.filepoolProvider.isFileEventDownloadedOrDeleted(data)) { + return; + } + + this.statusCache.invalidate(this.filepoolProvider.getPackageId(data.component, data.componentId)); + }, this.sitesProvider.getCurrentSiteId()); } /** diff --git a/src/core/siteplugins/components/module-index/core-siteplugins-module-index.html b/src/core/siteplugins/components/module-index/core-siteplugins-module-index.html index f3c8b832d..538055ea5 100644 --- a/src/core/siteplugins/components/module-index/core-siteplugins-module-index.html +++ b/src/core/siteplugins/components/module-index/core-siteplugins-module-index.html @@ -5,7 +5,7 @@ - + diff --git a/src/providers/events.ts b/src/providers/events.ts index abed87a95..4da2900c0 100644 --- a/src/providers/events.ts +++ b/src/providers/events.ts @@ -47,6 +47,7 @@ export class CoreEventsProvider { static PACKAGE_STATUS_CHANGED = 'package_status_changed'; static COURSE_STATUS_CHANGED = 'course_status_changed'; static SECTION_STATUS_CHANGED = 'section_status_changed'; + static COMPONENT_FILE_ACTION = 'component_file_action'; static SITE_PLUGINS_LOADED = 'site_plugins_loaded'; static SITE_PLUGINS_COURSE_RESTRICT_UPDATED = 'site_plugins_course_restrict_updated'; static LOGIN_SITE_CHECKED = 'login_site_checked'; diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index 6235c973a..a3889773d 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -212,6 +212,51 @@ export interface CoreFilepoolComponentLink { componentId?: string | number; } +/** + * File actions. + */ +export const enum CoreFilepoolFileActions { + DOWNLOAD = 'download', + DOWNLOADING = 'downloading', + DELETED = 'deleted', + OUTDATED = 'outdated', +} + +/** + * Data sent to file events. + */ +export interface CoreFilepoolFileEventData { + /** + * The file ID. + */ + fileId: string; + + /** + * The file ID. + */ + action: CoreFilepoolFileActions; + + /** + * Whether the action was a success. Only for DOWNLOAD action. + */ + success?: boolean; +} + +/** + * Data sent to component file events. + */ +export interface CoreFilepoolComponentFileEventData extends CoreFilepoolFileEventData { + /** + * The component. + */ + component: string; + + /** + * The component ID. + */ + componentId: string | number; +} + /* * Factory for handling downloading files and retrieve downloaded files. * @@ -1218,8 +1263,9 @@ export class CoreFilepoolProvider { downloadUrl(siteId: string, fileUrl: string, ignoreStale?: boolean, component?: string, componentId?: string | number, timemodified: number = 0, onProgress?: (event: any) => any, filePath?: string, options: any = {}, revision?: number) : Promise { - let fileId, - promise; + let fileId; + let promise; + let alreadyDownloaded = true; if (this.fileProvider.isAvailable()) { return this.fixPluginfileURL(siteId, fileUrl).then((file) => { @@ -1239,13 +1285,15 @@ export class CoreFilepoolProvider { if (typeof fileObject === 'undefined') { // We do not have the file, download and add to pool. this.notifyFileDownloading(siteId, fileId, links); + alreadyDownloaded = false; return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); } else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) && - this.appProvider.isOnline() && !ignoreStale) { + this.appProvider.isOnline() && !ignoreStale) { // The file is outdated, force the download and update it. this.notifyFileDownloading(siteId, fileId, links); + alreadyDownloaded = false; return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); } @@ -1262,6 +1310,7 @@ export class CoreFilepoolProvider { }, () => { // The file was not found in the pool, weird. this.notifyFileDownloading(siteId, fileId, links); + alreadyDownloaded = false; return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject); }); @@ -1269,6 +1318,7 @@ export class CoreFilepoolProvider { }, () => { // The file is not in the pool just yet. this.notifyFileDownloading(siteId, fileId, links); + alreadyDownloaded = false; return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress); }).then((response) => { @@ -1277,7 +1327,10 @@ export class CoreFilepoolProvider { // Ignore errors. }); } - this.notifyFileDownloaded(siteId, fileId, links); + + if (!alreadyDownloaded) { + this.notifyFileDownloaded(siteId, fileId, links); + } return response; }, (err) => { @@ -1434,18 +1487,6 @@ export class CoreFilepoolProvider { }); } - /** - * Get the name of the event used to notify file status to component (CoreEventsProvider). - * - * @param siteId The site ID. - * @param component The component name. - * @param componentId The component ID. - * @return Event name. - */ - static getComponentEventName(siteId: string, component: string, componentId: string | number): string { - return 'CoreFilepoolComponentFile:' + siteId + ':' + component + ':' + componentId; - } - /** * Convenience function to get component files. * @@ -2450,6 +2491,17 @@ export class CoreFilepoolProvider { }); } + /** + * Whether a file action indicates a file was downloaded or deleted. + * + * @param data Event data. + * @return Whether downloaded or deleted. + */ + isFileEventDownloadedOrDeleted(data: CoreFilepoolFileEventData): boolean { + return (data.action == CoreFilepoolFileActions.DOWNLOAD && data.success == true) || + data.action == CoreFilepoolFileActions.DELETED; + } + /** * Check whether a file is downloadable. * @@ -2508,14 +2560,19 @@ export class CoreFilepoolProvider { * Notify an action performed on a file to a list of components. * * @param siteId The site ID. - * @param eventData The event data. + * @param eventData The file event data. * @param links The links to the components. */ - protected notifyFileActionToComponents(siteId: string, eventData: any, links: CoreFilepoolComponentLink[]): void { + protected notifyFileActionToComponents(siteId: string, eventData: CoreFilepoolFileEventData, + links: CoreFilepoolComponentLink[]): void { links.forEach((link) => { - this.eventsProvider.trigger(CoreFilepoolProvider.getComponentEventName(siteId, link.component, link.componentId), - eventData, siteId); + const data: CoreFilepoolComponentFileEventData = Object.assign({ + component: link.component, + componentId: link.componentId, + }, eventData); + + this.eventsProvider.trigger(CoreEventsProvider.COMPONENT_FILE_ACTION, data, siteId); }); } @@ -2527,9 +2584,9 @@ export class CoreFilepoolProvider { * @param links The links to components. */ protected notifyFileDeleted(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { - const data = { + const data: CoreFilepoolFileEventData = { fileId: fileId, - action: CoreConstants.FILE_ACTION_DELETED + action: CoreFilepoolFileActions.DELETED, }; this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); @@ -2544,10 +2601,10 @@ export class CoreFilepoolProvider { * @param links The links to components. */ protected notifyFileDownloaded(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { - const data = { + const data: CoreFilepoolFileEventData = { fileId: fileId, - action: CoreConstants.FILE_ACTION_DOWNLOAD, - success: true + action: CoreFilepoolFileActions.DOWNLOAD, + success: true, }; this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); @@ -2562,10 +2619,10 @@ export class CoreFilepoolProvider { * @param links The links to components. */ protected notifyFileDownloadError(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { - const data = { + const data: CoreFilepoolFileEventData = { fileId: fileId, - action: CoreConstants.FILE_ACTION_DOWNLOAD, - success: false + action: CoreFilepoolFileActions.DOWNLOAD, + success: false, }; this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); @@ -2580,9 +2637,9 @@ export class CoreFilepoolProvider { * @param links The links to components. */ protected notifyFileDownloading(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { - const data = { + const data: CoreFilepoolFileEventData = { fileId: fileId, - action: CoreConstants.FILE_ACTION_DOWNLOADING + action: CoreFilepoolFileActions.DOWNLOADING, }; this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); @@ -2598,8 +2655,9 @@ export class CoreFilepoolProvider { * @param links The links to components. */ protected notifyFileOutdated(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void { - const data = { - action: CoreConstants.FILE_ACTION_OUTDATED + const data: CoreFilepoolFileEventData = { + fileId: fileId, + action: CoreFilepoolFileActions.OUTDATED, }; this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data); @@ -2729,7 +2787,6 @@ export class CoreFilepoolProvider { }).finally(() => { this.treatQueueDeferred(siteId, fileId, true); }); - this.notifyFileDownloaded(siteId, fileId, links); return; } diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index bedd0e4b0..bebc3ce1c 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -1392,4 +1392,27 @@ export class CoreUtilsProvider { return filtered; } + + /** + * Debounce a function so consecutive calls are ignored until a certain time has passed since the last call. + * + * @param context The context to apply to the function. + * @param fn Function to debounce. + * @param delay Time that must pass until the function is called. + * @return Debounced function. + */ + debounce(fn: (...args: any[]) => any, delay: number): (...args: any[]) => void { + + let timeoutID: number; + + const debounced = (...args: any[]): void => { + clearTimeout(timeoutID); + + timeoutID = window.setTimeout(() => { + fn.apply(null, args); + }, delay); + }; + + return debounced; + } } From 3a3d45db9235bff6fbc9ad842ecf24f5f154dda1 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 24 Mar 2020 12:18:32 +0100 Subject: [PATCH 013/166] MOBILE-3101 core: Create singletons of all core providers --- config/webpack.config.js | 3 +- src/app/app.module.ts | 8 ++- src/classes/singletons-factory.ts | 76 ++++++++++++++++++++++++ src/core/compile/providers/compile.ts | 2 +- src/core/login/pages/site/site.ts | 2 +- src/providers/app.ts | 3 + src/providers/config.ts | 3 + src/providers/cron.ts | 3 + src/providers/db.ts | 3 + src/providers/events.ts | 3 + src/providers/file-helper.ts | 4 +- src/providers/file-session.ts | 3 + src/providers/file.ts | 3 + src/providers/filepool.ts | 3 + src/providers/groups.ts | 3 + src/providers/init.ts | 3 + src/providers/lang.ts | 3 + src/providers/local-notifications.ts | 3 + src/providers/logger.ts | 3 + src/providers/plugin-file-delegate.ts | 3 + src/providers/sites-factory.ts | 3 + src/providers/sites.ts | 4 +- src/providers/sync.ts | 3 + src/providers/update-manager.ts | 3 + src/providers/urlschemes.ts | 3 + src/providers/utils/dom.ts | 3 + src/providers/utils/iframe.ts | 3 + src/providers/utils/mimetype.ts | 3 + src/providers/utils/text.ts | 3 + src/providers/utils/time.ts | 3 + src/providers/utils/url.ts | 3 + src/providers/utils/utils.ts | 3 + src/providers/ws.ts | 3 + src/singletons/core.singletons.ts | 49 +++++++++++++++ src/{classes/utils => singletons}/url.ts | 0 tsconfig.json | 3 +- 36 files changed, 222 insertions(+), 7 deletions(-) create mode 100644 src/classes/singletons-factory.ts create mode 100644 src/singletons/core.singletons.ts rename src/{classes/utils => singletons}/url.ts (100%) diff --git a/config/webpack.config.js b/config/webpack.config.js index 3f622bcd3..1c6ae7ca5 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -12,7 +12,8 @@ const customConfig = { '@providers': resolve('./src/providers'), '@components': resolve('./src/components'), '@directives': resolve('./src/directives'), - '@pipes': resolve('./src/pipes') + '@pipes': resolve('./src/pipes'), + '@singletons': resolve('./src/singletons'), } }, externals: [ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 81fdb84a7..c36f76078 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,7 +14,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { NgModule, COMPILER_OPTIONS } from '@angular/core'; +import { NgModule, COMPILER_OPTIONS, Injector } from '@angular/core'; import { IonicApp, IonicModule, Platform, Content, ScrollEvent, Config, Refresher } from 'ionic-angular'; import { assert } from 'ionic-angular/util/util'; import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; @@ -155,6 +155,8 @@ import { AddonQtypeModule } from '@addon/qtype/qtype.module'; import { AddonStorageManagerModule } from '@addon/storagemanager/storagemanager.module'; import { AddonFilterModule } from '@addon/filter/filter.module'; +import { setSingletonsInjector } from '@singletons/core.singletons'; + // For translate loader. AoT requires an exported function for factories. export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { return new TranslateHttpLoader(http, './assets/lang/', '.json'); @@ -357,6 +359,7 @@ export class AppModule { private eventsProvider: CoreEventsProvider, cronDelegate: CoreCronDelegate, siteInfoCronHandler: CoreSiteInfoCronHandler, + injector: Injector, ) { // Register a handler for platform ready. initDelegate.registerProcess({ @@ -391,6 +394,9 @@ export class AppModule { // Register handlers. cronDelegate.register(siteInfoCronHandler); + // Set the injector. + setSingletonsInjector(injector); + // Set transition animation. config.setTransition('core-page-transition', CorePageTransition); config.setTransition('core-modal-lateral-transition', CoreModalLateralTransition); diff --git a/src/classes/singletons-factory.ts b/src/classes/singletons-factory.ts new file mode 100644 index 000000000..791b192f0 --- /dev/null +++ b/src/classes/singletons-factory.ts @@ -0,0 +1,76 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector, Type } from '@angular/core'; + +/** + * Stub class used to type anonymous classes created in CoreSingletonsFactory#makeSingleton method. + */ +class CoreSingleton {} + +/** + * Token that can be used to resolve instances from the injector. + */ +export type CoreInjectionToken = Type | Type | string; + +/** + * Singleton class created using the factory. + */ +export type CoreSingletonClass = typeof CoreSingleton & { instance: Service }; + +/** + * Factory used to create CoreSingleton classes that get instances from an injector. + */ +export class CoreSingletonsFactory { + + /** + * Angular injector used to resolve singleton instances. + */ + private injector: Injector; + + /** + * Set the injector that will be used to resolve instances in the singletons created with this factory. + * + * @param injector Injector. + */ + setInjector(injector: Injector): void { + this.injector = injector; + } + + /** + * Make a singleton that will hold an instance resolved from the factory injector. + * + * @param injectionToken Injection token used to resolve the singleton instance. This is usually the service class if the + * provider was defined using a class or the string used in the `provide` key if it was defined using an object. + */ + makeSingleton(injectionToken: CoreInjectionToken): CoreSingletonClass { + // tslint:disable: no-this-assignment + const factory = this; + + return class { + + private static _instance: Service; + + static get instance(): Service { + // Initialize instances lazily. + if (!this._instance) { + this._instance = factory.injector.get(injectionToken); + } + + return this._instance; + } + + }; + } +} diff --git a/src/core/compile/providers/compile.ts b/src/core/compile/providers/compile.ts index 51cbc8afd..fc8268f61 100644 --- a/src/core/compile/providers/compile.ts +++ b/src/core/compile/providers/compile.ts @@ -56,7 +56,7 @@ import { Md5 } from 'ts-md5/dist/md5'; // Import core classes that can be useful for site plugins. import { CoreSyncBaseProvider } from '@classes/base-sync'; -import { CoreUrl } from '@classes/utils/url'; +import { CoreUrl } from '@singletons/url'; import { CoreCache } from '@classes/cache'; import { CoreDelegate } from '@classes/delegate'; import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index ebf6cfcaf..400491069 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -22,7 +22,7 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreConfigConstants } from '../../../../configconstants'; import { CoreLoginHelperProvider } from '../../providers/helper'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { CoreUrl } from '@classes/utils/url'; +import { CoreUrl } from '@singletons/url'; import { TranslateService } from '@ngx-translate/core'; /** diff --git a/src/providers/app.ts b/src/providers/app.ts index 7a50ff553..4d29185e5 100644 --- a/src/providers/app.ts +++ b/src/providers/app.ts @@ -23,6 +23,7 @@ import { CoreLoggerProvider } from './logger'; import { CoreEventsProvider } from './events'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; import { CoreConfigConstants } from '../configconstants'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Data stored for a redirect to another page/site. @@ -703,3 +704,5 @@ export class CoreAppProvider { this.forceOffline = !!value; } } + +export class CoreApp extends makeSingleton(CoreAppProvider) {} diff --git a/src/providers/config.ts b/src/providers/config.ts index 709b5ce8e..cf62a9012 100644 --- a/src/providers/config.ts +++ b/src/providers/config.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreAppProvider, CoreAppSchema } from './app'; import { SQLiteDB } from '@classes/sqlitedb'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Factory to provide access to dynamic and permanent config and settings. @@ -102,3 +103,5 @@ export class CoreConfigProvider { return this.appDB.insertRecord(this.TABLE_NAME, { name: name, value: value }); } } + +export class CoreConfig extends makeSingleton(CoreConfigProvider) {} diff --git a/src/providers/cron.ts b/src/providers/cron.ts index f0b130e9f..0cdf5e7e2 100644 --- a/src/providers/cron.ts +++ b/src/providers/cron.ts @@ -20,6 +20,7 @@ import { CoreLoggerProvider } from './logger'; import { CoreUtilsProvider } from './utils/utils'; import { CoreConstants } from '@core/constants'; import { SQLiteDB } from '@classes/sqlitedb'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Interface that all cron handlers must implement. @@ -554,3 +555,5 @@ export class CoreCronDelegate { delete this.handlers[name].timeout; } } + +export class CoreCron extends makeSingleton(CoreCronDelegate) {} diff --git a/src/providers/db.ts b/src/providers/db.ts index 6805c82e1..8e6c03299 100644 --- a/src/providers/db.ts +++ b/src/providers/db.ts @@ -17,6 +17,7 @@ import { SQLite } from '@ionic-native/sqlite'; import { Platform } from 'ionic-angular'; import { SQLiteDB } from '@classes/sqlitedb'; import { SQLiteDBMock } from '@core/emulator/classes/sqlitedb'; +import { makeSingleton } from '@singletons/core.singletons'; /** * This service allows interacting with the local database to store and retrieve data. @@ -81,3 +82,5 @@ export class CoreDbProvider { }); } } + +export class CoreDB extends makeSingleton(CoreDbProvider) {} diff --git a/src/providers/events.ts b/src/providers/events.ts index abed87a95..16f9baf3c 100644 --- a/src/providers/events.ts +++ b/src/providers/events.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; import { CoreLoggerProvider } from '@providers/logger'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Observer instance to stop listening to an event. @@ -173,3 +174,5 @@ export class CoreEventsProvider { } } } + +export class CoreEvents extends makeSingleton(CoreEventsProvider) {} diff --git a/src/providers/file-helper.ts b/src/providers/file-helper.ts index 73daa59b3..00b4b4150 100644 --- a/src/providers/file-helper.ts +++ b/src/providers/file-helper.ts @@ -21,6 +21,7 @@ import { CoreSitesProvider } from './sites'; import { CoreWSProvider } from './ws'; import { CoreUtilsProvider } from './utils/utils'; import { CoreConstants } from '@core/constants'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Provider to provide some helper functions regarding files and packages. @@ -333,5 +334,6 @@ export class CoreFileHelperProvider { throw new Error('Couldn\'t determine file size: ' + file.fileurl); } - } + +export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {} diff --git a/src/providers/file-session.ts b/src/providers/file-session.ts index 79798ae0f..552284a86 100644 --- a/src/providers/file-session.ts +++ b/src/providers/file-session.ts @@ -14,6 +14,7 @@ import { Injectable } from '@angular/core'; import { CoreSitesProvider } from './sites'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Helper to store some temporary data for file submission. @@ -146,3 +147,5 @@ export class CoreFileSessionProvider { this.files[siteId][component][id] = newFiles; } } + +export class CoreFileSession extends makeSingleton(CoreFileSessionProvider) {} diff --git a/src/providers/file.ts b/src/providers/file.ts index 07d1628f5..1af76887e 100644 --- a/src/providers/file.ts +++ b/src/providers/file.ts @@ -21,6 +21,7 @@ import { CoreLoggerProvider } from './logger'; import { CoreMimetypeUtilsProvider } from './utils/mimetype'; import { CoreTextUtilsProvider } from './utils/text'; import { Zip } from '@ionic-native/zip'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Progress event used when writing a file data into a file. @@ -1270,3 +1271,5 @@ export class CoreFileProvider { return window.location.href; } } + +export class CoreFile extends makeSingleton(CoreFileProvider) {} diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index a4faa08f3..40a5c0d56 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -31,6 +31,7 @@ import { CoreUtilsProvider } from './utils/utils'; import { SQLiteDB } from '@classes/sqlitedb'; import { CoreConstants } from '@core/constants'; import { Md5 } from 'ts-md5/dist/md5'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Entry from filepool. @@ -3069,3 +3070,5 @@ export class CoreFilepoolProvider { }); } } + +export class CoreFilepool extends makeSingleton(CoreFilepoolProvider) {} diff --git a/src/providers/groups.ts b/src/providers/groups.ts index d0c96e8d2..e05335501 100644 --- a/src/providers/groups.ts +++ b/src/providers/groups.ts @@ -17,6 +17,7 @@ import { TranslateService } from '@ngx-translate/core'; import { CoreSitesProvider } from './sites'; import { CoreCoursesProvider } from '@core/courses/providers/courses'; import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Group info for an activity. @@ -449,3 +450,5 @@ export class CoreGroupsProvider { return groupInfo.defaultGroupId; } } + +export class CoreGroups extends makeSingleton(CoreGroupsProvider) {} diff --git a/src/providers/init.ts b/src/providers/init.ts index f44e6f79e..3ac620352 100644 --- a/src/providers/init.ts +++ b/src/providers/init.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { Platform } from 'ionic-angular'; import { CoreLoggerProvider } from './logger'; import { CoreUtilsProvider } from './utils/utils'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Interface that all init handlers must implement. @@ -175,3 +176,5 @@ export class CoreInitDelegate { this.initProcesses[handler.name] = handler; } } + +export class CoreInit extends makeSingleton(CoreInitDelegate) {} diff --git a/src/providers/lang.ts b/src/providers/lang.ts index df16004e3..b598be1b7 100644 --- a/src/providers/lang.ts +++ b/src/providers/lang.ts @@ -20,6 +20,7 @@ import { Platform, Config } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; import { CoreConfigProvider } from './config'; import { CoreConfigConstants } from '../configconstants'; +import { makeSingleton } from '@singletons/core.singletons'; /* * Service to handle language features, like changing the current language. @@ -453,3 +454,5 @@ export class CoreLangProvider { } } } + +export class CoreLang extends makeSingleton(CoreLangProvider) {} diff --git a/src/providers/local-notifications.ts b/src/providers/local-notifications.ts index 78f2ccb08..2ac4dbdfb 100644 --- a/src/providers/local-notifications.ts +++ b/src/providers/local-notifications.ts @@ -27,6 +27,7 @@ import { SQLiteDB } from '@classes/sqlitedb'; import { CoreConstants } from '@core/constants'; import { CoreConfigConstants } from '../configconstants'; import { Subject, Subscription } from 'rxjs'; +import { makeSingleton } from '@singletons/core.singletons'; /* * Generated class for the LocalNotificationsProvider provider. @@ -754,3 +755,5 @@ export class CoreLocalNotificationsProvider { return this.appDB.updateRecords(this.COMPONENTS_TABLE, {id: newId}, {id: oldId}); } } + +export class CoreLocalNotifications extends makeSingleton(CoreLocalNotificationsProvider) {} diff --git a/src/providers/logger.ts b/src/providers/logger.ts index 1453f8cbf..12ad8a79f 100644 --- a/src/providers/logger.ts +++ b/src/providers/logger.ts @@ -14,6 +14,7 @@ import { Injectable } from '@angular/core'; import * as moment from 'moment'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Helper service to display messages in the console. @@ -72,3 +73,5 @@ export class CoreLoggerProvider { }; } } + +export class CoreLogger extends makeSingleton(CoreLoggerProvider) {} diff --git a/src/providers/plugin-file-delegate.ts b/src/providers/plugin-file-delegate.ts index 42ee781a7..b08989dc2 100644 --- a/src/providers/plugin-file-delegate.ts +++ b/src/providers/plugin-file-delegate.ts @@ -19,6 +19,7 @@ import { CoreSitesProvider } from './sites'; import { CoreWSExternalFile } from '@providers/ws'; import { FileEntry } from '@ionic-native/file'; import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Interface that all plugin file handlers must implement. @@ -371,3 +372,5 @@ export class CorePluginFileDelegate extends CoreDelegate { return Promise.resolve(); } } + +export class CorePluginFile extends makeSingleton(CorePluginFileDelegate) {} diff --git a/src/providers/sites-factory.ts b/src/providers/sites-factory.ts index f97d334cb..2ce61382b 100644 --- a/src/providers/sites-factory.ts +++ b/src/providers/sites-factory.ts @@ -14,6 +14,7 @@ import { Injectable, Injector } from '@angular/core'; import { CoreSite } from '@classes/site'; +import { makeSingleton } from '@singletons/core.singletons'; /* * Provider to create sites instances. @@ -56,3 +57,5 @@ export class CoreSitesFactoryProvider { return methods; } } + +export class CoreSitesFactory extends makeSingleton(CoreSitesFactoryProvider) {} diff --git a/src/providers/sites.ts b/src/providers/sites.ts index dcf33d0c4..f0f85df99 100644 --- a/src/providers/sites.ts +++ b/src/providers/sites.ts @@ -30,6 +30,7 @@ import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; import { Md5 } from 'ts-md5/dist/md5'; import { WP_PROVIDER } from '@app/app.module'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Response of checking if a site exists and its configuration. @@ -1925,5 +1926,6 @@ export class CoreSitesProvider { return {}; } } - } + +export class CoreSites extends makeSingleton(CoreSitesProvider) {} diff --git a/src/providers/sync.ts b/src/providers/sync.ts index 739d1b59f..c68514165 100644 --- a/src/providers/sync.ts +++ b/src/providers/sync.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreEventsProvider } from './events'; import { CoreSitesProvider, CoreSiteSchema } from './sites'; +import { makeSingleton } from '@singletons/core.singletons'; /* * Service that provides some features regarding synchronization. @@ -206,3 +207,5 @@ export class CoreSyncProvider { } } } + +export class CoreSync extends makeSingleton(CoreSyncProvider) {} diff --git a/src/providers/update-manager.ts b/src/providers/update-manager.ts index b32ef3499..cbf493127 100644 --- a/src/providers/update-manager.ts +++ b/src/providers/update-manager.ts @@ -17,6 +17,7 @@ import { CoreConfigProvider } from './config'; import { CoreInitHandler, CoreInitDelegate } from './init'; import { CoreLoggerProvider } from './logger'; import { CoreConfigConstants } from '../configconstants'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Factory to handle app updates. This factory shouldn't be used outside of core. @@ -59,3 +60,5 @@ export class CoreUpdateManagerProvider implements CoreInitHandler { }); } } + +export class CoreUpdateManager extends makeSingleton(CoreUpdateManagerProvider) {} diff --git a/src/providers/urlschemes.ts b/src/providers/urlschemes.ts index b7ed851c3..5c22508d2 100644 --- a/src/providers/urlschemes.ts +++ b/src/providers/urlschemes.ts @@ -28,6 +28,7 @@ import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate' import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins'; import { CoreConfigConstants } from '../configconstants'; import { CoreConstants } from '@core/constants'; +import { makeSingleton } from '@singletons/core.singletons'; /** * All params that can be in a custom URL scheme. @@ -488,3 +489,5 @@ export class CoreCustomURLSchemesProvider { return url.indexOf(CoreConfigConstants.customurlscheme + '://token=') != -1; } } + +export class CoreCustomURLSchemes extends makeSingleton(CoreCustomURLSchemesProvider) {} diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index c692faf65..743a333ec 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -30,6 +30,7 @@ import { CoreConstants } from '@core/constants'; import { CoreBSTooltipComponent } from '@components/bs-tooltip/bs-tooltip'; import { Md5 } from 'ts-md5/dist/md5'; import { Subject } from 'rxjs'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Interface that defines an extension of the Ionic Alert class, to support multiple listeners. @@ -1666,3 +1667,5 @@ export class CoreDomUtilsProvider { }, siteId); } } + +export class CoreDomUtils extends makeSingleton(CoreDomUtilsProvider) {} diff --git a/src/providers/utils/iframe.ts b/src/providers/utils/iframe.ts index e60c19b58..5b82ebab2 100644 --- a/src/providers/utils/iframe.ts +++ b/src/providers/utils/iframe.ts @@ -25,6 +25,7 @@ import { CoreTextUtilsProvider } from './text'; import { CoreUrlUtilsProvider } from './url'; import { CoreUtilsProvider } from './utils'; import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { makeSingleton } from '@singletons/core.singletons'; /* * "Utils" service with helper functions for iframes, embed and similar. @@ -396,6 +397,8 @@ export class CoreIframeUtilsProvider { } } +export class CoreIframeUtils extends makeSingleton(CoreIframeUtilsProvider) {} + /** * Subtype of HTMLAnchorElement, with some calculated data. */ diff --git a/src/providers/utils/mimetype.ts b/src/providers/utils/mimetype.ts index c162f3dc7..4b256196c 100644 --- a/src/providers/utils/mimetype.ts +++ b/src/providers/utils/mimetype.ts @@ -17,6 +17,7 @@ import { HttpClient } from '@angular/common/http'; import { CoreLoggerProvider } from '../logger'; import { TranslateService } from '@ngx-translate/core'; import { CoreTextUtilsProvider } from './text'; +import { makeSingleton } from '@singletons/core.singletons'; /* * "Utils" service with helper functions for mimetypes and extensions. @@ -549,3 +550,5 @@ export class CoreMimetypeUtilsProvider { return path; } } + +export class CoreMimetypeUtils extends makeSingleton(CoreMimetypeUtilsProvider) {} diff --git a/src/providers/utils/text.ts b/src/providers/utils/text.ts index 8565b6dfc..66e617091 100644 --- a/src/providers/utils/text.ts +++ b/src/providers/utils/text.ts @@ -17,6 +17,7 @@ import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { ModalController, Platform } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreLangProvider } from '../lang'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Different type of errors the app can treat. @@ -1106,3 +1107,5 @@ export class CoreTextUtilsProvider { return _unserialize((data + ''), 0)[2]; } } + +export class CoreTextUtils extends makeSingleton(CoreTextUtilsProvider) {} diff --git a/src/providers/utils/time.ts b/src/providers/utils/time.ts index ca0d464fe..470c30f44 100644 --- a/src/providers/utils/time.ts +++ b/src/providers/utils/time.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import * as moment from 'moment'; import { CoreConstants } from '@core/constants'; +import { makeSingleton } from '@singletons/core.singletons'; /* * "Utils" service with helper functions for date and time. @@ -353,3 +354,5 @@ export class CoreTimeUtilsProvider { } } } + +export class CoreTimeUtils extends makeSingleton(CoreTimeUtilsProvider) {} diff --git a/src/providers/utils/url.ts b/src/providers/utils/url.ts index 5c8c0e35a..26e2bb691 100644 --- a/src/providers/utils/url.ts +++ b/src/providers/utils/url.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreLangProvider } from '../lang'; import { CoreTextUtilsProvider } from './text'; +import { makeSingleton } from '@singletons/core.singletons'; /* * "Utils" service with helper functions for URLs. @@ -498,3 +499,5 @@ export class CoreUrlUtilsProvider { return url; } } + +export class CoreUrlUtils extends makeSingleton(CoreUrlUtilsProvider) {} diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index bedd0e4b0..f1235e375 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -27,6 +27,7 @@ import { CoreLoggerProvider } from '../logger'; import { TranslateService } from '@ngx-translate/core'; import { CoreLangProvider } from '../lang'; import { CoreWSProvider, CoreWSError } from '../ws'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Deferred promise. It's similar to the result of $q.defer() in AngularJS. @@ -1393,3 +1394,5 @@ export class CoreUtilsProvider { return filtered; } } + +export class CoreUtils extends makeSingleton(CoreUtilsProvider) {} diff --git a/src/providers/ws.ts b/src/providers/ws.ts index 8440316ae..9f8743a86 100644 --- a/src/providers/ws.ts +++ b/src/providers/ws.ts @@ -24,6 +24,7 @@ import { CoreTextUtilsProvider } from './utils/text'; import { CoreConstants } from '@core/constants'; import { Md5 } from 'ts-md5/dist/md5'; import { CoreInterceptor } from '@classes/interceptor'; +import { makeSingleton } from '@singletons/core.singletons'; /** * PreSets accepted by the WS call. @@ -879,6 +880,8 @@ export class CoreWSProvider { } } +export class CoreWS extends makeSingleton(CoreWSProvider) {} + /** * Error returned by a WS call. */ diff --git a/src/singletons/core.singletons.ts b/src/singletons/core.singletons.ts new file mode 100644 index 000000000..7eacfe6bc --- /dev/null +++ b/src/singletons/core.singletons.ts @@ -0,0 +1,49 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { AlertController, App } from 'ionic-angular'; +import { Injector } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { HttpClient } from '@angular/common/http'; + +import { CoreSingletonsFactory, CoreInjectionToken, CoreSingletonClass } from '@classes/singletons-factory'; + +const factory = new CoreSingletonsFactory(); + +/** + * Set the injector that will be used to resolve instances in the singletons of this module. + * + * @param injector Module injector. + */ +export function setSingletonsInjector(injector: Injector): void { + factory.setInjector(injector); +} + +/** + * Make a singleton for this module. + * + * @param injectionToken Injection token used to resolve the singleton instance. This is usually the service class if the + * provider was defined using a class or the string used in the `provide` key if it was defined using an object. + */ +export function makeSingleton(injectionToken: CoreInjectionToken): CoreSingletonClass { + return factory.makeSingleton(injectionToken); +} + +export class Translate extends makeSingleton(TranslateService) {} + +export class Alerts extends makeSingleton(AlertController) {} + +export class Ionic extends makeSingleton(App) {} + +export class Http extends makeSingleton(HttpClient) {} diff --git a/src/classes/utils/url.ts b/src/singletons/url.ts similarity index 100% rename from src/classes/utils/url.ts rename to src/singletons/url.ts diff --git a/tsconfig.json b/tsconfig.json index 84a65ecd5..22454c549 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,8 @@ "@providers/*": ["providers/*"], "@components/*": ["components/*"], "@directives/*": ["directives/*"], - "@pipes/*": ["pipes/*"] + "@pipes/*": ["pipes/*"], + "@singletons/*": ["singletons/*"] }, "typeRoots": [ "node_modules/@types" From 38e3e88ed6e54d8cacf6002fc8c1619815da7cfb Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 31 Mar 2020 09:03:02 +0200 Subject: [PATCH 014/166] MOBILE-3101 core: Use same scheme in Android and iOS --- config.xml | 3 +++ src/index.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.xml b/config.xml index cc8259460..a9d1ff306 100644 --- a/config.xml +++ b/config.xml @@ -8,6 +8,7 @@ + @@ -38,6 +39,8 @@ + + diff --git a/src/index.html b/src/index.html index fa07d2622..78f94ce36 100644 --- a/src/index.html +++ b/src/index.html @@ -4,7 +4,7 @@ Moodle Desktop - + From 47decde520ca321cc516ffc861f230a0665b76a8 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 23 Mar 2020 10:57:49 +0100 Subject: [PATCH 015/166] MOBILE-3101 core: Fix embedded files --- src/components/iframe/iframe.ts | 8 +- src/config.json | 3 +- src/directives/external-content.ts | 131 +++++++++++++++-------------- src/directives/format-text.ts | 41 ++++----- src/directives/link.ts | 2 +- src/providers/file.ts | 27 ++++++ src/providers/filepool.ts | 23 +++-- src/providers/utils/iframe.ts | 10 +-- src/providers/utils/mimetype.ts | 3 +- src/providers/utils/url.ts | 21 +++++ src/providers/utils/utils.ts | 8 +- 11 files changed, 173 insertions(+), 104 deletions(-) diff --git a/src/components/iframe/iframe.ts b/src/components/iframe/iframe.ts index 516012a8f..5e98b10f7 100644 --- a/src/components/iframe/iframe.ts +++ b/src/components/iframe/iframe.ts @@ -17,6 +17,7 @@ import { } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { NavController } from 'ionic-angular'; +import { CoreFileProvider } from '@providers/file'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; @@ -49,7 +50,8 @@ export class CoreIframeComponent implements OnInit, OnChanges { protected navCtrl: NavController, protected urlUtils: CoreUrlUtilsProvider, protected utils: CoreUtilsProvider, - @Optional() protected svComponent: CoreSplitViewComponent) { + @Optional() protected svComponent: CoreSplitViewComponent, + protected fileProvider: CoreFileProvider) { this.logger = logger.getInstance('CoreIframe'); this.loaded = new EventEmitter(); @@ -93,8 +95,8 @@ export class CoreIframeComponent implements OnInit, OnChanges { */ ngOnChanges(changes: {[name: string]: SimpleChange }): void { if (changes.src) { - const youtubeUrl = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue); - this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(youtubeUrl || changes.src.currentValue); + const url = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue; + this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.fileProvider.convertFileSrc(url)); } } } diff --git a/src/config.json b/src/config.json index 50897768a..a81136800 100644 --- a/src/config.json +++ b/src/config.json @@ -93,5 +93,6 @@ "statusbarbgremotetheme": "#000000", "statusbarlighttextremotetheme": true, "enableanalytics": false, - "forceColorScheme": "" + "forceColorScheme": "", + "webviewscheme": "moodleappfs" } \ No newline at end of file diff --git a/src/directives/external-content.ts b/src/directives/external-content.ts index 1879772c7..47b4c776e 100644 --- a/src/directives/external-content.ts +++ b/src/directives/external-content.ts @@ -16,6 +16,7 @@ import { Directive, Input, AfterViewInit, ElementRef, OnChanges, SimpleChange, O import { Platform } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; import { CoreLoggerProvider } from '@providers/logger'; +import { CoreFile } from '@providers/file'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -52,9 +53,15 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges { invalid = false; - constructor(element: ElementRef, logger: CoreLoggerProvider, private filepoolProvider: CoreFilepoolProvider, - private platform: Platform, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, - private urlUtils: CoreUrlUtilsProvider, private appProvider: CoreAppProvider, private utils: CoreUtilsProvider) { + constructor(element: ElementRef, + logger: CoreLoggerProvider, + protected filepoolProvider: CoreFilepoolProvider, + protected platform: Platform, + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider, + protected urlUtils: CoreUrlUtilsProvider, + protected appProvider: CoreAppProvider, + protected utils: CoreUtilsProvider) { // This directive can be added dynamically. In that case, the first param is the HTMLElement. this.element = element.nativeElement || element; this.logger = logger.getInstance('CoreExternalContentDirective'); @@ -179,7 +186,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges { * @param siteId Site ID. * @return Promise resolved if the element is successfully treated. */ - protected handleExternalContent(targetAttr: string, url: string, siteId?: string): Promise { + protected async handleExternalContent(targetAttr: string, url: string, siteId?: string): Promise { const tagName = this.element.tagName; @@ -214,72 +221,70 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges { this.addSource(url); } - return Promise.reject(null); + throw 'Non-downloadable URL'; } - // Get the webservice pluginfile URL, we ignore failures here. - return this.sitesProvider.getSite(siteId).then((site) => { - if (!site.canDownloadFiles() && this.urlUtils.isPluginFileUrl(url)) { - this.element.parentElement.removeChild(this.element); // Remove element since it'll be broken. + const site = await this.sitesProvider.getSite(siteId); - return Promise.reject(null); + if (!site.canDownloadFiles() && this.urlUtils.isPluginFileUrl(url)) { + this.element.parentElement.removeChild(this.element); // Remove element since it'll be broken. + + throw 'Site doesn\'t allow downloading files.'; + } + + // Download images, tracks and posters if size is unknown. + const dwnUnknown = tagName == 'IMG' || tagName == 'TRACK' || targetAttr == 'poster'; + let finalUrl: string; + + if (targetAttr === 'src' && tagName !== 'SOURCE' && tagName !== 'TRACK' && tagName !== 'VIDEO' && tagName !== 'AUDIO') { + finalUrl = await this.filepoolProvider.getSrcByUrl(siteId, url, this.component, this.componentId, 0, true, dwnUnknown); + } else { + finalUrl = await this.filepoolProvider.getUrlByUrl(siteId, url, this.component, this.componentId, 0, true, dwnUnknown); + + finalUrl = CoreFile.instance.convertFileSrc(finalUrl); + } + + if (finalUrl.match(/^https?:\/\//i)) { + /* In iOS, if we use the same URL in embedded file and background download then the download only + downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */ + finalUrl = finalUrl + '#moodlemobile-embedded'; + } + + this.logger.debug('Using URL ' + finalUrl + ' for ' + url); + if (tagName === 'SOURCE') { + // The browser does not catch changes in SRC, we need to add a new source. + this.addSource(finalUrl); + } else { + if (tagName === 'IMG') { + this.loaded = false; + this.waitForLoad(); + } + this.element.setAttribute(targetAttr, finalUrl); + this.element.setAttribute('data-original-' + targetAttr, url); + } + + // Set events to download big files (not downloaded automatically). + if (finalUrl.indexOf('http') === 0 && targetAttr != 'poster' && + (tagName == 'VIDEO' || tagName == 'AUDIO' || tagName == 'A' || tagName == 'SOURCE')) { + const eventName = tagName == 'A' ? 'click' : 'play'; + let clickableEl = this.element; + + if (tagName == 'SOURCE') { + clickableEl = this.domUtils.closest(this.element, 'video,audio'); + if (!clickableEl) { + return; + } } - // Download images, tracks and posters if size is unknown. - const dwnUnknown = tagName == 'IMG' || tagName == 'TRACK' || targetAttr == 'poster'; - let promise; - - if (targetAttr === 'src' && tagName !== 'SOURCE' && tagName !== 'TRACK' && tagName !== 'VIDEO' && - tagName !== 'AUDIO') { - promise = this.filepoolProvider.getSrcByUrl(siteId, url, this.component, this.componentId, 0, true, dwnUnknown); - } else { - promise = this.filepoolProvider.getUrlByUrl(siteId, url, this.component, this.componentId, 0, true, dwnUnknown); - } - - return promise.then((finalUrl) => { - if (finalUrl.match(/^https?:\/\//i)) { - /* In iOS, if we use the same URL in embedded file and background download then the download only - downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */ - finalUrl = finalUrl + '#moodlemobile-embedded'; - } - - this.logger.debug('Using URL ' + finalUrl + ' for ' + url); - if (tagName === 'SOURCE') { - // The browser does not catch changes in SRC, we need to add a new source. - this.addSource(finalUrl); - } else { - if (tagName === 'IMG') { - this.loaded = false; - this.waitForLoad(); - } - this.element.setAttribute(targetAttr, finalUrl); - this.element.setAttribute('data-original-' + targetAttr, url); - } - - // Set events to download big files (not downloaded automatically). - if (finalUrl.indexOf('http') === 0 && targetAttr != 'poster' && - (tagName == 'VIDEO' || tagName == 'AUDIO' || tagName == 'A' || tagName == 'SOURCE')) { - const eventName = tagName == 'A' ? 'click' : 'play'; - let clickableEl = this.element; - - if (tagName == 'SOURCE') { - clickableEl = this.domUtils.closest(this.element, 'video,audio'); - if (!clickableEl) { - return; - } - } - - clickableEl.addEventListener(eventName, () => { - // User played media or opened a downloadable link. - // Download the file if in wifi and it hasn't been downloaded already (for big files). - if (this.appProvider.isWifi()) { - // We aren't using the result, so it doesn't matter which of the 2 functions we call. - this.filepoolProvider.getUrlByUrl(siteId, url, this.component, this.componentId, 0, false); - } - }); + clickableEl.addEventListener(eventName, () => { + // User played media or opened a downloadable link. + // Download the file if in wifi and it hasn't been downloaded already (for big files). + if (this.appProvider.isWifi()) { + // We aren't using the result, so it doesn't matter which of the 2 functions we call. + this.filepoolProvider.getUrlByUrl(siteId, url, this.component, this.componentId, 0, false); } }); - }); + } } /** diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index 7057b269f..9dfe8a746 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -74,26 +74,27 @@ export class CoreFormatTextDirective implements OnChanges { protected loadingChangedListener; constructor(element: ElementRef, - private sitesProvider: CoreSitesProvider, - private domUtils: CoreDomUtilsProvider, - private textUtils: CoreTextUtilsProvider, - private translate: TranslateService, - private platform: Platform, - private utils: CoreUtilsProvider, - private urlUtils: CoreUrlUtilsProvider, - private loggerProvider: CoreLoggerProvider, - private filepoolProvider: CoreFilepoolProvider, - private appProvider: CoreAppProvider, - private contentLinksHelper: CoreContentLinksHelperProvider, - @Optional() private navCtrl: NavController, - @Optional() private content: Content, @Optional() - private svComponent: CoreSplitViewComponent, - private iframeUtils: CoreIframeUtilsProvider, - private eventsProvider: CoreEventsProvider, - private filterProvider: CoreFilterProvider, - private filterHelper: CoreFilterHelperProvider, - private filterDelegate: CoreFilterDelegate, - private viewContainerRef: ViewContainerRef) { + protected sitesProvider: CoreSitesProvider, + protected domUtils: CoreDomUtilsProvider, + protected textUtils: CoreTextUtilsProvider, + protected translate: TranslateService, + protected platform: Platform, + protected utils: CoreUtilsProvider, + protected urlUtils: CoreUrlUtilsProvider, + protected loggerProvider: CoreLoggerProvider, + protected filepoolProvider: CoreFilepoolProvider, + protected appProvider: CoreAppProvider, + protected contentLinksHelper: CoreContentLinksHelperProvider, + @Optional() protected navCtrl: NavController, + @Optional() protected content: Content, @Optional() + protected svComponent: CoreSplitViewComponent, + protected iframeUtils: CoreIframeUtilsProvider, + protected eventsProvider: CoreEventsProvider, + protected filterProvider: CoreFilterProvider, + protected filterHelper: CoreFilterHelperProvider, + protected filterDelegate: CoreFilterDelegate, + protected viewContainerRef: ViewContainerRef, + ) { this.element = element.nativeElement; this.element.classList.add('opacity-hide'); // Hide contents until they're treated. diff --git a/src/directives/link.ts b/src/directives/link.ts index 5ccfe3c64..5d85e2199 100644 --- a/src/directives/link.ts +++ b/src/directives/link.ts @@ -92,7 +92,7 @@ export class CoreLinkDirective implements OnInit { protected navigate(href: string): void { const contentLinksScheme = CoreConfigConstants.customurlscheme + '://link='; - if (href.indexOf('cdvfile://') === 0 || href.indexOf('file://') === 0 || href.indexOf('filesystem:') === 0) { + if (this.urlUtils.isLocalFileUrl(href)) { // We have a local file. this.utils.openFile(href).catch((error) => { this.domUtils.showErrorModal(error); diff --git a/src/providers/file.ts b/src/providers/file.ts index 1af76887e..1bee27880 100644 --- a/src/providers/file.ts +++ b/src/providers/file.ts @@ -20,6 +20,7 @@ import { CoreAppProvider } from './app'; import { CoreLoggerProvider } from './logger'; import { CoreMimetypeUtilsProvider } from './utils/mimetype'; import { CoreTextUtilsProvider } from './utils/text'; +import { CoreConfigConstants } from '../configconstants'; import { Zip } from '@ionic-native/zip'; import { makeSingleton } from '@singletons/core.singletons'; @@ -946,6 +947,7 @@ export class CoreFileProvider { /** * Get the internal URL of a file. + * Please notice that with WKWebView these URLs no longer work in mobile. Use fileEntry.toURL() along with convertFileSrc. * * @param fileEntry File Entry. * @return Internal URL. @@ -1270,6 +1272,31 @@ export class CoreFileProvider { return window.location.href; } + + /** + * Helper function to call Ionic WebView convertFileSrc only in the needed platforms. + * This is needed to make files work with the Ionic WebView plugin. + * + * @param src Source to convert. + * @return Converted src. + */ + convertFileSrc(src: string): string { + return this.appProvider.isMobile() ? ( window).Ionic.WebView.convertFileSrc(src) : src; + } + + /** + * Undo the conversion of convertFileSrc. + * + * @param src Source to unconvert. + * @return Unconverted src. + */ + unconvertFileSrc(src: string): string { + if (!this.appProvider.isMobile()) { + return src; + } + + return src.replace(CoreConfigConstants.webviewscheme + '://localhost/_app_file_', 'file://'); + } } export class CoreFile extends makeSingleton(CoreFileProvider) {} diff --git a/src/providers/filepool.ts b/src/providers/filepool.ts index 40a5c0d56..3d4ff5bfe 100644 --- a/src/providers/filepool.ts +++ b/src/providers/filepool.ts @@ -412,11 +412,21 @@ export class CoreFilepoolProvider { protected packagesPromises = {}; protected filePromises: { [s: string]: { [s: string]: Promise } } = {}; - constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider, - private sitesProvider: CoreSitesProvider, private wsProvider: CoreWSProvider, private textUtils: CoreTextUtilsProvider, - private utils: CoreUtilsProvider, private mimeUtils: CoreMimetypeUtilsProvider, private urlUtils: CoreUrlUtilsProvider, - private timeUtils: CoreTimeUtilsProvider, private eventsProvider: CoreEventsProvider, initDelegate: CoreInitDelegate, - network: Network, private pluginFileDelegate: CorePluginFileDelegate, private domUtils: CoreDomUtilsProvider, + constructor(logger: CoreLoggerProvider, + protected appProvider: CoreAppProvider, + protected fileProvider: CoreFileProvider, + protected sitesProvider: CoreSitesProvider, + protected wsProvider: CoreWSProvider, + protected textUtils: CoreTextUtilsProvider, + protected utils: CoreUtilsProvider, + protected mimeUtils: CoreMimetypeUtilsProvider, + protected urlUtils: CoreUrlUtilsProvider, + protected timeUtils: CoreTimeUtilsProvider, + protected eventsProvider: CoreEventsProvider, + initDelegate: CoreInitDelegate, + network: Network, + protected pluginFileDelegate: CorePluginFileDelegate, + protected domUtils: CoreDomUtilsProvider, zone: NgZone) { this.logger = logger.getInstance('CoreFilepoolProvider'); @@ -1796,8 +1806,7 @@ export class CoreFilepoolProvider { if (this.fileProvider.isAvailable()) { return Promise.resolve(this.getFilePath(siteId, fileId)).then((path) => { return this.fileProvider.getFile(path).then((fileEntry) => { - // We use toInternalURL so images are loaded in iOS8 using img HTML tags. - return this.fileProvider.getInternalURL(fileEntry); + return this.fileProvider.convertFileSrc(fileEntry.toURL()); }); }); } diff --git a/src/providers/utils/iframe.ts b/src/providers/utils/iframe.ts index 5b82ebab2..69c4251f8 100644 --- a/src/providers/utils/iframe.ts +++ b/src/providers/utils/iframe.ts @@ -225,7 +225,7 @@ export class CoreIframeUtilsProvider { } else { element.setAttribute('src', url); } - } else if (url.indexOf('cdvfile://') === 0 || url.indexOf('file://') === 0) { + } else if (this.urlUtils.isLocalFileUrl(url)) { // It's a local file. this.utils.openFile(url).catch((error) => { this.domUtils.showErrorModal(error); @@ -353,16 +353,14 @@ export class CoreIframeUtilsProvider { return; } - if (scheme && scheme != 'file' && scheme != 'filesystem') { + if (!this.urlUtils.isLocalFileUrlScheme(scheme)) { // Scheme suggests it's an external resource. event.preventDefault(); - const frameSrc = ( element).src || ( element).data, - frameScheme = this.urlUtils.getUrlScheme(frameSrc); + const frameSrc = ( element).src || ( element).data; // If the frame is not local, check the target to identify how to treat the link. - if (frameScheme && frameScheme != 'file' && frameScheme != 'filesystem' && - (!link.target || link.target == '_self')) { + if (!this.urlUtils.isLocalFileUrl(frameSrc) && (!link.target || link.target == '_self')) { // Load the link inside the frame itself. if (element.tagName.toLowerCase() == 'object') { element.setAttribute('data', link.href); diff --git a/src/providers/utils/mimetype.ts b/src/providers/utils/mimetype.ts index 4b256196c..eae580a46 100644 --- a/src/providers/utils/mimetype.ts +++ b/src/providers/utils/mimetype.ts @@ -14,6 +14,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; +import { CoreFile } from '../file'; import { CoreLoggerProvider } from '../logger'; import { TranslateService } from '@ngx-translate/core'; import { CoreTextUtilsProvider } from './text'; @@ -165,7 +166,7 @@ export class CoreMimetypeUtilsProvider { if (this.canBeEmbedded(ext)) { file.embedType = this.getExtensionType(ext); - path = path || file.fileurl || (file.toURL && file.toURL()); + path = CoreFile.instance.convertFileSrc(path || file.fileurl || (file.toURL && file.toURL())); if (file.embedType == 'image') { return ''; diff --git a/src/providers/utils/url.ts b/src/providers/utils/url.ts index 26e2bb691..f9b07929b 100644 --- a/src/providers/utils/url.ts +++ b/src/providers/utils/url.ts @@ -16,6 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreLangProvider } from '../lang'; import { CoreTextUtilsProvider } from './text'; import { makeSingleton } from '@singletons/core.singletons'; +import { CoreConfigConstants } from '../../configconstants'; /* * "Utils" service with helper functions for URLs. @@ -424,6 +425,26 @@ export class CoreUrlUtilsProvider { return /^https?\:\/\/.+/i.test(url); } + /** + * Check whether an URL belongs to a local file. + * + * @param url URL to check. + * @return Whether the URL belongs to a local file. + */ + isLocalFileUrl(url: string): boolean { + return this.isLocalFileUrlScheme(this.getUrlScheme(url)); + } + + /** + * Check whether a URL scheme belongs to a local file. + * + * @param scheme Scheme to check. + * @return Whether the scheme belongs to a local file. + */ + isLocalFileUrlScheme(scheme: string): boolean { + return scheme == 'cdvfile' || scheme == 'file' || scheme == 'filesystem' || scheme == CoreConfigConstants.webviewscheme; + } + /** * Returns if a URL is a pluginfile URL. * diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index f1235e375..9ce7d0ea8 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -27,6 +27,7 @@ import { CoreLoggerProvider } from '../logger'; import { TranslateService } from '@ngx-translate/core'; import { CoreLangProvider } from '../lang'; import { CoreWSProvider, CoreWSError } from '../ws'; +import { CoreFile } from '../file'; import { makeSingleton } from '@singletons/core.singletons'; /** @@ -863,8 +864,11 @@ export class CoreUtilsProvider { * @return Promise resolved when done. */ openFile(path: string): Promise { - const extension = this.mimetypeUtils.getFileExtension(path), - mimetype = this.mimetypeUtils.getMimeType(extension); + // Convert the path to a native path if needed. + path = CoreFile.instance.unconvertFileSrc(path); + + const extension = this.mimetypeUtils.getFileExtension(path); + const mimetype = this.mimetypeUtils.getMimeType(extension); // Path needs to be decoded, the file won't be opened if the path has %20 instead of spaces and so. try { From 8b9635e6757cc188fdc94c7f71a102b5ea94ba3e Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 26 Mar 2020 15:09:42 +0100 Subject: [PATCH 016/166] MOBILE-3101 core: Install and use cordova-plugin-advanced-http --- config.xml | 1 + package-lock.json | 10 ++ package.json | 7 +- src/classes/native-to-angular-http.ts | 98 +++++++++++++ src/classes/site.ts | 90 ++++++------ src/providers/ws.ts | 196 +++++++++++++++++++++++--- 6 files changed, 340 insertions(+), 62 deletions(-) create mode 100644 src/classes/native-to-angular-http.ts diff --git a/config.xml b/config.xml index a9d1ff306..fc0883b59 100644 --- a/config.xml +++ b/config.xml @@ -182,6 +182,7 @@ + diff --git a/package-lock.json b/package-lock.json index 36872c57b..07c1ea7d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -147,6 +147,11 @@ "resolved": "https://registry.npmjs.org/@ionic-native/globalization/-/globalization-4.20.0.tgz", "integrity": "sha512-zyxaW+vZb1OHeDgGbrZHQe3hy30K4YeKjGr8KNGcwq+k2ZHkfqo/H6XIwf2m/UlFTgacvdR9XZtfP+6N0suybg==" }, + "@ionic-native/http": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@ionic-native/http/-/http-4.20.0.tgz", + "integrity": "sha512-DF+Y1oYoHTv9Y22a2jLgniOmj9Twba+9j8rzHA4xboVT2HpB6bsBSWOktdAXDVjoajXiLsA/u7fh6YD8//NVGg==" + }, "@ionic-native/in-app-browser": { "version": "4.20.0", "resolved": "https://registry.npmjs.org/@ionic-native/in-app-browser/-/in-app-browser-4.20.0.tgz", @@ -2621,6 +2626,11 @@ } } }, + "cordova-plugin-advanced-http": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/cordova-plugin-advanced-http/-/cordova-plugin-advanced-http-2.4.1.tgz", + "integrity": "sha512-6G8MTy/d02jE6n3Y9CVyCtD5hZGiBb+/dR2AIzhKN1RGGz38g1D2C8yE4MqHRvnmry6k/KHQWT1MsHNXrjouXQ==" + }, "cordova-plugin-badge": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/cordova-plugin-badge/-/cordova-plugin-badge-0.8.8.tgz", diff --git a/package.json b/package.json index 2d3f35c34..ecbd217aa 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@ionic-native/file-transfer": "4.20.0", "@ionic-native/geolocation": "4.20.0", "@ionic-native/globalization": "4.20.0", + "@ionic-native/http": "^4.20.0", "@ionic-native/in-app-browser": "4.20.0", "@ionic-native/keyboard": "4.20.0", "@ionic-native/local-notifications": "4.20.0", @@ -81,6 +82,7 @@ "cordova-android-support-gradle-release": "3.0.1", "cordova-clipboard": "1.3.0", "cordova-ios": "5.1.1", + "cordova-plugin-advanced-http": "2.4.1", "cordova-plugin-badge": "0.8.8", "cordova-plugin-camera": "4.1.0", "cordova-plugin-customurlscheme": "5.0.0", @@ -187,7 +189,10 @@ "cordova-plugin-geolocation": { "GEOLOCATION_USAGE_DESCRIPTION": "To locate you" }, - "cordova-plugin-ionic-webview": {} + "cordova-plugin-ionic-webview": {}, + "cordova-plugin-advanced-http": { + "OKHTTP_VERSION": "3.10.0" + } } }, "main": "desktop/electron.js", diff --git a/src/classes/native-to-angular-http.ts b/src/classes/native-to-angular-http.ts new file mode 100644 index 000000000..e21e7eb7e --- /dev/null +++ b/src/classes/native-to-angular-http.ts @@ -0,0 +1,98 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { HttpResponse as AngularHttpResponse, HttpHeaders } from '@angular/common/http'; +import { HTTPResponse as NativeHttpResponse } from '@ionic-native/http'; + +const HTTP_STATUS_MESSAGES = { + 100: 'Continue', + 101: 'Switching Protocol', + 102: 'Processing', + 103: 'Early Hints', + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + 207: 'Multi-Status', + 208: 'Already Reported', + 226: 'IM Used', + 300: 'Multiple Choice', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: 'unused', + 307: 'Temporary Redirect', + 308: 'Permanent Redirect', + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Payload Too Large', + 414: 'URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Range Not Satisfiable', + 417: 'Expectation Failed', + 418: 'I\'m a teapot', + 421: 'Misdirected Request', + 422: 'Unprocessable Entity', + 423: 'Locked', + 424: 'Failed Dependency', + 425: 'Too Early', + 426: 'Upgrade Required', + 428: 'Precondition Required', + 429: 'Too Many Requests', + 431: 'Request Header Fields Too Large', + 451: 'Unavailable For Legal Reasons', + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', + 506: 'Variant Also Negotiates', + 507: 'Insufficient Storage', + 508: 'Loop Detected', + 510: 'Not Extended', + 511: 'Network Authentication Required', +}; + +/** + * Class that adapts a Cordova plugin http response to an Angular http response. + */ +export class CoreNativeToAngularHttpResponse extends AngularHttpResponse { + + constructor(protected nativeResponse: NativeHttpResponse) { + super({ + body: nativeResponse.data, + headers: new HttpHeaders(nativeResponse.headers), + status: nativeResponse.status, + statusText: HTTP_STATUS_MESSAGES[nativeResponse.status] || '', + url: nativeResponse.url || '' + }); + } +} diff --git a/src/classes/site.ts b/src/classes/site.ts index 54b2dd294..befacd29e 100644 --- a/src/classes/site.ts +++ b/src/classes/site.ts @@ -14,7 +14,6 @@ import { Injector } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { HttpClient } from '@angular/common/http'; import { SQLiteDB } from './sqlitedb'; import { CoreAppProvider } from '@providers/app'; import { CoreDbProvider } from '@providers/db'; @@ -190,7 +189,6 @@ export class CoreSite { protected domUtils: CoreDomUtilsProvider; protected eventsProvider: CoreEventsProvider; protected fileProvider: CoreFileProvider; - protected http: HttpClient; protected textUtils: CoreTextUtilsProvider; protected timeUtils: CoreTimeUtilsProvider; protected translate: TranslateService; @@ -256,7 +254,6 @@ export class CoreSite { this.domUtils = injector.get(CoreDomUtilsProvider); this.eventsProvider = injector.get(CoreEventsProvider); this.fileProvider = injector.get(CoreFileProvider); - this.http = injector.get(HttpClient); this.textUtils = injector.get(CoreTextUtilsProvider); this.timeUtils = injector.get(CoreTimeUtilsProvider); this.translate = injector.get(TranslateService); @@ -1357,55 +1354,62 @@ export class CoreSite { * @param retrying True if we're retrying the check. * @return Promise resolved when the check is done. */ - checkLocalMobilePlugin(retrying?: boolean): Promise { + async checkLocalMobilePlugin(retrying?: boolean): Promise { const checkUrl = this.siteUrl + '/local/mobile/check.php', service = CoreConfigConstants.wsextservice; if (!service) { // External service not defined. - return Promise.resolve({ code: 0 }); + return { code: 0 }; } - const promise = this.http.post(checkUrl, { service: service }).timeout(this.wsProvider.getRequestTimeout()).toPromise(); + let data; - return promise.then((data: any) => { - if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') { - if (!retrying) { - this.siteUrl = this.urlUtils.addOrRemoveWWW(this.siteUrl); + try { + const response = await this.wsProvider.sendHTTPRequest(checkUrl, { + method: 'post', + data: { service: service }, + }); - return this.checkLocalMobilePlugin(true); - } else { - return Promise.reject(data.error); - } - } else if (typeof data == 'undefined' || typeof data.code == 'undefined') { - // The local_mobile returned something we didn't expect. Let's assume it's not installed. - return { code: 0, warning: 'core.login.localmobileunexpectedresponse' }; - } - - const code = parseInt(data.code, 10); - if (data.error) { - switch (code) { - case 1: - // Site in maintenance mode. - return Promise.reject(this.translate.instant('core.login.siteinmaintenance')); - case 2: - // Web services not enabled. - return Promise.reject(this.translate.instant('core.login.webservicesnotenabled')); - case 3: - // Extended service not enabled, but the official is enabled. - return { code: 0 }; - case 4: - // Neither extended or official services enabled. - return Promise.reject(this.translate.instant('core.login.mobileservicesnotenabled')); - default: - return Promise.reject(this.translate.instant('core.unexpectederror')); - } - } else { - return { code: code, service: service, coreSupported: !!data.coresupported }; - } - }, () => { + data = response.body; + } catch (ex) { return { code: 0 }; - }); + } + + if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') { + if (!retrying) { + this.siteUrl = this.urlUtils.addOrRemoveWWW(this.siteUrl); + + return this.checkLocalMobilePlugin(true); + } else { + throw data.error; + } + } else if (typeof data == 'undefined' || typeof data.code == 'undefined') { + // The local_mobile returned something we didn't expect. Let's assume it's not installed. + return { code: 0, warning: 'core.login.localmobileunexpectedresponse' }; + } + + const code = parseInt(data.code, 10); + if (data.error) { + switch (code) { + case 1: + // Site in maintenance mode. + throw this.translate.instant('core.login.siteinmaintenance'); + case 2: + // Web services not enabled. + throw this.translate.instant('core.login.webservicesnotenabled'); + case 3: + // Extended service not enabled, but the official is enabled. + return { code: 0 }; + case 4: + // Neither extended or official services enabled. + throw this.translate.instant('core.login.mobileservicesnotenabled'); + default: + throw this.translate.instant('core.unexpectederror'); + } + } else { + return { code: code, service: service, coreSupported: !!data.coresupported }; + } } /** @@ -1970,7 +1974,7 @@ export class CoreSite { url = this.fixPluginfileURL(url); this.tokenPluginFileWorksPromise = this.wsProvider.performHead(url).then((result) => { - return result.ok; + return result.status >= 200 && result.status < 300; }).catch((error) => { // Error performing head request. return false; diff --git a/src/providers/ws.ts b/src/providers/ws.ts index 9f8743a86..57c91985a 100644 --- a/src/providers/ws.ts +++ b/src/providers/ws.ts @@ -25,6 +25,8 @@ import { CoreConstants } from '@core/constants'; import { Md5 } from 'ts-md5/dist/md5'; import { CoreInterceptor } from '@classes/interceptor'; import { makeSingleton } from '@singletons/core.singletons'; +import { Observable } from 'rxjs/Observable'; +import { CoreNativeToAngularHttpResponse } from '@classes/native-to-angular-http'; /** * PreSets accepted by the WS call. @@ -81,6 +83,61 @@ export interface CoreWSAjaxPreSets { useGet?: boolean; } +/** + * Options for HTTP requests. + */ +export type HttpRequestOptions = { + /** + * The HTTP method. + */ + method: string; + + /** + * Payload to send to the server. Only applicable on post, put or patch methods. + */ + data?: any; + + /** + * Query params to be appended to the URL (only applicable on get, head, delete, upload or download methods). + */ + params?: any; + + /** + * Response type. Defaults to json. + */ + responseType?: 'json' | 'text' | 'arraybuffer' | 'blob'; + + /** + * Timeout for the request in seconds. If undefined, the default value will be used. If null, no timeout. + */ + timeout?: number | null; + + /** + * Serializer to use. Defaults to 'urlencoded'. Only for mobile environments. + */ + serializer?: string; + + /** + * Whether to follow redirects. Defaults to true. Only for mobile environments. + */ + followRedirect?: boolean; + + /** + * Headers. Only for mobile environments. + */ + headers?: {[name: string]: string}; + + /** + * File paths to use for upload or download. Only for mobile environments. + */ + filePath?: string; + + /** + * Name to use during upload. Only for mobile environments. + */ + name?: string; +}; + /** * This service allows performing WS calls and download/upload files. */ @@ -377,8 +434,8 @@ export class CoreWSProvider { return Promise.resolve(this.mimeTypeCache[url]); } - return this.performHead(url).then((data) => { - let mimeType = data.headers.get('Content-Type'); + return this.performHead(url).then((response) => { + let mimeType = response.headers.get('Content-Type'); if (mimeType) { // Remove "parameters" like charset. mimeType = mimeType.split(';')[0]; @@ -399,8 +456,8 @@ export class CoreWSProvider { * @return Promise resolved with the size or -1 if failure. */ getRemoteFileSize(url: string): Promise { - return this.performHead(url).then((data) => { - const size = parseInt(data.headers.get('Content-Length'), 10); + return this.performHead(url).then((response) => { + const size = parseInt(response.headers.get('Content-Length'), 10); if (size) { return size; @@ -463,12 +520,12 @@ export class CoreWSProvider { preSets.responseExpected = true; } - const script = preSets.noLogin ? 'service-nologin.php' : 'service.php', - ajaxData = JSON.stringify([{ - index: 0, - methodname: method, - args: this.convertValuesToString(data) - }]); + const script = preSets.noLogin ? 'service-nologin.php' : 'service.php'; + const ajaxData = [{ + index: 0, + methodname: method, + args: this.convertValuesToString(data) + }]; // The info= parameter has no function. It is just to help with debugging. // We call it info to match the parameter name use by Moodle's AMD ajax module. @@ -476,13 +533,22 @@ export class CoreWSProvider { if (preSets.noLogin && preSets.useGet) { // Send params using GET. - siteUrl += '&args=' + encodeURIComponent(ajaxData); - promise = this.http.get(siteUrl).timeout(this.getRequestTimeout()).toPromise(); + siteUrl += '&args=' + encodeURIComponent(JSON.stringify(ajaxData)); + + promise = this.sendHTTPRequest(siteUrl, { + method: 'get', + }); } else { - promise = this.http.post(siteUrl, ajaxData).timeout(this.getRequestTimeout()).toPromise(); + promise = this.sendHTTPRequest(siteUrl, { + method: 'post', + data: ajaxData, + serializer: 'json', + }); } - return promise.then((data: any) => { + return promise.then((response: HttpResponse) => { + let data = response.body; + // Some moodle web services return null. // If the responseExpected value is set then so long as no data is returned, we create a blank object. if (!data && !preSets.responseExpected) { @@ -536,8 +602,11 @@ export class CoreWSProvider { let promise = this.getPromiseHttp('head', url); if (!promise) { - promise = this.http.head(url, {observe: 'response', responseType: 'blob'}).timeout(this.getRequestTimeout()) - .toPromise(); + promise = this.sendHTTPRequest(url, { + method: 'head', + responseType: 'text', + }); + promise = this.setPromiseHttp(promise, 'head', url); } @@ -571,6 +640,7 @@ export class CoreWSProvider { const promise = this.http.post(requestUrl, ajaxData, options).timeout(this.getRequestTimeout()).toPromise(); return promise.then((data: any) => { + // Some moodle web services return null. // If the responseExpected value is set to false, we create a blank object if the response is null. if (!data && !preSets.responseExpected) { @@ -871,13 +941,103 @@ export class CoreWSProvider { */ async getText(url: string): Promise { // Fetch the URL content. - const content = await this.http.get(url, { responseType: 'text' }).toPromise(); + const options: HttpRequestOptions = { + method: 'get', + responseType: 'text', + }; + + const response = await this.sendHTTPRequest(url, options); + + const content = response.body; + if (typeof content !== 'string') { - return Promise.reject(null); + throw 'Error reading content'; } return content; } + + /** + * Send an HTTP request. In mobile devices it will use the cordova plugin. + * + * @param url URL of the request. + * @param options Options for the request. + * @return Promise resolved with the response. + */ + async sendHTTPRequest(url: string, options: HttpRequestOptions): Promise> { + + // Set default values. + options.responseType = options.responseType || 'json'; + options.timeout = typeof options.timeout == 'undefined' ? this.getRequestTimeout() : options.timeout; + + if (this.appProvider.isMobile()) { + // Use the cordova plugin. + if (url.indexOf('file://') === 0) { + // We cannot load local files using the http native plugin. Use file provider instead. + const format = options.responseType == 'json' ? CoreFileProvider.FORMATJSON : CoreFileProvider.FORMATTEXT; + + const content = await this.fileProvider.readFile(url, format); + + return new HttpResponse({ + body: content, + headers: null, + status: 200, + statusText: 'OK', + url: url + }); + } + + return new Promise>((resolve, reject): void => { + // We cannot use Ionic Native plugin because it doesn't have the sendRequest method. + ( cordova).plugin.http.sendRequest(url, options, (response) => { + resolve(new CoreNativeToAngularHttpResponse(response)); + }, reject); + }); + } else { + let observable: Observable; + + // Use Angular's library. + switch (options.method) { + case 'get': + observable = this.http.get(url, { + headers: options.headers, + params: options.params, + observe: 'response', + responseType: options.responseType, + }); + break; + + case 'post': + if (options.serializer == 'json') { + options.data = JSON.stringify(options.data); + } + + observable = this.http.post(url, options.data, { + headers: options.headers, + observe: 'response', + responseType: options.responseType, + }); + break; + + case 'head': + observable = this.http.head(url, { + headers: options.headers, + observe: 'response', + responseType: options.responseType + }); + break; + + default: + return Promise.reject('Method not implemented yet.'); + } + + if (options.timeout) { + observable = observable.timeout(options.timeout); + } + + return observable.toPromise(); + } + } } export class CoreWS extends makeSingleton(CoreWSProvider) {} From 830089e09476728929f04812e4357f794e8d9eb4 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 31 Mar 2020 09:05:13 +0200 Subject: [PATCH 017/166] MOBILE-3101 h5p: Make H5P work with the new webview --- src/core/h5p/providers/h5p.ts | 53 ++++++++++++++++++++++++++++----- src/providers/update-manager.ts | 31 +++++++++++-------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/core/h5p/providers/h5p.ts b/src/core/h5p/providers/h5p.ts index 75fe4b2b9..821509cda 100644 --- a/src/core/h5p/providers/h5p.ts +++ b/src/core/h5p/providers/h5p.ts @@ -27,6 +27,7 @@ import { CoreH5PUtilsProvider } from './utils'; import { CoreH5PContentValidator } from '../classes/content-validator'; import { TranslateService } from '@ngx-translate/core'; import { FileEntry } from '@ionic-native/file'; +import { makeSingleton } from '@singletons/core.singletons'; /** * Service to provide H5P functionalities. @@ -410,7 +411,7 @@ export class CoreH5PProvider { * @return Promise resolved with all of the files content in one string. */ protected concatenateFiles(assets: CoreH5PDependencyAsset[], type: string): Promise { - const basePath = this.fileProvider.getBasePathInstant(); + const basePath = this.fileProvider.convertFileSrc(this.fileProvider.getBasePathInstant()); let content = '', promise = Promise.resolve(); // Use a chain of promises so the order is kept. @@ -495,7 +496,8 @@ export class CoreH5PProvider { const contentId = this.getContentId(id), basePath = this.fileProvider.getBasePathInstant(), - contentUrl = this.textUtils.concatenatePaths(basePath, this.getContentFolderPath(content.folderName, site.getId())); + contentUrl = this.fileProvider.convertFileSrc(this.textUtils.concatenatePaths( + basePath, this.getContentFolderPath(content.folderName, site.getId()))); // Create the settings needed for the content. const contentSettings = { @@ -560,6 +562,40 @@ export class CoreH5PProvider { }); } + /** + * Delete all content indexes of all sites from filesystem. + * + * @return Promise resolved when done. + */ + async deleteAllContentIndexes(): Promise { + const siteIds = await this.sitesProvider.getSitesIds(); + + await Promise.all(siteIds.map((siteId) => this.deleteAllContentIndexesForSite(siteId))); + } + + /** + * Delete all content indexes for a certain site from filesystem. + * + * @param siteId Site ID. If not defined, current site. + * @return Promise resolved when done. + */ + async deleteAllContentIndexesForSite(siteId?: string): Promise { + + const site = await this.sitesProvider.getSite(siteId); + + const records = await site.getDb().getAllRecords(this.CONTENT_TABLE); + + const promises = records.map(async (record) => { + try { + await this.fileProvider.removeFile(this.getContentIndexPath(record.foldername, site.getId())); + } catch (err) { + // Ignore errors, maybe the file doesn't exist. + } + }); + + await Promise.all(promises); + } + /** * Delete cached assets from DB and filesystem. * @@ -1033,12 +1069,11 @@ export class CoreH5PProvider { settings.loadedJs = []; settings.loadedCss = []; - const libUrl = this.getCoreH5PPath(), - relPath = this.urlUtils.removeProtocolAndWWW(libUrl); + const libUrl = this.getCoreH5PPath(); // Add core stylesheets. CoreH5PProvider.STYLES.forEach((style) => { - settings.core.styles.push(relPath + style); + settings.core.styles.push(libUrl + style); cssRequires.push(libUrl + style); }); @@ -1279,8 +1314,10 @@ export class CoreH5PProvider { return { baseUrl: this.fileProvider.getWWWPath(), - url: this.textUtils.concatenatePaths(basePath, this.getExternalH5PFolderPath(site.getId())), - urlLibraries: this.textUtils.concatenatePaths(basePath, this.getLibrariesFolderPath(site.getId())), + url: this.fileProvider.convertFileSrc(this.textUtils.concatenatePaths( + basePath, this.getExternalH5PFolderPath(site.getId()))), + urlLibraries: this.fileProvider.convertFileSrc(this.textUtils.concatenatePaths( + basePath, this.getLibrariesFolderPath(site.getId()))), postUserStatistics: false, ajax: ajaxPaths, saveFreq: false, @@ -2623,6 +2660,8 @@ export class CoreH5PProvider { } } +export class CoreH5P extends makeSingleton(CoreH5PProvider) {} + /** * Display options behaviour constants. */ diff --git a/src/providers/update-manager.ts b/src/providers/update-manager.ts index cbf493127..bf76dec22 100644 --- a/src/providers/update-manager.ts +++ b/src/providers/update-manager.ts @@ -17,6 +17,7 @@ import { CoreConfigProvider } from './config'; import { CoreInitHandler, CoreInitDelegate } from './init'; import { CoreLoggerProvider } from './logger'; import { CoreConfigConstants } from '../configconstants'; +import { CoreH5P } from '@core/h5p/providers/h5p'; import { makeSingleton } from '@singletons/core.singletons'; /** @@ -34,7 +35,8 @@ export class CoreUpdateManagerProvider implements CoreInitHandler { protected VERSION_APPLIED = 'version_applied'; protected logger; - constructor(logger: CoreLoggerProvider, private configProvider: CoreConfigProvider) { + constructor(logger: CoreLoggerProvider, + protected configProvider: CoreConfigProvider) { this.logger = logger.getInstance('CoreUpdateManagerProvider'); } @@ -44,21 +46,24 @@ export class CoreUpdateManagerProvider implements CoreInitHandler { * * @return Promise resolved when the update process finishes. */ - load(): Promise { - const promises = [], - versionCode = CoreConfigConstants.versioncode; + async load(): Promise { + const promises = []; + const versionCode = CoreConfigConstants.versioncode; - return this.configProvider.get(this.VERSION_APPLIED, 0).then((versionApplied: number) => { + const versionApplied: number = await this.configProvider.get(this.VERSION_APPLIED, 0); - // Put here the code to treat app updates. + if (versionCode >= 3900 && versionApplied < 3900 && versionApplied > 0) { + promises.push(CoreH5P.instance.deleteAllContentIndexes()); + } - return Promise.all(promises).then(() => { - return this.configProvider.set(this.VERSION_APPLIED, versionCode); - }).catch((error) => { - this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error); - }); - }); + try { + await Promise.all(promises); + + await this.configProvider.set(this.VERSION_APPLIED, versionCode); + } catch (error) { + this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error); + } } } -export class CoreUpdateManager extends makeSingleton(CoreUpdateManagerProvider) {} +export class CoreUpdateManager extends makeSingleton(CoreUpdateManagerProvider) {} From 17dda0c10e2ae7d81d1d607319b0d141a287c65c Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 6 Apr 2020 14:07:36 +0200 Subject: [PATCH 018/166] MOBILE-3101 config: Install WKWebView Cookies plugin --- config.xml | 1 + package-lock.json | 6 +++++- package.json | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config.xml b/config.xml index fc0883b59..1282a7a65 100644 --- a/config.xml +++ b/config.xml @@ -174,6 +174,7 @@ + diff --git a/package-lock.json b/package-lock.json index 07c1ea7d7..15e6dbdf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "moodlemobile", - "version": "3.8.1", + "version": "3.8.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2725,6 +2725,10 @@ "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.4.tgz", "integrity": "sha512-EYC5eQFVkoYXq39l7tYKE6lEjHJ04mvTmKXxGL7quHLdFPfJMNzru/UYpn92AOfpl3PQaZmou78C7EgmFOwFQQ==" }, + "cordova-plugin-wkwebview-cookies": { + "version": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git#0f20979803ffd9b13250215975692703342d759c", + "from": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git" + }, "cordova-plugin-zip": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cordova-plugin-zip/-/cordova-plugin-zip-3.1.0.tgz", diff --git a/package.json b/package.json index ecbd217aa..941127fae 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "cordova-plugin-splashscreen": "5.0.3", "cordova-plugin-statusbar": "2.4.3", "cordova-plugin-whitelist": "1.3.4", + "cordova-plugin-wkwebview-cookies": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git", "cordova-plugin-zip": "3.1.0", "cordova-sqlite-storage": "4.0.0", "cordova-support-google-services": "1.3.2", @@ -192,7 +193,8 @@ "cordova-plugin-ionic-webview": {}, "cordova-plugin-advanced-http": { "OKHTTP_VERSION": "3.10.0" - } + }, + "cordova-plugin-wkwebview-cookies": {} } }, "main": "desktop/electron.js", From 2698261593b40b08c5601c4ccd105f4ba35c896c Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 14 Apr 2020 10:44:06 +0200 Subject: [PATCH 019/166] MOBILE-3101 iframe: Use wkwebview cookies plugin in iOS --- src/components/iframe/iframe.ts | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/components/iframe/iframe.ts b/src/components/iframe/iframe.ts index 5e98b10f7..8f7ce3b49 100644 --- a/src/components/iframe/iframe.ts +++ b/src/components/iframe/iframe.ts @@ -16,14 +16,16 @@ import { Component, Input, Output, OnInit, ViewChild, ElementRef, EventEmitter, OnChanges, SimpleChange, Optional } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; -import { NavController } from 'ionic-angular'; -import { CoreFileProvider } from '@providers/file'; +import { NavController, Platform } from 'ionic-angular'; +import { CoreFile } from '@providers/file'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreIframeUtilsProvider } from '@providers/utils/iframe'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreUrl } from '@singletons/url'; +import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies'; @Component({ selector: 'core-iframe', @@ -51,7 +53,7 @@ export class CoreIframeComponent implements OnInit, OnChanges { protected urlUtils: CoreUrlUtilsProvider, protected utils: CoreUtilsProvider, @Optional() protected svComponent: CoreSplitViewComponent, - protected fileProvider: CoreFileProvider) { + protected platform: Platform) { this.logger = logger.getInstance('CoreIframe'); this.loaded = new EventEmitter(); @@ -93,10 +95,28 @@ export class CoreIframeComponent implements OnInit, OnChanges { /** * Detect changes on input properties. */ - ngOnChanges(changes: {[name: string]: SimpleChange }): void { + async ngOnChanges(changes: {[name: string]: SimpleChange }): Promise { if (changes.src) { const url = this.urlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue; - this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.fileProvider.convertFileSrc(url)); + + if (this.platform.is('ios')) { + // Save a "fake" cookie for the iframe's domain to fix a bug in WKWebView. + try { + const win = window; + const urlParts = CoreUrl.parse(url); + + await win.WKWebViewCookies.setCookie({ + name: 'MoodleAppCookieForWKWebView', + value: '1', + domain: urlParts.domain, + }); + } catch (err) { + // Ignore errors. + this.logger.error('Error setting cookie', err); + } + } + + this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(CoreFile.instance.convertFileSrc(url)); } } } From c744de17c1afe0d6ecc1c43b73d3cbdc4eb9f71c Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 22 Apr 2020 13:16:35 +0200 Subject: [PATCH 020/166] MOBILE-3398 data: Fix ##moreurl## links --- src/addon/mod/data/providers/approve-link-handler.ts | 1 + src/addon/mod/data/providers/show-link-handler.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/addon/mod/data/providers/approve-link-handler.ts b/src/addon/mod/data/providers/approve-link-handler.ts index f4c9bb5f4..7426ad39f 100644 --- a/src/addon/mod/data/providers/approve-link-handler.ts +++ b/src/addon/mod/data/providers/approve-link-handler.ts @@ -27,6 +27,7 @@ export class AddonModDataApproveLinkHandler extends CoreContentLinksHandlerBase name = 'AddonModDataApproveLinkHandler'; featureName = 'CoreCourseModuleDelegate_AddonModData'; pattern = /\/mod\/data\/view\.php.*([\?\&](d|approve|disapprove)=\d+)/; + priority = 50; // Higher priority than the default link handler for view.php. constructor(private dataProvider: AddonModDataProvider, private dataHelper: AddonModDataHelperProvider) { super(); diff --git a/src/addon/mod/data/providers/show-link-handler.ts b/src/addon/mod/data/providers/show-link-handler.ts index 5f4f3b22c..5bb471762 100644 --- a/src/addon/mod/data/providers/show-link-handler.ts +++ b/src/addon/mod/data/providers/show-link-handler.ts @@ -29,6 +29,7 @@ export class AddonModDataShowLinkHandler extends CoreContentLinksHandlerBase { name = 'AddonModDataShowLinkHandler'; featureName = 'CoreCourseModuleDelegate_AddonModData'; pattern = /\/mod\/data\/view\.php.*([\?\&](d|rid|page|group|mode)=\d+)/; + priority = 50; // Higher priority than the default link handler for view.php. constructor(private linkHelper: CoreContentLinksHelperProvider, private dataProvider: AddonModDataProvider, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) { From 1b1ff7347dff4c54d7afbf81d40178e1234392fd Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 27 Apr 2020 12:53:58 +0200 Subject: [PATCH 021/166] MOBILE-3407 quiz: Fix drops in ddimageortext in Moodle 3.6 --- src/core/question/providers/helper.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/question/providers/helper.ts b/src/core/question/providers/helper.ts index 0cb77a0b0..7623ea747 100644 --- a/src/core/question/providers/helper.ts +++ b/src/core/question/providers/helper.ts @@ -275,10 +275,11 @@ export class CoreQuestionHelperProvider { question.initObjects = this.textUtils.parseJSON(initMatch, null); } - const amdRegExp = new RegExp('require\\(\\[["\']qtype_' + question.type + '/question["\']\\], ?' + - 'function\\(amd\\) ?\\{ ?amd\\.init\\((["\'](q|question-' + usageId + '-)' + question.slot + - '["\'].*?)\\);', 'm'); + const amdRegExp = new RegExp('require\\(\\[["\']qtype_' + question.type + '/question["\']\\],[^f]*' + + 'function\\(amd\\)[^\\{]*\\{[^a]*amd\\.init\\((["\'](q|question-' + usageId + '-)' + question.slot + + '["\'].*)\\);', 'm'); const amdMatch = match.match(amdRegExp); + if (amdMatch) { // Try to convert the arguments to an array and add them to the question. question.amdArgs = this.textUtils.parseJSON('[' + amdMatch[1] + ']', null); From 9dddd95a057e5244c3bf88e7e34b546fc8034680 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 27 Apr 2020 16:54:40 +0200 Subject: [PATCH 022/166] MOBILE-3101 npm: Fix commit in package-lock file --- package-lock.json | 521 +++++++++++++++++++++++++--------------------- 1 file changed, 289 insertions(+), 232 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15e6dbdf1..956c7923b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2726,7 +2726,7 @@ "integrity": "sha512-EYC5eQFVkoYXq39l7tYKE6lEjHJ04mvTmKXxGL7quHLdFPfJMNzru/UYpn92AOfpl3PQaZmou78C7EgmFOwFQQ==" }, "cordova-plugin-wkwebview-cookies": { - "version": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git#0f20979803ffd9b13250215975692703342d759c", + "version": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git#8e319b9cc5887611bd8972152e4377757986d570", "from": "git+https://github.com/moodlemobile/cordova-plugin-wkwebview-cookies.git" }, "cordova-plugin-zip": { @@ -5079,24 +5079,25 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "resolved": "", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "optional": true, "requires": { @@ -5106,13 +5107,15 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "resolved": "", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5120,34 +5123,37 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "resolved": "", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved": "", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "resolved": "", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "optional": true }, "debug": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "optional": true, "requires": { @@ -5156,25 +5162,25 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "optional": true, "requires": { @@ -5183,13 +5189,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { @@ -5205,7 +5211,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "optional": true, "requires": { @@ -5219,13 +5225,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "optional": true, "requires": { @@ -5234,7 +5240,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "optional": true, "requires": { @@ -5243,7 +5249,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "optional": true, "requires": { @@ -5253,46 +5259,51 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "resolved": "", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "resolved": "", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5300,7 +5311,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "optional": true, "requires": { @@ -5309,15 +5320,16 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "optional": true }, @@ -5329,7 +5341,7 @@ }, "needle": { "version": "2.3.0", - "resolved": false, + "resolved": "", "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "optional": true, "requires": { @@ -5340,7 +5352,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "optional": true, "requires": { @@ -5358,7 +5370,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { @@ -5368,13 +5380,13 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": false, + "resolved": "", "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "optional": true, "requires": { @@ -5384,7 +5396,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "optional": true, "requires": { @@ -5396,38 +5408,40 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "resolved": "", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "optional": true, "requires": { @@ -5437,19 +5451,19 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "optional": true, "requires": { @@ -5461,7 +5475,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true } @@ -5469,7 +5483,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "optional": true, "requires": { @@ -5484,7 +5498,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "optional": true, "requires": { @@ -5493,43 +5507,45 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved": "", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "optional": true }, "semver": { "version": "5.7.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5538,7 +5554,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "optional": true, "requires": { @@ -5547,21 +5563,22 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "optional": true, "requires": { @@ -5576,13 +5593,13 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "optional": true, "requires": { @@ -5591,13 +5608,15 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved": "", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "resolved": "", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "optional": true } } }, @@ -6017,27 +6036,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -6048,15 +6068,17 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6064,39 +6086,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, @@ -6106,28 +6131,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -6137,14 +6162,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -6161,7 +6186,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -6176,14 +6201,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -6193,7 +6218,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -6203,7 +6228,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -6214,53 +6239,58 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6268,7 +6298,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -6278,23 +6308,24 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "resolved": false, + "resolved": "", "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, @@ -6306,7 +6337,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, + "resolved": "", "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, @@ -6325,7 +6356,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -6336,14 +6367,14 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": false, + "resolved": "", "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, @@ -6354,7 +6385,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -6367,43 +6398,45 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -6414,21 +6447,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -6441,7 +6474,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -6450,7 +6483,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -6466,7 +6499,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -6476,50 +6509,52 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6528,7 +6563,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -6538,23 +6573,24 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -6570,14 +6606,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -6587,15 +6623,17 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, + "resolved": "", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "dev": true, + "optional": true } } }, @@ -12831,27 +12869,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -12862,15 +12901,17 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -12878,39 +12919,42 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": false, + "resolved": "", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -12920,28 +12964,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, + "resolved": "", "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -12951,14 +12995,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -12975,7 +13019,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, @@ -12990,14 +13034,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -13007,7 +13051,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -13017,7 +13061,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -13028,53 +13072,58 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, + "resolved": "", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -13082,7 +13131,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, + "resolved": "", "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, @@ -13092,23 +13141,24 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "dev": true, "optional": true, @@ -13120,7 +13170,7 @@ }, "node-pre-gyp": { "version": "0.10.3", - "resolved": false, + "resolved": "", "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "dev": true, "optional": true, @@ -13139,7 +13189,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -13150,14 +13200,14 @@ }, "npm-bundled": { "version": "1.0.5", - "resolved": false, + "resolved": "", "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "dev": true, "optional": true, @@ -13168,7 +13218,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -13181,43 +13231,45 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -13228,21 +13280,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -13255,7 +13307,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -13264,7 +13316,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -13280,7 +13332,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, + "resolved": "", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, @@ -13290,50 +13342,52 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.6.0", - "resolved": false, + "resolved": "", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -13342,7 +13396,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -13352,23 +13406,24 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, + "resolved": "", "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, @@ -13384,14 +13439,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -13401,15 +13456,17 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, + "resolved": "", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true + "dev": true, + "optional": true } } }, From 0893b2fb03f3f65ae79aee71dade6a8afc0885eb Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 5 Mar 2020 17:41:04 +0100 Subject: [PATCH 023/166] MOBILE-3375 course: Make download warnings less intrusive Also, now the download function is called only if it's really needed --- .../index/addon-mod-book-index.html | 4 + src/addon/mod/book/components/index/index.ts | 34 ++--- .../mod/folder/components/index/index.ts | 7 +- .../index/addon-mod-imscp-index.html | 5 + src/addon/mod/imscp/components/index/index.ts | 35 ++--- .../index/addon-mod-page-index.html | 4 + src/addon/mod/page/components/index/index.ts | 37 ++--- .../index/addon-mod-resource-index.html | 4 + .../mod/resource/components/index/index.ts | 31 ++-- src/addon/mod/url/components/index/index.ts | 9 +- .../course/classes/main-activity-component.ts | 62 -------- .../course/classes/main-resource-component.ts | 143 +++++++++++++++++- .../providers/module-prefetch-delegate.ts | 19 +++ 13 files changed, 230 insertions(+), 164 deletions(-) diff --git a/src/addon/mod/book/components/index/addon-mod-book-index.html b/src/addon/mod/book/components/index/addon-mod-book-index.html index cfd0ff551..ee1e5bbad 100644 --- a/src/addon/mod/book/components/index/addon-mod-book-index.html +++ b/src/addon/mod/book/components/index/addon-mod-book-index.html @@ -18,6 +18,10 @@ + + + +
    diff --git a/src/addon/mod/book/components/index/index.ts b/src/addon/mod/book/components/index/index.ts index 50c69e8bd..9b3fa4574 100644 --- a/src/addon/mod/book/components/index/index.ts +++ b/src/addon/mod/book/components/index/index.ts @@ -16,7 +16,9 @@ import { Component, Optional, Injector, Input } from '@angular/core'; import { Content, ModalController } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; +import { + CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult +} from '@core/course/classes/main-resource-component'; import { AddonModBookProvider, AddonModBookContentsMap, AddonModBookTocChapter, AddonModBookBook, AddonModBookNavStyle } from '../../providers/book'; @@ -41,6 +43,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp displayNavBar = true; previousNavBarTitle: string; nextNavBarTitle: string; + warning: string; protected chapters: AddonModBookTocChapter[]; protected currentChapter: string; @@ -48,9 +51,11 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp protected book: AddonModBookBook; protected displayTitlesInNavBar = false; - constructor(injector: Injector, private bookProvider: AddonModBookProvider, private courseProvider: CoreCourseProvider, - private appProvider: CoreAppProvider, private prefetchDelegate: AddonModBookPrefetchHandler, - private modalCtrl: ModalController, private tagProvider: CoreTagProvider, @Optional() private content: Content) { + constructor(injector: Injector, + protected bookProvider: AddonModBookProvider, + protected modalCtrl: ModalController, + protected tagProvider: CoreTagProvider, + @Optional() protected content: Content) { super(injector); } @@ -126,8 +131,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp */ protected fetchContent(refresh?: boolean): Promise { const promises = []; - let downloadFailed = false; - let downloadFailError; + let downloadResult: CoreCourseResourceDownloadResult; // Try to get the book data. promises.push(this.bookProvider.getBook(this.courseId, this.module.id).then((book) => { @@ -140,16 +144,9 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp // Ignore errors since this WS isn't available in some Moodle versions. })); - // Download content. This function also loads module contents if needed. - promises.push(this.prefetchDelegate.download(this.module, this.courseId).catch((error) => { - // Mark download as failed but go on since the main files could have been downloaded. - downloadFailed = true; - downloadFailError = error; - - if (!this.module.contents.length) { - // Try to load module contents for offline usage. - return this.courseProvider.loadModuleContents(this.module, this.courseId); - } + // Get module status to determine if it needs to be downloaded. + promises.push(this.downloadResourceIfNeeded(refresh).then((result) => { + downloadResult = result; })); return Promise.all(promises).then(() => { @@ -174,10 +171,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp // Show chapter. return this.loadChapter(this.currentChapter, refresh).then(() => { - if (downloadFailed && this.appProvider.isOnline()) { - // We could load the main file but the download failed. Show error message. - this.showErrorDownloadingSomeFiles(downloadFailError); - } + this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error) : ''; }).catch(() => { // Ignore errors, they're handled inside the loadChapter function. }); diff --git a/src/addon/mod/folder/components/index/index.ts b/src/addon/mod/folder/components/index/index.ts index 622acb449..805210106 100644 --- a/src/addon/mod/folder/components/index/index.ts +++ b/src/addon/mod/folder/components/index/index.ts @@ -13,8 +13,6 @@ // limitations under the License. import { Component, Input, Injector } from '@angular/core'; -import { CoreAppProvider } from '@providers/app'; -import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; import { AddonModFolderProvider } from '../../providers/folder'; import { AddonModFolderHelperProvider } from '../../providers/helper'; @@ -36,8 +34,9 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo canGetFolder: boolean; contents: any; - constructor(injector: Injector, private folderProvider: AddonModFolderProvider, private courseProvider: CoreCourseProvider, - private appProvider: CoreAppProvider, private folderHelper: AddonModFolderHelperProvider) { + constructor(injector: Injector, + protected folderProvider: AddonModFolderProvider, + protected folderHelper: AddonModFolderHelperProvider) { super(injector); } diff --git a/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html b/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html index 6be152d02..9f767d27c 100644 --- a/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html +++ b/src/addon/mod/imscp/components/index/addon-mod-imscp-index.html @@ -15,6 +15,11 @@ + + + + +
    diff --git a/src/addon/mod/imscp/components/index/index.ts b/src/addon/mod/imscp/components/index/index.ts index a17aa8de4..246721aab 100644 --- a/src/addon/mod/imscp/components/index/index.ts +++ b/src/addon/mod/imscp/components/index/index.ts @@ -14,11 +14,10 @@ import { Component, Injector } from '@angular/core'; import { ModalController } from 'ionic-angular'; -import { CoreAppProvider } from '@providers/app'; -import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; +import { + CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult +} from '@core/course/classes/main-resource-component'; import { AddonModImscpProvider } from '../../providers/imscp'; -import { AddonModImscpPrefetchHandler } from '../../providers/prefetch-handler'; /** * Component that displays a IMSCP. @@ -33,14 +32,15 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom items = []; currentItem: string; src = ''; + warning: string; // Initialize empty previous/next to prevent showing arrows for an instant before they're hidden. previousItem = ''; nextItem = ''; - constructor(injector: Injector, private imscpProvider: AddonModImscpProvider, private courseProvider: CoreCourseProvider, - private appProvider: CoreAppProvider, private modalCtrl: ModalController, - private imscpPrefetch: AddonModImscpPrefetchHandler) { + constructor(injector: Injector, + protected imscpProvider: AddonModImscpProvider, + protected modalCtrl: ModalController) { super(injector); } @@ -75,8 +75,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom * @return Promise resolved when done. */ protected fetchContent(refresh?: boolean): Promise { - let downloadFailed = false; - let downloadFailError; + let downloadResult: CoreCourseResourceDownloadResult; const promises = []; promises.push(this.imscpProvider.getImscp(this.courseId, this.module.id).then((imscp) => { @@ -84,17 +83,8 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom this.dataRetrieved.emit(imscp); })); - promises.push(this.imscpPrefetch.download(this.module, this.courseId).catch((error) => { - // Mark download as failed but go on since the main files could have been downloaded. - downloadFailed = true; - downloadFailError = error; - - return this.courseProvider.loadModuleContents(this.module, this.courseId).catch((error) => { - // Error getting module contents, fail. - this.domUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true); - - return Promise.reject(null); - }); + promises.push(this.downloadResourceIfNeeded(refresh).then((result) => { + downloadResult = result; })); return Promise.all(promises).then(() => { @@ -109,10 +99,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom return Promise.reject(null); }); }).then(() => { - if (downloadFailed && this.appProvider.isOnline()) { - // We could load the main file but the download failed. Show error message. - this.showErrorDownloadingSomeFiles(downloadFailError); - } + this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error) : ''; }).finally(() => { this.fillContextMenu(refresh); diff --git a/src/addon/mod/page/components/index/addon-mod-page-index.html b/src/addon/mod/page/components/index/addon-mod-page-index.html index 12f6ddbd3..d3d6c7726 100644 --- a/src/addon/mod/page/components/index/addon-mod-page-index.html +++ b/src/addon/mod/page/components/index/addon-mod-page-index.html @@ -15,6 +15,10 @@ + + + +

    diff --git a/src/addon/mod/page/components/index/index.ts b/src/addon/mod/page/components/index/index.ts index b8300246a..27f84b9b9 100644 --- a/src/addon/mod/page/components/index/index.ts +++ b/src/addon/mod/page/components/index/index.ts @@ -13,13 +13,12 @@ // limitations under the License. import { Component, Injector } from '@angular/core'; -import { CoreAppProvider } from '@providers/app'; import { CoreUtilsProvider } from '@providers/utils/utils'; -import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; +import { + CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult +} from '@core/course/classes/main-resource-component'; import { AddonModPageProvider, AddonModPagePage } from '../../providers/page'; import { AddonModPageHelperProvider } from '../../providers/helper'; -import { AddonModPagePrefetchHandler } from '../../providers/prefetch-handler'; /** * Component that displays a page. @@ -35,12 +34,14 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp displayDescription = true; displayTimemodified = true; page: AddonModPagePage; + warning: string; protected fetchContentDefaultError = 'addon.mod_page.errorwhileloadingthepage'; - constructor(injector: Injector, private pageProvider: AddonModPageProvider, private courseProvider: CoreCourseProvider, - private appProvider: CoreAppProvider, private pageHelper: AddonModPageHelperProvider, - private pagePrefetch: AddonModPagePrefetchHandler, private utils: CoreUtilsProvider) { + constructor(injector: Injector, + protected pageProvider: AddonModPageProvider, + protected pageHelper: AddonModPageHelperProvider, + protected utils: CoreUtilsProvider) { super(injector); } @@ -77,19 +78,11 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp * @return Promise resolved when done. */ protected fetchContent(refresh?: boolean): Promise { - let downloadFailed = false; - let downloadFailError; + let downloadResult: CoreCourseResourceDownloadResult; - // Download content. This function also loads module contents if needed. - return this.pagePrefetch.download(this.module, this.courseId).catch((error) => { - // Mark download as failed but go on since the main files could have been downloaded. - downloadFailed = true; - downloadFailError = error; - }).then(() => { - if (!this.module.contents.length) { - // Try to load module contents for offline usage. - return this.courseProvider.loadModuleContents(this.module, this.courseId); - } + // Download the resource if it needs to be downloaded. + return this.downloadResourceIfNeeded(refresh).then((result) => { + downloadResult = result; }).then(() => { const promises = []; @@ -131,11 +124,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp promises.push(this.pageHelper.getPageHtml(this.module.contents, this.module.id).then((content) => { this.contents = content; - - if (downloadFailed && this.appProvider.isOnline()) { - // We could load the main file but the download failed. Show error message. - this.showErrorDownloadingSomeFiles(downloadFailError); - } + this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error) : ''; })); return Promise.all(promises); diff --git a/src/addon/mod/resource/components/index/addon-mod-resource-index.html b/src/addon/mod/resource/components/index/addon-mod-resource-index.html index 9fcfdaa83..e6aa1efff 100644 --- a/src/addon/mod/resource/components/index/addon-mod-resource-index.html +++ b/src/addon/mod/resource/components/index/addon-mod-resource-index.html @@ -15,6 +15,10 @@ + + + + diff --git a/src/addon/mod/resource/components/index/index.ts b/src/addon/mod/resource/components/index/index.ts index 8875bae06..58810ad3d 100644 --- a/src/addon/mod/resource/components/index/index.ts +++ b/src/addon/mod/resource/components/index/index.ts @@ -13,14 +13,12 @@ // limitations under the License. import { Component, Injector } from '@angular/core'; -import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; -import { CoreSitesProvider } from '@providers/sites'; import { CoreUtilsProvider } from '@providers/utils/utils'; -import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; +import { + CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult +} from '@core/course/classes/main-resource-component'; import { AddonModResourceProvider } from '../../providers/resource'; -import { AddonModResourcePrefetchHandler } from '../../providers/prefetch-handler'; import { AddonModResourceHelperProvider } from '../../providers/helper'; /** @@ -38,14 +36,11 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource src: string; contentText: string; displayDescription = true; + warning: string; constructor(injector: Injector, protected resourceProvider: AddonModResourceProvider, - protected courseProvider: CoreCourseProvider, - protected appProvider: CoreAppProvider, - protected prefetchHandler: AddonModResourcePrefetchHandler, protected resourceHelper: AddonModResourceHelperProvider, - protected sitesProvider: CoreSitesProvider, protected utils: CoreUtilsProvider, protected filepoolProvider: CoreFilepoolProvider) { super(injector); @@ -109,13 +104,10 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource } if (this.resourceHelper.isDisplayedInIframe(this.module)) { - let downloadFailed = false; - let downloadFailError; + let downloadResult: CoreCourseResourceDownloadResult; - return this.prefetchHandler.download(this.module, this.courseId).catch((error) => { - // Mark download as failed but go on since the main files could have been downloaded. - downloadFailed = true; - downloadFailError = error; + return this.downloadResourceIfNeeded(refresh, true).then((result) => { + downloadResult = result; }).then(() => { return this.resourceHelper.getIframeSrc(this.module).then((src) => { this.mode = 'iframe'; @@ -131,14 +123,12 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource this.src = src; } - if (downloadFailed && this.appProvider.isOnline()) { - // We could load the main file but the download failed. Show error message. - this.showErrorDownloadingSomeFiles(downloadFailError); - } + this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error) : ''; }); }); } else if (this.resourceHelper.isDisplayedEmbedded(this.module, resource && resource.display)) { this.mode = 'embedded'; + this.warning = ''; return this.resourceHelper.getEmbeddedHtml(this.module, this.courseId).then((html) => { this.contentText = html; @@ -147,6 +137,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource }); } else { this.mode = 'external'; + this.warning = ''; } }).finally(() => { this.fillContextMenu(refresh); @@ -159,7 +150,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource * @return Promise resolved when done. */ async open(): Promise { - let downloadable = await this.prefetchHandler.isDownloadable(this.module, this.courseId); + let downloadable = await this.modulePrefetchDelegate.isModuleDownloadable(this.module, this.courseId); if (downloadable) { // Check if the main file is downloadle. diff --git a/src/addon/mod/url/components/index/index.ts b/src/addon/mod/url/components/index/index.ts index b9381aae0..1275b3796 100644 --- a/src/addon/mod/url/components/index/index.ts +++ b/src/addon/mod/url/components/index/index.ts @@ -13,9 +13,7 @@ // limitations under the License. import { Component, Injector } from '@angular/core'; -import { CoreSitesProvider } from '@providers/sites'; import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; -import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseModuleMainResourceComponent } from '@core/course/classes/main-resource-component'; import { AddonModUrlProvider } from '../../providers/url'; import { AddonModUrlHelperProvider } from '../../providers/helper'; @@ -43,9 +41,10 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo mimetype: string; displayDescription = true; - constructor(injector: Injector, private urlProvider: AddonModUrlProvider, private courseProvider: CoreCourseProvider, - private urlHelper: AddonModUrlHelperProvider, private mimeUtils: CoreMimetypeUtilsProvider, - private sitesProvider: CoreSitesProvider) { + constructor(injector: Injector, + protected urlProvider: AddonModUrlProvider, + protected urlHelper: AddonModUrlHelperProvider, + protected mimeUtils: CoreMimetypeUtilsProvider) { super(injector); } diff --git a/src/core/course/classes/main-activity-component.ts b/src/core/course/classes/main-activity-component.ts index 5b2d7f830..f30bad08d 100644 --- a/src/core/course/classes/main-activity-component.ts +++ b/src/core/course/classes/main-activity-component.ts @@ -14,12 +14,7 @@ import { Injector, Input, NgZone } from '@angular/core'; import { Content } from 'ionic-angular'; -import { CoreSitesProvider } from '@providers/sites'; -import { CoreCourseProvider } from '@core/course/providers/course'; -import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; -import { CoreEventsProvider } from '@providers/events'; import { Network } from '@ionic-native/network'; -import { CoreAppProvider } from '@providers/app'; import { CoreCourseModuleMainResourceComponent } from './main-resource-component'; /** @@ -35,30 +30,13 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR hasOffline: boolean; // If it has offline data to be synced. isOnline: boolean; // If the app is online or not. - protected siteId: string; // Current Site ID. protected syncObserver: any; // It will observe the sync auto event. - protected statusObserver: any; // It will observe changes on the status of the activity. Only if setStatusListener is called. protected onlineObserver: any; // It will observe the status of the network connection. protected syncEventName: string; // Auto sync event name. - protected currentStatus: string; // The current status of the activity. Only if setStatusListener is called. - - // List of services that will be injected using injector. - // It's done like this so subclasses don't have to send all the services to the parent in the constructor. - protected sitesProvider: CoreSitesProvider; - protected courseProvider: CoreCourseProvider; - protected appProvider: CoreAppProvider; - protected eventsProvider: CoreEventsProvider; - protected modulePrefetchDelegate: CoreCourseModulePrefetchDelegate; constructor(injector: Injector, protected content?: Content, loggerName: string = 'CoreCourseModuleMainResourceComponent') { super(injector, loggerName); - this.sitesProvider = injector.get(CoreSitesProvider); - this.courseProvider = injector.get(CoreCourseProvider); - this.appProvider = injector.get(CoreAppProvider); - this.eventsProvider = injector.get(CoreEventsProvider); - this.modulePrefetchDelegate = injector.get(CoreCourseModulePrefetchDelegate); - const network = injector.get(Network); const zone = injector.get(NgZone); @@ -79,7 +57,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR this.hasOffline = false; this.syncIcon = 'spinner'; - this.siteId = this.sitesProvider.getCurrentSiteId(); this.moduleName = this.courseProvider.translateModuleName(this.moduleName); if (this.syncEventName) { @@ -242,44 +219,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR }); } - /** - * Displays some data based on the current status. - * - * @param status The current status. - * @param previousStatus The previous status. If not defined, there is no previous status. - */ - protected showStatus(status: string, previousStatus?: string): void { - // To be overridden. - } - - /** - * Watch for changes on the status. - * - * @return Promise resolved when done. - */ - protected setStatusListener(): Promise { - if (typeof this.statusObserver == 'undefined') { - // Listen for changes on this module status. - this.statusObserver = this.eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => { - if (data.componentId === this.module.id && data.component === this.component) { - // The status has changed, update it. - const previousStatus = this.currentStatus; - this.currentStatus = data.status; - - this.showStatus(this.currentStatus, previousStatus); - } - }, this.siteId); - - // Also, get the current status. - return this.modulePrefetchDelegate.getModuleStatus(this.module, this.courseId).then((status) => { - this.currentStatus = status; - this.showStatus(status); - }); - } - - return Promise.resolve(); - } - /** * Performs the sync of the activity. * @@ -329,6 +268,5 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR this.onlineObserver && this.onlineObserver.unsubscribe(); this.syncObserver && this.syncObserver.off(); - this.statusObserver && this.statusObserver.off(); } } diff --git a/src/core/course/classes/main-resource-component.ts b/src/core/course/classes/main-resource-component.ts index 1bbff628d..b84b2964e 100644 --- a/src/core/course/classes/main-resource-component.ts +++ b/src/core/course/classes/main-resource-component.ts @@ -15,16 +15,29 @@ import { OnInit, OnDestroy, Input, Output, EventEmitter, Injector } from '@angular/core'; import { NavController } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; +import { CoreAppProvider } from '@providers/app'; +import { CoreEventsProvider } from '@providers/events'; import { CoreLoggerProvider } from '@providers/logger'; +import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider, CoreTextErrorObject } from '@providers/utils/text'; import { CoreCourseHelperProvider } from '@core/course/providers/helper'; +import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseModuleMainComponent, CoreCourseModuleDelegate } from '@core/course/providers/module-delegate'; +import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; import { CoreCourseSectionPage } from '@core/course/pages/section/section.ts'; import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; import { AddonBlogProvider } from '@addon/blog/providers/blog'; import { CoreConstants } from '@core/constants'; +/** + * Result of a resource download. + */ +export type CoreCourseResourceDownloadResult = { + failed?: boolean; // Whether the download has failed. + error?: string | CoreTextErrorObject; // The error in case it failed. +}; + /** * Template class to easily create CoreCourseModuleMainComponent of resources (or activities without syncing). */ @@ -52,6 +65,9 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, protected contextFileStatusObserver; // Observer of file status changed, used when calling fillContextMenu. protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents. protected isCurrentView: boolean; // Whether the component is in the current view. + protected siteId: string; // Current Site ID. + protected statusObserver: any; // It will observe changes on the status of the module. Only if setStatusListener is called. + protected currentStatus: string; // The current status of the module. Only if setStatusListener is called. // List of services that will be injected using injector. // It's done like this so subclasses don't have to send all the services to the parent in the constructor. @@ -64,6 +80,11 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, protected linkHelper: CoreContentLinksHelperProvider; protected navCtrl: NavController; protected blogProvider: AddonBlogProvider; + protected sitesProvider: CoreSitesProvider; + protected eventsProvider: CoreEventsProvider; + protected modulePrefetchDelegate: CoreCourseModulePrefetchDelegate; + protected courseProvider: CoreCourseProvider; + protected appProvider: CoreAppProvider; protected logger; @@ -77,6 +98,12 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, this.linkHelper = injector.get(CoreContentLinksHelperProvider); this.navCtrl = injector.get(NavController, null); this.blogProvider = injector.get(AddonBlogProvider, null); + this.sitesProvider = injector.get(CoreSitesProvider); + this.eventsProvider = injector.get(CoreEventsProvider); + this.modulePrefetchDelegate = injector.get(CoreCourseModulePrefetchDelegate); + this.courseProvider = injector.get(CoreCourseProvider); + this.appProvider = injector.get(CoreAppProvider); + this.dataRetrieved = new EventEmitter(); const loggerProvider = injector.get(CoreLoggerProvider); @@ -87,6 +114,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, * Component being initialized. */ ngOnInit(): void { + this.siteId = this.sitesProvider.getCurrentSiteId(); this.description = this.module.description; this.componentId = this.module.id; this.externalUrl = this.module.url; @@ -274,18 +302,122 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId, done); } + /** + * Get message about an error occurred while downloading files. + * + * @param error The specific error. + * @param multiLine Whether to put each message in a different paragraph or in a single line. + */ + protected getErrorDownloadingSomeFilesMessage(error: string | CoreTextErrorObject, multiLine?: boolean): string { + if (multiLine) { + return this.textUtils.buildSeveralParagraphsMessage([ + this.translate.instant('core.errordownloadingsomefiles'), + error, + ]); + } else { + error = this.textUtils.getErrorMessageFromError(error); + + return this.translate.instant('core.errordownloadingsomefiles') + (error ? ' ' + error : ''); + } + } + /** * Show an error occurred while downloading files. * * @param error The specific error. */ protected showErrorDownloadingSomeFiles(error: string | CoreTextErrorObject): void { - const errorMessage = this.textUtils.buildSeveralParagraphsMessage([ - this.translate.instant('core.errordownloadingsomefiles'), - error, - ]); + this.domUtils.showErrorModal(this.getErrorDownloadingSomeFilesMessage(error, true)); + } - this.domUtils.showErrorModal(errorMessage); + /** + * Displays some data based on the current status. + * + * @param status The current status. + * @param previousStatus The previous status. If not defined, there is no previous status. + */ + protected showStatus(status: string, previousStatus?: string): void { + // To be overridden. + } + + /** + * Watch for changes on the status. + * + * @return Promise resolved when done. + */ + protected setStatusListener(): Promise { + if (typeof this.statusObserver == 'undefined') { + // Listen for changes on this module status. + this.statusObserver = this.eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => { + if (data.componentId === this.module.id && data.component === this.component) { + // The status has changed, update it. + const previousStatus = this.currentStatus; + this.currentStatus = data.status; + + this.showStatus(this.currentStatus, previousStatus); + } + }, this.siteId); + + // Also, get the current status. + return this.modulePrefetchDelegate.getModuleStatus(this.module, this.courseId).then((status) => { + this.currentStatus = status; + this.showStatus(status); + }); + } + + return Promise.resolve(); + } + + /** + * Download a resource if needed. + * If the download call fails the promise won't be rejected, but the error will be included in the returned object. + * If module.contents cannot be loaded then the Promise will be rejected. + * + * @param refresh Whether we're refreshing data. + * @return Promise resolved when done. + */ + protected async downloadResourceIfNeeded(refresh?: boolean, contentsAlreadyLoaded?: boolean) + : Promise { + + const result: CoreCourseResourceDownloadResult = { + failed: false, + }; + + // Get module status to determine if it needs to be downloaded. + await this.setStatusListener(); + + if (this.currentStatus != CoreConstants.DOWNLOADED) { + // Download content. This function also loads module contents if needed. + try { + await this.modulePrefetchDelegate.downloadModule(this.module, this.courseId); + + // If we reach here it means the download process already loaded the contents, no need to do it again. + contentsAlreadyLoaded = true; + } catch (error) { + // Mark download as failed but go on since the main files could have been downloaded. + result.failed = true; + result.error = error; + } + } + + if (!this.module.contents.length || (refresh && !contentsAlreadyLoaded)) { + // Try to load the contents. + const ignoreCache = refresh && this.appProvider.isOnline(); + + try { + await this.courseProvider.loadModuleContents(this.module, this.courseId, undefined, false, ignoreCache); + } catch (error) { + // Error loading contents. If we ignored cache, try to get the cached value. + if (ignoreCache && !this.module.contents) { + await this.courseProvider.loadModuleContents(this.module, this.courseId); + } else if (!this.module.contents) { + // Not able to load contents, throw the error. + throw error; + } + } + } + + return result; } /** @@ -295,6 +427,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, this.isDestroyed = true; this.contextMenuStatusObserver && this.contextMenuStatusObserver.off(); this.contextFileStatusObserver && this.contextFileStatusObserver.off(); + this.statusObserver && this.statusObserver.off(); } /** diff --git a/src/core/course/providers/module-prefetch-delegate.ts b/src/core/course/providers/module-prefetch-delegate.ts index ef0c1ad04..50fbdc5db 100644 --- a/src/core/course/providers/module-prefetch-delegate.ts +++ b/src/core/course/providers/module-prefetch-delegate.ts @@ -404,6 +404,25 @@ export class CoreCourseModulePrefetchDelegate extends CoreDelegate { return status; } + /** + * Download a module. + * + * @param module Module to download. + * @param courseId Course ID the module belongs to. + * @param dirPath Path of the directory where to store all the content files. + * @return Promise resolved when finished. + */ + async downloadModule(module: any, courseId: number, dirPath?: string): Promise { + const handler = this.getPrefetchHandlerFor(module); + + // Check if the module has a prefetch handler. + if (handler) { + await this.syncModule(module, courseId); + + await handler.download(module, courseId, dirPath); + } + } + /** * Check for updates in a course. * From 92247d04e16dff6854f7bd9f21928e6eda375ec8 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 28 Apr 2020 10:28:03 +0200 Subject: [PATCH 024/166] MOBILE-3384 login: Accept null in local_mobile check response --- src/classes/site.ts | 5 +++++ src/core/login/pages/site/site.ts | 9 ++++++++- src/providers/sites.ts | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/classes/site.ts b/src/classes/site.ts index befacd29e..a3dda67a2 100644 --- a/src/classes/site.ts +++ b/src/classes/site.ts @@ -1376,6 +1376,11 @@ export class CoreSite { return { code: 0 }; } + if (data === null) { + // This probably means that the server was configured to return null for non-existing URLs. Not installed. + return { code: 0 }; + } + if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') { if (!retrying) { this.siteUrl = this.urlUtils.addOrRemoveWWW(this.siteUrl); diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index 400491069..59b87f862 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -165,7 +165,14 @@ export class CoreLoginSitePage { // Attempt guessing the domain if the initial check failed const domain = CoreUrl.guessMoodleDomain(url); - return domain ? this.sitesProvider.checkSite(domain) : Promise.reject(error); + if (domain && domain != url) { + return this.sitesProvider.checkSite(domain).catch((secondError) => { + // Try to use the first error. + return Promise.reject(error || secondError); + }); + } + + return Promise.reject(error); }) .then((result) => this.login(result)) .catch((error) => this.showLoginIssue(url, error)) diff --git a/src/providers/sites.ts b/src/providers/sites.ts index f0f85df99..22d42b4e0 100644 --- a/src/providers/sites.ts +++ b/src/providers/sites.ts @@ -572,6 +572,11 @@ export class CoreSitesProvider { return Promise.reject({error: this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION})}); }).then((data: any) => { + if (data === null) { + // Cannot connect. + return Promise.reject({error: this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION})}); + } + if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) { return Promise.reject({ errorcode: data.errorcode, error: data.error }); } else if (data.error && data.error == 'Web services must be enabled in Advanced features.') { From ec3a1bdb56a517fa39bd9502c887e27582dbb590 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 7 Apr 2020 12:22:47 +0200 Subject: [PATCH 025/166] MOBILE-3270 core: Fix upload files from Google Drive --- src/components/local-file/local-file.ts | 2 +- .../pages/capture-media/capture-media.ts | 21 ++++++++---- src/providers/file.ts | 33 ++++++++++++------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/components/local-file/local-file.ts b/src/components/local-file/local-file.ts index c9f63ed17..cd0c573a3 100644 --- a/src/components/local-file/local-file.ts +++ b/src/components/local-file/local-file.ts @@ -78,7 +78,7 @@ export class CoreLocalFileComponent implements OnInit { this.size = this.textUtils.bytesToSize(metadata.size, 2); } - this.timemodified = this.timeUtils.userDate(metadata.modificationTime, 'core.strftimedatetimeshort'); + this.timemodified = this.timeUtils.userDate(metadata.modificationTime.getTime(), 'core.strftimedatetimeshort'); }); } diff --git a/src/core/emulator/pages/capture-media/capture-media.ts b/src/core/emulator/pages/capture-media/capture-media.ts index 77c1ec99e..89cbbbdab 100644 --- a/src/core/emulator/pages/capture-media/capture-media.ts +++ b/src/core/emulator/pages/capture-media/capture-media.ts @@ -18,6 +18,7 @@ import { CoreFileProvider } from '@providers/file'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTimeUtilsProvider } from '@providers/utils/time'; +import { MediaFile } from '@ionic-native/media-capture'; /** * Page to capture media in browser or desktop. @@ -364,13 +365,21 @@ export class CoreEmulatorCaptureMediaPage implements OnInit, OnDestroy { if (this.isImage && !this.isCaptureImage) { this.dismissWithData(fileEntry.toURL()); } else { - // The capture plugin returns a MediaFile, not a FileEntry. - // The only difference is that it supports a new function that won't be supported in desktop. - fileEntry.getFormatData = (successFn, errorFn): any => { - // Nothing to do. - }; + // The capture plugin should return a MediaFile, not a FileEntry. Convert it. + return this.fileProvider.getMetadata(fileEntry).then((metadata) => { + const mediaFile: MediaFile = { + name: fileEntry.name, + fullPath: fileEntry.fullPath, + type: null, + lastModifiedDate: metadata.modificationTime, + size: metadata.size, + getFormatData: (successFn, errorFn): void => { + // Nothing to do. + } + }; - this.dismissWithData([fileEntry]); + this.dismissWithData([mediaFile]); + }); } }).catch((err) => { this.domUtils.showErrorModal(err); diff --git a/src/providers/file.ts b/src/providers/file.ts index 1bee27880..658560c42 100644 --- a/src/providers/file.ts +++ b/src/providers/file.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; import { Platform } from 'ionic-angular'; -import { File, FileEntry, DirectoryEntry } from '@ionic-native/file'; +import { File, FileEntry, DirectoryEntry, Entry, Metadata } from '@ionic-native/file'; import { CoreAppProvider } from './app'; import { CoreLoggerProvider } from './logger'; @@ -545,7 +545,7 @@ export class CoreFileProvider { reader.onloadend = (evt): void => { const target = evt.target; // Convert to to be able to use non-standard properties. - if (target.result !== undefined || target.result !== null) { + if (target.result !== undefined && target.result !== null) { if (format == CoreFileProvider.FORMATJSON) { // Convert to object. const parsed = this.textUtils.parseJSON(target.result, null); @@ -558,7 +558,7 @@ export class CoreFileProvider { } else { resolve(target.result); } - } else if (target.error !== undefined || target.error !== null) { + } else if (target.error !== undefined && target.error !== null) { reject(target.error); } else { reject({ code: null, message: 'READER_ONLOADEND_ERR' }); @@ -602,7 +602,7 @@ export class CoreFileProvider { * @param append Whether to append the data to the end of the file. * @return Promise to be resolved when the file is written. */ - writeFile(path: string, data: any, append?: boolean): Promise { + writeFile(path: string, data: any, append?: boolean): Promise { return this.init().then(() => { // Remove basePath if it's in the path. path = this.removeStartingSlash(path.replace(this.basePath, '')); @@ -635,15 +635,18 @@ export class CoreFileProvider { * @param append Whether to append the data to the end of the file. * @return Promise resolved when done. */ - writeFileDataInFile(file: any, path: string, onProgress?: (event: CoreFileProgressEvent) => any, offset: number = 0, - append?: boolean): Promise { + async writeFileDataInFile(file: Blob, path: string, onProgress?: (event: CoreFileProgressEvent) => void, offset: number = 0, + append?: boolean): Promise { offset = offset || 0; // Get the chunk to read. - const blob = file.slice(offset, Math.min(offset + this.CHUNK_SIZE, file.size)); + const readWholeFile = offset === 0 && this.CHUNK_SIZE >= file.size; + const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + this.CHUNK_SIZE, file.size)); + + try { + const fileEntry = await this.writeFileDataInFileChunk(chunk, path, append); - return this.writeFileDataInFileChunk(blob, path, append).then((fileEntry) => { offset += this.CHUNK_SIZE; onProgress && onProgress({ @@ -659,7 +662,15 @@ export class CoreFileProvider { // Read the next chunk. return this.writeFileDataInFile(file, path, onProgress, offset, true); - }); + } catch (error) { + if (readWholeFile || !error || error.name != 'NotReadableError') { + return Promise.reject(error); + } + + // Permission error when reading file in chunks. This usually happens with Google Drive files. + // Try to read the whole file at once. + return this.writeFileDataInFileChunk(file, path, false); + } } /** @@ -670,7 +681,7 @@ export class CoreFileProvider { * @param append Whether to append the data to the end of the file. * @return Promise resolved when done. */ - protected writeFileDataInFileChunk(chunkData: any, path: string, append?: boolean): Promise { + protected writeFileDataInFileChunk(chunkData: any, path: string, append?: boolean): Promise { // Read the chunk data. return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => { // Write the data in the file. @@ -1053,7 +1064,7 @@ export class CoreFileProvider { * @param fileEntry FileEntry retrieved from getFile or similar. * @return Promise resolved with metadata. */ - getMetadata(fileEntry: Entry): Promise { + getMetadata(fileEntry: Entry): Promise { if (!fileEntry || !fileEntry.getMetadata) { return Promise.reject(null); } From 4deaf3be80560ff2c7688b84961a5a91c8ee4112 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 8 Apr 2020 08:27:43 +0200 Subject: [PATCH 026/166] MOBILE-3270 core: Show warning if app crashed when uploading big file --- scripts/langindex.json | 1 + src/assets/lang/en.json | 1 + .../fileuploader/providers/file-handler.ts | 16 +- src/core/fileuploader/providers/helper.ts | 27 ++-- src/lang/en.json | 1 + src/providers/file-helper.ts | 146 +++++++++++++++++- src/providers/file.ts | 31 ++-- upgrade.txt | 4 + 8 files changed, 198 insertions(+), 29 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index 4810e4705..c275a91ed 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1373,6 +1373,7 @@ "core.confirmgotabrootdefault": "local_moodlemobileapp", "core.confirmloss": "local_moodlemobileapp", "core.confirmopeninbrowser": "local_moodlemobileapp", + "core.confirmreadfiletoobig": "local_moodlemobileapp", "core.considereddigitalminor": "moodle", "core.content": "moodle", "core.contenteditingsynced": "local_moodlemobileapp", diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 080e14b1c..7966066ec 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1373,6 +1373,7 @@ "core.confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?", "core.confirmloss": "Are you sure? All changes will be lost.", "core.confirmopeninbrowser": "Do you want to open it in a web browser?", + "core.confirmreadfiletoobig": "It seems the app previously crashed when trying to read a file as big as this one. Are you sure you want to continue?

    If this file is stored in a repository like Google Drive, please try to download the file to your device first and use the downloaded file.", "core.considereddigitalminor": "You are too young to create an account on this site.", "core.content": "Content", "core.contenteditingsynced": "The content you are editing has been synced.", diff --git a/src/core/fileuploader/providers/file-handler.ts b/src/core/fileuploader/providers/file-handler.ts index 9d4c92462..c89eaa03d 100644 --- a/src/core/fileuploader/providers/file-handler.ts +++ b/src/core/fileuploader/providers/file-handler.ts @@ -20,6 +20,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreFileUploaderHandler, CoreFileUploaderHandlerData } from './delegate'; import { CoreFileUploaderHelperProvider } from './helper'; import { CoreFileUploaderProvider } from './fileuploader'; +import { TranslateService } from '@ngx-translate/core'; /** * Handler to upload any type of file. */ @@ -28,9 +29,13 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler { name = 'CoreFileUploaderFile'; priority = 1200; - constructor(private appProvider: CoreAppProvider, private platform: Platform, private timeUtils: CoreTimeUtilsProvider, - private uploaderHelper: CoreFileUploaderHelperProvider, private uploaderProvider: CoreFileUploaderProvider, - private domUtils: CoreDomUtilsProvider) { } + constructor(protected appProvider: CoreAppProvider, + protected platform: Platform, + protected timeUtils: CoreTimeUtilsProvider, + protected uploaderHelper: CoreFileUploaderHelperProvider, + protected uploaderProvider: CoreFileUploaderProvider, + protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService) { } /** * Whether or not the handler is enabled on a site level. @@ -107,9 +112,8 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler { this.uploaderHelper.uploadFileObject(file, maxSize, upload, allowOffline, fileName).then((result) => { this.uploaderHelper.fileUploaded(result); }).catch((error) => { - if (error) { - this.domUtils.showErrorModal(error); - } + this.domUtils.showErrorModalDefault(error, + this.translate.instant('core.fileuploader.errorreadingfile')); }); }); diff --git a/src/core/fileuploader/providers/helper.ts b/src/core/fileuploader/providers/helper.ts index afaa6f909..903a5fda6 100644 --- a/src/core/fileuploader/providers/helper.ts +++ b/src/core/fileuploader/providers/helper.ts @@ -19,6 +19,7 @@ import { Camera, CameraOptions } from '@ionic-native/camera'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreFileProvider, CoreFileProgressEvent } from '@providers/file'; +import { CoreFileHelperProvider } from '@providers/file-helper'; import { CoreLoggerProvider } from '@providers/logger'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; @@ -36,11 +37,19 @@ export class CoreFileUploaderHelperProvider { protected filePickerDeferred: PromiseDefer; protected actionSheet: ActionSheet; - constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private translate: TranslateService, - private fileUploaderProvider: CoreFileUploaderProvider, private domUtils: CoreDomUtilsProvider, - private textUtils: CoreTextUtilsProvider, private fileProvider: CoreFileProvider, private utils: CoreUtilsProvider, - private actionSheetCtrl: ActionSheetController, private uploaderDelegate: CoreFileUploaderDelegate, - private camera: Camera, private platform: Platform) { + constructor(logger: CoreLoggerProvider, + protected appProvider: CoreAppProvider, + protected translate: TranslateService, + protected fileUploaderProvider: CoreFileUploaderProvider, + protected domUtils: CoreDomUtilsProvider, + protected textUtils: CoreTextUtilsProvider, + protected fileProvider: CoreFileProvider, + protected utils: CoreUtilsProvider, + protected actionSheetCtrl: ActionSheetController, + protected uploaderDelegate: CoreFileUploaderDelegate, + protected camera: Camera, + protected platform: Platform, + protected fileHelper: CoreFileHelperProvider) { this.logger = logger.getInstance('CoreFileUploaderProvider'); } @@ -99,14 +108,14 @@ export class CoreFileUploaderHelperProvider { const filePath = this.textUtils.concatenatePaths(CoreFileProvider.TMPFOLDER, newName); // Write the data into the file. - return this.fileProvider.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => { + return this.fileHelper.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => { this.showProgressModal(modal, 'core.fileuploader.readingfileperc', progress); }); }).catch((error) => { this.logger.error('Error reading file to upload.', error); modal.dismiss(); - return Promise.reject(this.translate.instant('core.fileuploader.errorreadingfile')); + return Promise.reject(error); }).then((fileEntry) => { modal.dismiss(); @@ -319,9 +328,7 @@ export class CoreFileUploaderHelperProvider { // Success uploading or picking, return the result. this.fileUploaded(result); }).catch((error) => { - if (error) { - this.domUtils.showErrorModal(error); - } + this.domUtils.showErrorModalDefault(error, this.translate.instant('core.fileuploader.errorreadingfile')); }); // Do not close the action sheet, it will be closed if success. diff --git a/src/lang/en.json b/src/lang/en.json index 3b9ccff0f..60d16355c 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -43,6 +43,7 @@ "confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?", "confirmloss": "Are you sure? All changes will be lost.", "confirmopeninbrowser": "Do you want to open it in a web browser?", + "confirmreadfiletoobig": "It seems the app previously crashed when trying to read a file as big as this one. Are you sure you want to continue?

    If this file is stored in a repository like Google Drive, please try to download the file to your device first and use the downloaded file.", "considereddigitalminor": "You are too young to create an account on this site.", "content": "Content", "contenteditingsynced": "The content you are editing has been synced.", diff --git a/src/providers/file-helper.ts b/src/providers/file-helper.ts index 00b4b4150..31a2e6e70 100644 --- a/src/providers/file-helper.ts +++ b/src/providers/file-helper.ts @@ -15,12 +15,15 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from './app'; -import { CoreFileProvider } from './file'; +import { CoreConfigProvider } from './config'; +import { CoreFileProvider, CoreFileProgressFunction } from './file'; import { CoreFilepoolProvider } from './filepool'; import { CoreSitesProvider } from './sites'; import { CoreWSProvider } from './ws'; +import { CoreDomUtilsProvider } from './utils/dom'; import { CoreUtilsProvider } from './utils/utils'; import { CoreConstants } from '@core/constants'; +import { FileEntry } from '@ionic-native/file'; import { makeSingleton } from '@singletons/core.singletons'; /** @@ -29,9 +32,23 @@ import { makeSingleton } from '@singletons/core.singletons'; @Injectable() export class CoreFileHelperProvider { - constructor(private fileProvider: CoreFileProvider, private filepoolProvider: CoreFilepoolProvider, - private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, private translate: TranslateService, - private utils: CoreUtilsProvider, private wsProvider: CoreWSProvider) { } + // Variables for reading files in chunks. + protected MAX_CHUNK_SIZE_NAME = 'file_max_chunk_size'; + protected READ_CHUNK_ATTEMPT_NAME = 'file_read_chunk_attempt'; + protected maxChunkSize = -1; + + constructor(protected fileProvider: CoreFileProvider, + protected filepoolProvider: CoreFilepoolProvider, + protected sitesProvider: CoreSitesProvider, + protected appProvider: CoreAppProvider, + protected translate: TranslateService, + protected utils: CoreUtilsProvider, + protected wsProvider: CoreWSProvider, + protected configProvider: CoreConfigProvider, + protected domUtils: CoreDomUtilsProvider) { + + this.initMaxChunkSize(); + } /** * Convenience function to open a file, downloading it if needed. @@ -240,6 +257,34 @@ export class CoreFileHelperProvider { return file.timemodified || 0; } + /** + * Initialize the max chunk size. + * + * @return Promise resolved when done. + */ + protected async initMaxChunkSize(): Promise { + const sizes = await Promise.all([ + await this.configProvider.get(this.READ_CHUNK_ATTEMPT_NAME, -1), // Check if there is any attempt pending. + await this.configProvider.get(this.MAX_CHUNK_SIZE_NAME, -1), // Retrieve current max chunk size from DB. + ]); + + const attemptSize = sizes[0]; + const maxChunkSize = sizes[1]; + + if (attemptSize != -1 && (maxChunkSize == -1 || attemptSize < maxChunkSize)) { + // Store the attempt's size as the max size. + this.storeMaxChunkSize(attemptSize); + } else { + // No attempt or the max size is already lower. Keep current max size. + this.maxChunkSize = maxChunkSize; + } + + if (attemptSize != -1) { + // Clean pending attempt. + await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME); + } + } + /** * Check if a state is downloaded or outdated. * @@ -334,6 +379,99 @@ export class CoreFileHelperProvider { throw new Error('Couldn\'t determine file size: ' + file.fileurl); } + + /** + * Save max chunk size. + * + * @param size Size to store. + * @return Promise resolved when done. + */ + protected async storeMaxChunkSize(size: number): Promise { + this.maxChunkSize = size; + + await this.configProvider.set(this.MAX_CHUNK_SIZE_NAME, size); + } + + /** + * Write some file data into a filesystem file. + * It's done in chunks to prevent crashing the app for big files. + * + * @param file The data to write. + * @param path Path where to store the data. + * @param onProgress Function to call on progress. + * @param offset Offset where to start reading from. + * @param append Whether to append the data to the end of the file. + * @return Promise resolved when done. + */ + async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0, + append?: boolean): Promise { + + offset = offset || 0; + + // Get the chunk to read and write. + const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size; + const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size)); + + try { + const fileEntry = await this.fileProvider.writeFileDataInFileChunk(chunk, path, append); + + offset += CoreFileProvider.CHUNK_SIZE; + + onProgress && onProgress({ + lengthComputable: true, + loaded: offset, + total: file.size + }); + + if (offset >= file.size) { + // Done, stop. + return fileEntry; + } + + // Read the next chunk. + return this.writeFileDataInFile(file, path, onProgress, offset, true); + } catch (error) { + if (readWholeFile || !error || error.name != 'NotReadableError') { + return Promise.reject(error); + } + + // Permission error when reading file in chunks. This usually happens with Google Drive files. + // Try to read the whole file at once. + return this.writeBigFileDataInFile(file, path, onProgress); + } + } + + /** + * Writes a big file data into a filesystem file without using chunks. + * The app can crash when doing this with big files, so this function will try to control the max size that works + * and warn the user if he's trying to upload a file that is too big. + * + * @param file The data to write. + * @param path Path where to store the data. + * @param onProgress Function to call on progress. + * @return Promise resolved with the file. + */ + protected async writeBigFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction): Promise { + if (this.maxChunkSize != -1 && file.size >= this.maxChunkSize) { + // The file size is bigger than the max allowed size. Ask the user to confirm. + await this.domUtils.showConfirm(this.translate.instant('core.confirmreadfiletoobig')); + } + + // Store the "attempt". + await this.configProvider.set(this.READ_CHUNK_ATTEMPT_NAME, file.size); + + // Write the whole file. + const fileEntry = await this.fileProvider.writeFileDataInFileChunk(file, path, false); + + // Success, remove the attempt and increase the max chunk size if needed. + await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME); + + if (file.size > this.maxChunkSize) { + await this.storeMaxChunkSize(file.size + 1); + } + + return fileEntry; + } } export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {} diff --git a/src/providers/file.ts b/src/providers/file.ts index 658560c42..5bc9140e8 100644 --- a/src/providers/file.ts +++ b/src/providers/file.ts @@ -44,6 +44,11 @@ export interface CoreFileProgressEvent { total?: number; } +/** + * Progress function. + */ +export type CoreFileProgressFunction = (event: CoreFileProgressEvent) => void; + /** * Factory to interact with the file system. */ @@ -60,14 +65,21 @@ export class CoreFileProvider { static SITESFOLDER = 'sites'; static TMPFOLDER = 'tmp'; + static CHUNK_SIZE = 10485760; // 10 MB. + protected logger; protected initialized = false; protected basePath = ''; protected isHTMLAPI = false; - protected CHUNK_SIZE = 10485760; // 10 MB. - constructor(logger: CoreLoggerProvider, private platform: Platform, private file: File, private appProvider: CoreAppProvider, - private textUtils: CoreTextUtilsProvider, private zip: Zip, private mimeUtils: CoreMimetypeUtilsProvider) { + constructor(logger: CoreLoggerProvider, + protected platform: Platform, + protected file: File, + protected appProvider: CoreAppProvider, + protected textUtils: CoreTextUtilsProvider, + protected zip: Zip, + protected mimeUtils: CoreMimetypeUtilsProvider) { + this.logger = logger.getInstance('CoreFileProvider'); if (platform.is('android') && !Object.getOwnPropertyDescriptor(FileReader.prototype, 'onloadend')) { @@ -634,20 +646,21 @@ export class CoreFileProvider { * @param offset Offset where to start reading from. * @param append Whether to append the data to the end of the file. * @return Promise resolved when done. + * @deprecated since 3.8.3. Please use CoreFileHelperProvider.writeFileDataInFile instead. */ - async writeFileDataInFile(file: Blob, path: string, onProgress?: (event: CoreFileProgressEvent) => void, offset: number = 0, + async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0, append?: boolean): Promise { offset = offset || 0; - // Get the chunk to read. - const readWholeFile = offset === 0 && this.CHUNK_SIZE >= file.size; - const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + this.CHUNK_SIZE, file.size)); + // Get the chunk to read and write. + const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size; + const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size)); try { const fileEntry = await this.writeFileDataInFileChunk(chunk, path, append); - offset += this.CHUNK_SIZE; + offset += CoreFileProvider.CHUNK_SIZE; onProgress && onProgress({ lengthComputable: true, @@ -681,7 +694,7 @@ export class CoreFileProvider { * @param append Whether to append the data to the end of the file. * @return Promise resolved when done. */ - protected writeFileDataInFileChunk(chunkData: any, path: string, append?: boolean): Promise { + writeFileDataInFileChunk(chunkData: Blob, path: string, append?: boolean): Promise { // Read the chunk data. return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => { // Write the data in the file. diff --git a/upgrade.txt b/upgrade.txt index 75333c0c4..f66263f6a 100644 --- a/upgrade.txt +++ b/upgrade.txt @@ -1,6 +1,10 @@ This files describes API changes in the Moodle Mobile app, information provided here is intended especially for developers. +=== 3.8.3 === + +- CoreFileProvider.writeFileDataInFile has been deprecated. Please use CoreFileHelperProvider.writeFileDataInFile instead. + === 3.8.0 === - CoreDomUtilsProvider.extractDownloadableFilesFromHtml and CoreDomUtilsProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects have been deprecated. Please use CoreFilepoolProvider.extractDownloadableFilesFromHtml and CoreFilepoolProvider.extractDownloadableFilesFromHtmlAsFakeFileObjects. We had to move them to prevent a circular dependency. From e97d4adafaba4af73cde2485e74f38ba3c4cec68 Mon Sep 17 00:00:00 2001 From: Tien Nguyen Phuc Date: Wed, 5 Feb 2020 08:04:35 +0700 Subject: [PATCH 027/166] MOBILE-3331 accessibility: Fix issues of Open in browser & PDF icons --- src/addon/mod/url/providers/module-handler.ts | 2 +- src/assets/lang/en.json | 1 + src/core/course/components/module/core-course-module.html | 6 +++--- src/lang/en.json | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/addon/mod/url/providers/module-handler.ts b/src/addon/mod/url/providers/module-handler.ts index 151dd2a8c..7d15e61fc 100644 --- a/src/addon/mod/url/providers/module-handler.ts +++ b/src/addon/mod/url/providers/module-handler.ts @@ -118,7 +118,7 @@ export class AddonModUrlModuleHandler implements CoreCourseModuleHandler { buttons: [ { hidden: true, // Hide it until we calculate if it should be displayed or not. icon: 'link', - label: 'core.openinbrowser', + label: 'core.openmodinbrowser', action: (event: Event, navCtrl: NavController, module: any, courseId: number): void => { handler.openUrl(module, courseId); } diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 080e14b1c..b25df240c 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1855,6 +1855,7 @@ "core.online": "Online", "core.openfullimage": "Click here to display the full size image", "core.openinbrowser": "Open in browser", + "core.openmodinbrowser": "Open {{$a}} in browser", "core.othergroups": "Other groups", "core.pagea": "Page {{$a}}", "core.parentlanguage": "", diff --git a/src/core/course/components/module/core-course-module.html b/src/core/course/components/module/core-course-module.html index 39358083f..9494aed55 100644 --- a/src/core/course/components/module/core-course-module.html +++ b/src/core/course/components/module/core-course-module.html @@ -1,8 +1,8 @@ - +

    - +
    @@ -13,7 +13,7 @@ -
    diff --git a/src/lang/en.json b/src/lang/en.json index 3b9ccff0f..83b98e37f 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -195,6 +195,7 @@ "online": "Online", "openfullimage": "Click here to display the full size image", "openinbrowser": "Open in browser", + "openmodinbrowser": "Open {{$a}} in browser", "othergroups": "Other groups", "pagea": "Page {{$a}}", "parentlanguage": "", From 0d7956c28c9b5d1b9664f2d15fda0ec8829f137e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 16 Apr 2020 10:53:41 +0200 Subject: [PATCH 028/166] MOBILE-3402 login: Improve login page UX --- src/app/app.scss | 13 -- src/assets/lang/en.json | 11 +- src/core/login/lang/en.json | 7 +- src/core/login/login.scss | 73 ++++--- .../change-password/change-password.html | 2 +- .../login/pages/credentials/credentials.html | 84 ++++---- .../login/pages/credentials/credentials.scss | 5 - .../login/pages/credentials/credentials.ts | 4 +- src/core/login/pages/reconnect/reconnect.html | 123 ++++++------ src/core/login/pages/reconnect/reconnect.scss | 4 +- .../login/pages/site-error/site-error.html | 27 --- .../pages/site-error/site-error.module.ts | 31 --- .../login/pages/site-error/site-error.scss | 3 - src/core/login/pages/site-error/site-error.ts | 41 ---- src/core/login/pages/site/site.html | 57 +++--- src/core/login/pages/site/site.scss | 121 ++++++++++-- src/core/login/pages/site/site.ts | 184 ++++++++++++++---- src/lang/en.json | 4 +- src/providers/sites.ts | 71 ++++++- src/providers/utils/dom.ts | 113 ++++++----- src/providers/utils/url.ts | 2 +- src/singletons/url.ts | 32 +++ src/theme/dark.scss | 10 - src/theme/variables.scss | 10 - 24 files changed, 594 insertions(+), 438 deletions(-) delete mode 100644 src/core/login/pages/credentials/credentials.scss delete mode 100644 src/core/login/pages/site-error/site-error.html delete mode 100644 src/core/login/pages/site-error/site-error.module.ts delete mode 100644 src/core/login/pages/site-error/site-error.scss delete mode 100644 src/core/login/pages/site-error/site-error.ts diff --git a/src/app/app.scss b/src/app/app.scss index a75d033d7..b384030c3 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -46,19 +46,6 @@ ion-app.app-root { text-transform: none; } - @include media-breakpoint-up(sm) { - .core-center-view .scroll-content { - display: flex!important; - align-content: center !important; - align-items: center !important; - > * { - margin: 0 auto; - width: 100%; - max-width: 600px; - } - } - } - @include media-breakpoint-down(sm) { .hidden-phone { display: none !important; diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index b25df240c..b5e6c754a 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1332,7 +1332,9 @@ "core.block.blocks": "Blocks", "core.browser": "Browser", "core.cancel": "Cancel", - "core.cannotconnect": "Cannot connect: Verify that you have correctly typed your site address.", + "core.cannotconnect": "Cannot connect", + "core.cannotconnecttrouble": "We're having trouble connecting to your site.", + "core.cannotconnectverify": "Please check the address is correct.", "core.cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.", "core.captureaudio": "Record audio", "core.capturedimage": "Taken picture.", @@ -1758,8 +1760,6 @@ "core.login.policyagreement": "Site policy agreement", "core.login.policyagreementclick": "Link to site policy agreement", "core.login.potentialidps": "Log in using your account on:", - "core.login.problemconnectingerror": "We're having trouble connecting to", - "core.login.problemconnectingerrorcontinue": "Double check you've entered the address correctly and try again.", "core.login.profileinvaliddata": "Invalid value", "core.login.recaptchachallengeimage": "reCAPTCHA challenge image", "core.login.recaptchaexpired": "Verification expired. Answer the security question again.", @@ -1773,7 +1773,7 @@ "core.login.selectacountry": "Select a country", "core.login.selectsite": "Please select your site:", "core.login.signupplugindisabled": "{{$a}} is not enabled.", - "core.login.siteaddress": "Your site address", + "core.login.siteaddress": "Your site", "core.login.sitehasredirect": "Your site contains at least one HTTP redirect. The app cannot follow redirects, this could be the issue that's preventing the app from connecting to your site.", "core.login.siteinmaintenance": "Your site is in maintenance mode", "core.login.sitepolicynotagreederror": "Site policy not agreed.", @@ -1787,7 +1787,8 @@ "core.login.usernamerequired": "Username required", "core.login.usernotaddederror": "User not added - error", "core.login.visitchangepassword": "Do you want to visit the site to change the password?", - "core.login.webservicesnotenabled": "Web services are not enabled in your site. Please contact your site administrator if you think they should be enabled.", + "core.login.webservicesnotenabled": "Your host site may not have enabled Web services. Please contact your administrator for help.", + "core.login.yourenteredsite": "Connect to your site", "core.lostconnection": "Your authentication token is invalid or has expired. You will have to reconnect to the site.", "core.mainmenu.changesite": "Change site", "core.mainmenu.help": "Help", diff --git a/src/core/login/lang/en.json b/src/core/login/lang/en.json index 3624b1063..7631d77bc 100644 --- a/src/core/login/lang/en.json +++ b/src/core/login/lang/en.json @@ -73,8 +73,6 @@ "policyagreement": "Site policy agreement", "policyagreementclick": "Link to site policy agreement", "potentialidps": "Log in using your account on:", - "problemconnectingerror": "We're having trouble connecting to", - "problemconnectingerrorcontinue": "Double check you've entered the address correctly and try again.", "profileinvaliddata": "Invalid value", "recaptchachallengeimage": "reCAPTCHA challenge image", "recaptchaexpired": "Verification expired. Answer the security question again.", @@ -88,7 +86,7 @@ "selectacountry": "Select a country", "selectsite": "Please select your site:", "signupplugindisabled": "{{$a}} is not enabled.", - "siteaddress": "Your site address", + "siteaddress": "Your site", "sitehasredirect": "Your site contains at least one HTTP redirect. The app cannot follow redirects, this could be the issue that's preventing the app from connecting to your site.", "siteinmaintenance": "Your site is in maintenance mode", "sitepolicynotagreederror": "Site policy not agreed.", @@ -102,5 +100,6 @@ "usernamerequired": "Username required", "usernotaddederror": "User not added - error", "visitchangepassword": "Do you want to visit the site to change the password?", - "webservicesnotenabled": "Web services are not enabled in your site. Please contact your site administrator if you think they should be enabled." + "yourenteredsite": "Connect to your site", + "webservicesnotenabled": "Your host site may not have enabled Web services. Please contact your administrator for help." } \ No newline at end of file diff --git a/src/core/login/login.scss b/src/core/login/login.scss index 7dce8dd70..2ea9290ef 100644 --- a/src/core/login/login.scss +++ b/src/core/login/login.scss @@ -1,11 +1,28 @@ +$core-login-page-background-color: $white !default; +$core-login-page-text-color: $text-color !default; +$core-login-button-outline: false !default; +$core-login-loading-color: false !default; +$core-login-item-inner-background-color: $white !default; +$core-login-item-background-color: $white !default; + +// Dark. +$core-dark-login-page-background-color: $black !default; +$core-dark-login-page-text-color: $core-dark-text-color !default; +$core-dark-login-item-inner-background-color: $core-dark-login-page-background-color !default; +$core-dark-login-item-background-color: $core-dark-login-page-background-color !default; +$core-dark-login-button-outline: $core-login-button-outline !default; +$core-dark-login-loading-color: $core-dark-text-color !default; + ion-app.app-root page-core-login-credentials, ion-app.app-root page-core-login-reconnect, ion-app.app-root page-core-login-site { .scroll-content { background: $core-login-page-background-color; + color: $core-login-page-text-color; @include darkmode() { background: $core-dark-login-page-background-color; + color: $core-dark-login-page-text-color; } } @@ -13,35 +30,18 @@ ion-app.app-root page-core-login-site { max-width: 100%; } - img.login-logo { - width: 90%; - max-width: 300px; - } - - .box { - padding: 16px; - margin: 8px; - background: $core-login-box-background-color; - border: 1px solid $core-login-box-background-border; - color: $core-login-box-text-color; - - @include darkmode() { - background: $core-dark-login-box-background-color; - border-color: $core-dark-login-box-background-border; - color: $core-dark-login-box-text-color; - } - - .item { - @include darkmode() { - background: $core-dark-login-box-background-color; - } - } - } - .core-sitename, .core-siteurl { @if $core-fixed-url { display: none; } } + .core-sitename + .core-siteurl { + margin-top: 0; + } + + .core-sitename { + font-size: 1.8rem; + } + @if $core-login-button-outline { .button-md.button-default-md, .button-ios.button-default-ios { @extend .button-md-light; @@ -77,4 +77,27 @@ ion-app.app-root page-core-login-site { .item-input { margin-bottom: 20px; } + + ion-list.core-login-forgotten-password { + margin-top: 0; + margin-bottom: 0; + + a.item { + background: transparent; + text-decoration: underline; + + @include darkmode() { + background: transparent; + } + } + } + + .core-login-site-logo { + margin-top: 5px; + margin-bottom: 5px; + img { + width: 90%; + max-width: 300px; + } + } } diff --git a/src/core/login/pages/change-password/change-password.html b/src/core/login/pages/change-password/change-password.html index 7c965a3a0..eb9f83042 100644 --- a/src/core/login/pages/change-password/change-password.html +++ b/src/core/login/pages/change-password/change-password.html @@ -8,7 +8,7 @@ - +

    {{ 'core.login.forcepasswordchangenotice' | translate }}

    diff --git a/src/core/login/pages/credentials/credentials.html b/src/core/login/pages/credentials/credentials.html index cff98e8b5..3bcde32fa 100644 --- a/src/core/login/pages/credentials/credentials.html +++ b/src/core/login/pages/credentials/credentials.html @@ -9,52 +9,54 @@ - + -
    -
    +
    + - - - - - - - +

    +

    {{siteUrl}}

    + + + + + + + + + diff --git a/src/core/login/pages/credentials/credentials.scss b/src/core/login/pages/credentials/credentials.scss deleted file mode 100644 index e93abd9d1..000000000 --- a/src/core/login/pages/credentials/credentials.scss +++ /dev/null @@ -1,5 +0,0 @@ -ion-app.app-root page-core-login-credentials { - .item-input { - margin-bottom: 20px; - } -} diff --git a/src/core/login/pages/credentials/credentials.ts b/src/core/login/pages/credentials/credentials.ts index 5c2d5909e..2702200bd 100644 --- a/src/core/login/pages/credentials/credentials.ts +++ b/src/core/login/pages/credentials/credentials.ts @@ -65,6 +65,8 @@ export class CoreLoginCredentialsPage { private eventsProvider: CoreEventsProvider) { this.siteUrl = navParams.get('siteUrl'); + this.siteName = navParams.get('siteName') || null; + this.logoUrl = navParams.get('logoUrl') || null; this.siteConfig = navParams.get('siteConfig'); this.urlToOpen = navParams.get('urlToOpen'); @@ -170,8 +172,6 @@ export class CoreLoginCredentialsPage { this.eventsProvider.trigger(CoreEventsProvider.LOGIN_SITE_CHECKED, { config: this.siteConfig }); } } else { - this.siteName = null; - this.logoUrl = null; this.authInstructions = null; this.canSignup = false; this.identityProviders = []; diff --git a/src/core/login/pages/reconnect/reconnect.html b/src/core/login/pages/reconnect/reconnect.html index 1b87186ee..986354d87 100644 --- a/src/core/login/pages/reconnect/reconnect.html +++ b/src/core/login/pages/reconnect/reconnect.html @@ -3,72 +3,69 @@ {{ 'core.login.reconnect' | translate }} - -
    -
    - - - - {{ 'core.pictureof' | translate:{$a: site.fullname} }} - - + +
    + + + + {{ 'core.pictureof' | translate:{$a: site.fullname} }} + + - - - - - - - -

    {{siteUrl}}

    - -

    -

    {{siteUrl}}

    - -

    - {{ 'core.login.reconnectdescription' | translate }} -

    -
    - - - - + + + + + + + + + + + + {{ 'core.login.cancel' | translate }} + +
    diff --git a/src/core/login/pages/reconnect/reconnect.scss b/src/core/login/pages/reconnect/reconnect.scss index a28e78d05..f6012b95b 100644 --- a/src/core/login/pages/reconnect/reconnect.scss +++ b/src/core/login/pages/reconnect/reconnect.scss @@ -30,7 +30,7 @@ ion-app.app-root page-core-login-reconnect { } } - .item-input { - margin-bottom: 20px; + .core-login-reconnect-warning { + color: $red; } } diff --git a/src/core/login/pages/site-error/site-error.html b/src/core/login/pages/site-error/site-error.html deleted file mode 100644 index 8c42122fc..000000000 --- a/src/core/login/pages/site-error/site-error.html +++ /dev/null @@ -1,27 +0,0 @@ - - - {{ 'core.error' | translate }} - - - - - - - -

    {{ 'core.whoops' | translate }}

    -

    {{ 'core.login.problemconnectingerror' | translate }}

    -

    {{siteUrl}}

    -

    {{ 'core.login.problemconnectingerrorcontinue' | translate }}

    - -

    {{ 'core.login.stillcantconnect' | translate }}

    -

    {{ 'core.login.contactyouradministrator' | translate }}

    -

    - {{ 'core.login.contactyouradministratorissue' | translate:{$a: ''} }} -

    -

    - -

    -
    - diff --git a/src/core/login/pages/site-error/site-error.module.ts b/src/core/login/pages/site-error/site-error.module.ts deleted file mode 100644 index 73332b1e1..000000000 --- a/src/core/login/pages/site-error/site-error.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import { NgModule } from '@angular/core'; -import { IonicPageModule } from 'ionic-angular'; -import { CoreLoginSiteErrorPage } from './site-error'; -import { TranslateModule } from '@ngx-translate/core'; -import { CoreDirectivesModule } from '@directives/directives.module'; - -@NgModule({ - declarations: [ - CoreLoginSiteErrorPage - ], - imports: [ - CoreDirectivesModule, - IonicPageModule.forChild(CoreLoginSiteErrorPage), - TranslateModule.forChild() - ] -}) -export class CoreLoginSiteErrorPageModule {} diff --git a/src/core/login/pages/site-error/site-error.scss b/src/core/login/pages/site-error/site-error.scss deleted file mode 100644 index 510539e27..000000000 --- a/src/core/login/pages/site-error/site-error.scss +++ /dev/null @@ -1,3 +0,0 @@ - page-core-login-site-error button.button.button-block { - margin-bottom: 3rem; - } \ No newline at end of file diff --git a/src/core/login/pages/site-error/site-error.ts b/src/core/login/pages/site-error/site-error.ts deleted file mode 100644 index 5d4df0e53..000000000 --- a/src/core/login/pages/site-error/site-error.ts +++ /dev/null @@ -1,41 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import { Component } from '@angular/core'; -import { IonicPage, ViewController, NavParams } from 'ionic-angular'; - -/** - * Component that displays an error when trying to connect to a site. - */ -@IonicPage({ segment: 'core-login-site-error' }) -@Component({ - selector: 'page-core-login-site-error', - templateUrl: 'site-error.html', -}) -export class CoreLoginSiteErrorPage { - siteUrl: string; - issue: string; - - constructor(private viewCtrl: ViewController, params: NavParams) { - this.siteUrl = params.get('siteUrl'); - this.issue = params.get('issue'); - } - - /** - * Close modal. - */ - closeModal(): void { - this.viewCtrl.dismiss(); - } -} diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html index 6d13b7507..9a4fe01bc 100644 --- a/src/core/login/pages/site/site.html +++ b/src/core/login/pages/site/site.html @@ -9,9 +9,9 @@ - -
    -
    + +
    +
    @@ -19,19 +19,36 @@

    {{ 'core.login.siteaddress' | translate }}

    - +
    + + + + + {{ 'core.login.selectsite' | translate }} {{site.name}} - -
    +

    {{ 'core.login.selectsite' | translate }}

    @@ -48,33 +65,9 @@ {{site.name}}
    - -
    - - - {{ 'core.whoops' | translate }} - - -

    - -

    {{ 'core.login.problemconnectingerror' | translate }}

    -

    {{ error.url }}

    -

    {{ 'core.login.problemconnectingerrorcontinue' | translate }}

    -
    -
    - - {{ 'core.login.stillcantconnect' | translate }} - - -

    {{ 'core.login.contactyouradministrator' | translate }}

    -

    {{ 'core.whoissiteadmin' | translate }}

    -
    -
    -
    - - - diff --git a/src/core/login/pages/site/site.scss b/src/core/login/pages/site/site.scss index 0a740cead..31fcbd528 100644 --- a/src/core/login/pages/site/site.scss +++ b/src/core/login/pages/site/site.scss @@ -11,23 +11,108 @@ ion-app.app-root page-core-login-site { } } - .core-site-error { - background: $red-light; - margin-left: 0; - margin-right: 0; - width: 100%; - user-select: text; - - p, ion-card-header { - color: $red-dark; - user-select: text; - } - ion-card-header { - font-weight: bold; - } - } - - .core-login-need-help { + .core-login-need-help.item { + background: transparent; text-decoration: underline; + + @include darkmode() { + background: transparent; + } } -} \ No newline at end of file + + .core-login-site-connect { + margin-top: 1.4rem; + } + + .item ion-thumbnail { + min-width: 50px; + min-height: 50px; + border-radius: 20%; + box-shadow: 0 0 4px #eee; + text-align: center; + + img { + width: 50px; + height: 50px; + } + ion-icon { + margin: 0 auto; + font-size: 40px; + line-height: 50px; + } + } + + .core-login-site-logo, + .core-login-site-list { + transition-delay: 0s; + visibility: visible; + opacity: 1; + transition: all 0.7s ease-in-out; + max-height: 9999px; + + &.hidden { + opacity: 0; + visibility: hidden; + margin: 0; + padding: 0; + max-height: 0; + } + } + + .core-login-site-list.dimmed { + pointer-events: none; + position: relative; + } + + .core-login-site-list-loading { + position: absolute; + @include position(0, 0, 0, 0); + width: 100%; + height: 100%; + display: flex; + align-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.5); + z-index: 1; + ion-spinner { + flex: 1; + } + } + + .core-login-site-nolist-loading { + text-align: center; + } + + .item.core-login-site-list-title { + ion-label, ion-label h2.item-heading { + margin-top: 0; + } + } + + @include media-breakpoint-up(md) { + .scroll-content > * { + max-width: 600px; + margin: 0 auto; + width: 100%; + } + .core-login-site-logo { + margin-top: 20%; + } + + &.hidden { + margin: 0; + } + } + + .core-login-entered-site { + background-color: $gray-lighter; + ion-thumbnail { + box-shadow: 0 0 4px #ddd; + } + } + + + .core-login-default-icon { + filter: grayscale(100%); + } +} diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index 400491069..ba8b1504b 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -13,36 +13,26 @@ // limitations under the License. import { Component, ViewChild, ElementRef } from '@angular/core'; -import { IonicPage, NavController, ModalController, NavParams } from 'ionic-angular'; +import { IonicPage, NavController, ModalController, AlertController, NavParams } from 'ionic-angular'; import { CoreAppProvider } from '@providers/app'; import { CoreEventsProvider } from '@providers/events'; -import { CoreSitesProvider, CoreSiteCheckResponse } from '@providers/sites'; +import { CoreSitesProvider, CoreSiteCheckResponse, CoreLoginSiteInfo } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreConfigConstants } from '../../../../configconstants'; import { CoreLoginHelperProvider } from '../../providers/helper'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, ValidatorFn, AbstractControl } from '@angular/forms'; import { CoreUrl } from '@singletons/url'; import { TranslateService } from '@ngx-translate/core'; /** - * Data about an error when connecting to a site. + * Extended data for UI implementation. */ -type CoreLoginSiteError = { - /** - * The error message that ocurred. - */ - message: string; - - /** - * URL the user entered. - */ - url?: string; - - /** - * URL the user entered with protocol added if needed. - */ - fullUrl?: string; +type CoreLoginSiteInfoExtended = CoreLoginSiteInfo & { + fromWS?: boolean; // If the site came from the WS call. + noProtocolUrl?: string; // Url wihtout protocol. + country?: string; // Based on countrycode. }; /** @@ -58,12 +48,16 @@ export class CoreLoginSitePage { @ViewChild('siteFormEl') formElement: ElementRef; siteForm: FormGroup; - fixedSites: any[]; - filteredSites: any[]; + fixedSites: CoreLoginSiteInfo[]; + filteredSites: CoreLoginSiteInfo[]; fixedDisplay = 'buttons'; showKeyboard = false; filter = ''; - error: CoreLoginSiteError; + sites: CoreLoginSiteInfoExtended[] = []; + hasSites = false; + loadingSites = false; + onlyWrittenSite = false; + searchFnc: Function; constructor(navParams: NavParams, protected navCtrl: NavController, @@ -72,10 +66,12 @@ export class CoreLoginSitePage { protected sitesProvider: CoreSitesProvider, protected loginHelper: CoreLoginHelperProvider, protected modalCtrl: ModalController, + protected alertCtrl: AlertController, + protected urlUtils: CoreUrlUtilsProvider, protected domUtils: CoreDomUtilsProvider, protected eventsProvider: CoreEventsProvider, protected translate: TranslateService, - protected urlUtils: CoreUrlUtilsProvider) { + protected utils: CoreUtilsProvider) { this.showKeyboard = !!navParams.get('showKeyboard'); @@ -94,8 +90,44 @@ export class CoreLoginSitePage { } this.siteForm = fb.group({ - siteUrl: [url, Validators.required] + siteUrl: [url, this.moodleUrlValidator()] }); + + this.searchFnc = this.utils.debounce(async (search: string, isValid: boolean = false) => { + search = search.trim(); + + if (search.length >= 3) { + this.onlyWrittenSite = false; + + // Update the sites list. + this.sites = await this.sitesProvider.findSites(search); + + // UI tweaks. + this.sites.forEach((site) => { + site.noProtocolUrl = CoreUrl.removeProtocol(site.url); + site.fromWS = true; + site.country = this.utils.getCountryName(site.countrycode); + }); + + // If it's a valid URL, add it. + if (isValid) { + this.onlyWrittenSite = !!this.sites.length; + this.sites.unshift({ + url: search, + fromWS: false, + name: this.translate.instant('core.login.yourenteredsite'), + noProtocolUrl: CoreUrl.removeProtocol(search), + }); + } + + this.hasSites = !!this.sites.length; + } else { + // Not reseting the array to allow animation to be displayed. + this.hasSites = false; + } + + this.loadingSites = false; + }, 1000); } /** @@ -103,8 +135,9 @@ export class CoreLoginSitePage { * * @param e Event. * @param url The URL to connect to. + * @param foundSite The site clicked, if any, from the found sites list. */ - connect(e: Event, url: string): void { + connect(e: Event, url: string, foundSite?: CoreLoginSiteInfoExtended): void { e.preventDefault(); e.stopPropagation(); @@ -130,8 +163,6 @@ export class CoreLoginSitePage { return; } - this.hideLoginIssue(); - const modal = this.domUtils.showModalLoading(), siteData = this.sitesProvider.getDemoSiteData(url); @@ -167,7 +198,7 @@ export class CoreLoginSitePage { return domain ? this.sitesProvider.checkSite(domain) : Promise.reject(error); }) - .then((result) => this.login(result)) + .then((result) => this.login(result, foundSite)) .catch((error) => this.showLoginIssue(url, error)) .finally(() => modal.dismiss()); } @@ -197,13 +228,6 @@ export class CoreLoginSitePage { modal.present(); } - /** - * Hide the login error. - */ - protected hideLoginIssue(): void { - this.error = null; - } - /** * Show an error that aims people to solve the issue. * @@ -211,13 +235,60 @@ export class CoreLoginSitePage { * @param error Error to display. */ protected showLoginIssue(url: string, error: any): void { - this.error = { - url: url, - message: this.domUtils.getErrorMessage(error), - }; + error = this.domUtils.getErrorMessage(error); + if (error == this.translate.instant('core.cannotconnecttrouble')) { + const found = this.sites.find((site) => site.fromWS && site.url == url); + + if (!found) { + error += ' ' + this.translate.instant('core.cannotconnectverify'); + } + } + + let message = '

    ' + error + '

    '; if (url) { - this.error.fullUrl = this.urlUtils.isAbsoluteURL(url) ? url : 'https://' + url; + const fullUrl = this.urlUtils.isAbsoluteURL(url) ? url : 'https://' + url; + message += '

    ' + url + '

    '; + } + + const buttons = [ + { + text: this.translate.instant('core.needhelp'), + handler: (): void => { + this.showHelp(); + } + }, + { + text: this.translate.instant('core.tryagain'), + role: 'cancel' + } + ]; + + this.domUtils.showAlertWithButtons(this.translate.instant('core.cannotconnect'), message, buttons); + } + + /** + * Find a site on the backend. + * + * @param e Event. + * @param search Text to search. + */ + searchSite(e: Event, search: string): void { + this.loadingSites = true; + + this.searchFnc(search.trim(), this.siteForm.valid); + } + + /** + * Get the demo data for a certain "name" if it is a demo site. + * + * @param name Name of the site to check. + * @return Site data if it's a demo site, undefined otherwise. + */ + getDemoSiteData(name: string): any { + const demoSites = CoreConfigConstants.demo_sites; + if (typeof demoSites != 'undefined' && typeof demoSites[name] != 'undefined') { + return demoSites[name]; } } @@ -225,10 +296,11 @@ export class CoreLoginSitePage { * Process login to a site. * * @param response Response obtained from the site check request. + * @param foundSite The site clicked, if any, from the found sites list. * * @return Promise resolved after logging in. */ - protected async login(response: CoreSiteCheckResponse): Promise { + protected async login(response: CoreSiteCheckResponse, foundSite?: CoreLoginSiteInfoExtended): Promise { return this.sitesProvider.checkRequiredMinimumVersion(response.config).then(() => { this.domUtils.triggerFormSubmittedEvent(this.formElement, true); @@ -242,11 +314,39 @@ export class CoreLoginSitePage { this.loginHelper.confirmAndOpenBrowserForSSOLogin( response.siteUrl, response.code, response.service, response.config && response.config.launchurl); } else { - this.navCtrl.push('CoreLoginCredentialsPage', { siteUrl: response.siteUrl, siteConfig: response.config }); + const pageParams = { siteUrl: response.siteUrl, siteConfig: response.config }; + if (foundSite) { + pageParams['siteName'] = foundSite.name; + pageParams['logoUrl'] = foundSite.imageurl; + } + + this.navCtrl.push('CoreLoginCredentialsPage', pageParams); } }).catch(() => { // Ignore errors. }); } + /** + * Validate Url. + * + * @return {ValidatorFn} Validation results. + */ + protected moodleUrlValidator(): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} | null => { + const value = control.value.trim(); + let valid = value.length >= 3 && CoreUrl.isValidMoodleUrl(value); + + if (!valid) { + const demo = !!this.getDemoSiteData(value); + + if (demo) { + valid = true; + } + } + + return valid ? null : {siteUrl: {value: control.value}}; + }; + } + } diff --git a/src/lang/en.json b/src/lang/en.json index 83b98e37f..73e7322db 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -12,7 +12,9 @@ "back": "Back", "browser": "Browser", "cancel": "Cancel", - "cannotconnect": "Cannot connect: Verify that you have correctly typed your site address.", + "cannotconnect": "Cannot connect", + "cannotconnecttrouble": "We're having trouble connecting to your site.", + "cannotconnectverify": "Please check the address is correct.", "cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.", "captureaudio": "Record audio", "capturedimage": "Taken picture.", diff --git a/src/providers/sites.ts b/src/providers/sites.ts index f0f85df99..405009119 100644 --- a/src/providers/sites.ts +++ b/src/providers/sites.ts @@ -165,6 +165,41 @@ export interface CoreSiteSchema { migrate?(db: SQLiteDB, oldVersion: number, siteId: string): Promise | void; } +/** + * Data about sites to be listed. + */ +export interface CoreLoginSiteInfo { + /** + * Site name. + */ + name: string; + + /** + * Site alias. + */ + alias?: string; + + /** + * URL of the site. + */ + url: string; + + /** + * Image URL of the site. + */ + imageurl?: string; + + /** + * City of the site. + */ + city?: string; + + /** + * Countrycode of the site. + */ + countrycode?: string; +} + /** * Registered site schema. */ @@ -367,10 +402,17 @@ export class CoreSitesProvider { ] }; - constructor(logger: CoreLoggerProvider, private http: HttpClient, private sitesFactory: CoreSitesFactoryProvider, - private appProvider: CoreAppProvider, private translate: TranslateService, private urlUtils: CoreUrlUtilsProvider, - private eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider, - private utils: CoreUtilsProvider, private injector: Injector, private wsProvider: CoreWSProvider, + constructor(logger: CoreLoggerProvider, + protected http: HttpClient, + protected sitesFactory: CoreSitesFactoryProvider, + protected appProvider: CoreAppProvider, + protected translate: TranslateService, + protected urlUtils: CoreUrlUtilsProvider, + protected eventsProvider: CoreEventsProvider, + protected textUtils: CoreTextUtilsProvider, + protected utils: CoreUtilsProvider, + protected injector: Injector, + protected wsProvider: CoreWSProvider, protected domUtils: CoreDomUtilsProvider) { this.logger = logger.getInstance('CoreSitesProvider'); @@ -431,7 +473,7 @@ export class CoreSitesProvider { } else if (this.textUtils.getErrorMessageFromError(secondError)) { return Promise.reject(secondError); } else { - return this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION}); + return this.translate.instant('core.cannotconnecttrouble'); } }); }); @@ -523,8 +565,7 @@ export class CoreSitesProvider { error.error = this.translate.instant('core.login.sitehasredirect'); } else { // We can't be sure if there is a redirect or not. Display cannot connect error. - error.error = this.translate.instant('core.cannotconnect', - {$a: CoreSite.MINIMUM_MOODLE_VERSION}); + error.error = this.translate.instant('core.cannotconnecttrouble'); } return Promise.reject(error); @@ -569,7 +610,7 @@ export class CoreSitesProvider { return this.http.post(siteUrl + '/login/token.php', {}).timeout(this.wsProvider.getRequestTimeout()).toPromise() .catch(() => { // Default error messages are kinda bad, return our own message. - return Promise.reject({error: this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION})}); + return Promise.reject({error: this.translate.instant('core.cannotconnecttrouble')}); }).then((data: any) => { if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) { @@ -611,7 +652,7 @@ export class CoreSitesProvider { return promise.then((data: any): any => { if (typeof data == 'undefined') { - return Promise.reject(this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION})); + return Promise.reject(this.translate.instant('core.cannotconnecttrouble')); } else { if (typeof data.token != 'undefined') { return { token: data.token, siteUrl: siteUrl, privateToken: data.privatetoken }; @@ -643,7 +684,7 @@ export class CoreSitesProvider { } } }, () => { - return Promise.reject(this.translate.instant('core.cannotconnect', {$a: CoreSite.MINIMUM_MOODLE_VERSION})); + return Promise.reject(this.translate.instant('core.cannotconnecttrouble')); }); } @@ -1926,6 +1967,16 @@ export class CoreSitesProvider { return {}; } } + + /** + * Returns site info found on the backend. + * + * @param search Searched text. + * @return Site info list. + */ + async findSites(search: string): Promise { + return []; + } } export class CoreSites extends makeSingleton(CoreSitesProvider) {} diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index 743a333ec..b4c904f9a 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -15,7 +15,7 @@ import { Injectable, SimpleChange, ElementRef } from '@angular/core'; import { LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content, PopoverController, - ModalController, + ModalController, AlertButton } from 'ionic-angular'; import { DomSanitizer } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; @@ -1138,65 +1138,76 @@ export class CoreDomUtilsProvider { * @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed. * @return Promise resolved with the alert modal. */ - showAlert(title: string, message: string, buttonText?: string, autocloseTime?: number): Promise { + async showAlert(title: string, message: string, buttonText?: string, autocloseTime?: number): Promise { + const buttons = [buttonText || this.translate.instant('core.ok')]; + + return this.showAlertWithButtons(title, message, buttons, autocloseTime); + } + + /** + * Show an alert modal with some buttons. + * + * @param title Title to show. + * @param message Message to show. + * @param buttons Buttons objects or texts. + * @param autocloseTime Number of milliseconds to wait to close the modal. If not defined, modal won't be closed. + * @return Promise resolved with the alert modal. + */ + async showAlertWithButtons(title: string, message: string, buttons: (string | AlertButton)[], autocloseTime?: number): + Promise { const hasHTMLTags = this.textUtils.hasHTMLTags(message); - let promise; if (hasHTMLTags) { // Format the text. - promise = this.textUtils.formatText(message); - } else { - promise = Promise.resolve(message); + message = await this.textUtils.formatText(message); } - return promise.then((message) => { - const alertId = Md5.hashAsciiStr((title || '') + '#' + (message || '')); + const alertId = Md5.hashAsciiStr((title || '') + '#' + (message || '')); - if (this.displayedAlerts[alertId]) { - // There's already an alert with the same message and title. Return it. - return this.displayedAlerts[alertId]; - } + if (this.displayedAlerts[alertId]) { + // There's already an alert with the same message and title. Return it. + return this.displayedAlerts[alertId]; + } - const alert: CoreAlert = this.alertCtrl.create({ - title: title, - message: message, - buttons: [buttonText || this.translate.instant('core.ok')] - }); - - alert.present().then(() => { - if (hasHTMLTags) { - // Treat all anchors so they don't override the app. - const alertMessageEl: HTMLElement = alert.pageRef().nativeElement.querySelector('.alert-message'); - this.treatAnchors(alertMessageEl); - } - }); - - // Store the alert and remove it when dismissed. - this.displayedAlerts[alertId] = alert; - - // Define the observables to extend the Alert class. This will allow several callbacks instead of just one. - alert.didDismiss = new Subject(); - alert.willDismiss = new Subject(); - - // Set the callbacks to trigger an observable event. - alert.onDidDismiss((data: any, role: string) => { - delete this.displayedAlerts[alertId]; - - alert.didDismiss.next({data: data, role: role}); - }); - - alert.onWillDismiss((data: any, role: string) => { - alert.willDismiss.next({data: data, role: role}); - }); - - if (autocloseTime > 0) { - setTimeout(() => { - alert.dismiss(); - }, autocloseTime); - } - - return alert; + const alert: CoreAlert = this.alertCtrl.create({ + title: title, + message: message, + buttons: buttons, }); + + alert.present().then(() => { + if (hasHTMLTags) { + // Treat all anchors so they don't override the app. + const alertMessageEl: HTMLElement = alert.pageRef().nativeElement.querySelector('.alert-message'); + this.treatAnchors(alertMessageEl); + } + }); + + // Store the alert and remove it when dismissed. + this.displayedAlerts[alertId] = alert; + + // Define the observables to extend the Alert class. This will allow several callbacks instead of just one. + alert.didDismiss = new Subject(); + alert.willDismiss = new Subject(); + + // Set the callbacks to trigger an observable event. + alert.onDidDismiss((data: any, role: string) => { + delete this.displayedAlerts[alertId]; + + alert.didDismiss.next({data: data, role: role}); + }); + + alert.onWillDismiss((data: any, role: string) => { + alert.willDismiss.next({data: data, role: role}); + }); + + if (autocloseTime > 0) { + setTimeout(() => { + alert.dismiss(); + }, autocloseTime); + } + + return alert; } /** diff --git a/src/providers/utils/url.ts b/src/providers/utils/url.ts index f9b07929b..7700b6e18 100644 --- a/src/providers/utils/url.ts +++ b/src/providers/utils/url.ts @@ -225,7 +225,7 @@ export class CoreUrlUtilsProvider { url = 'https://' + url; } - // http allways in lowercase. + // http always in lowercase. url = url.replace(/^http/i, 'http'); url = url.replace(/^https/i, 'https'); diff --git a/src/singletons/url.ts b/src/singletons/url.ts index 2539d19c6..d777c8f27 100644 --- a/src/singletons/url.ts +++ b/src/singletons/url.ts @@ -119,4 +119,36 @@ export class CoreUrl { return urlParts && urlParts.domain ? urlParts.domain : null; } + /** + * Returns the pattern to check if the URL is a valid Moodle Url. + * + * @return {RegExp} Desired RegExp. + */ + static getValidMoodleUrlPattern(): RegExp { + // Regular expression based on RFC 3986: https://tools.ietf.org/html/rfc3986#appendix-B. + // Improved to not admit spaces. + return new RegExp(/^(([^:/?# ]+):)?(\/\/([^/?# ]*))?([^?# ]*)(\?([^#]*))?(#(.*))?$/); + } + + /** + * Check if the given url is valid for the app to connect. + * + * @param {string} url Url to check. + * @return {boolean} True if valid, false otherwise. + */ + static isValidMoodleUrl(url: string): boolean { + const patt = CoreUrl.getValidMoodleUrlPattern(); + + return patt.test(url.trim()); + } + + /** + * Removes protocol from the url. + * + * @param url Site url. + * @return Url without protocol. + */ + static removeProtocol(url: string): string { + return url.replace(/^[a-zA-Z]+:\/\//i, ''); + } } diff --git a/src/theme/dark.scss b/src/theme/dark.scss index 94ce2b6b1..6411791bc 100644 --- a/src/theme/dark.scss +++ b/src/theme/dark.scss @@ -6,16 +6,6 @@ $core-dark-item-bg-color: $gray-darker !default; $core-dark-item-divider-bg-color: $gray-dark !default; $core-dark-background-color: $black !default; -// Login. -$core-dark-login-page-background-color: radial-gradient(white, $gray-dark) !default; -$core-dark-login-box-background-color: $black !default; -$core-dark-login-box-background-border: $core-login-box-background-border !default; -$core-dark-login-box-text-color: $core-dark-text-color !default; -$core-dark-login-item-inner-background-color: $core-dark-login-box-background-color !default; -$core-dark-login-item-background-color: $core-dark-login-box-background-color !default; -$core-dark-login-button-outline: $core-login-button-outline !default; -$core-dark-login-loading-color: $core-dark-text-color !default; - ion-app.app-root { @include darkmode() { ion-action-sheet .action-sheet-container .action-sheet-group .action-sheet-button { diff --git a/src/theme/variables.scss b/src/theme/variables.scss index aefe54083..61f401678 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -184,16 +184,6 @@ $core-button-outline-background-color: $white !default; $core-network-message-height: 16px !default; -// Login. -$core-login-page-background-color: radial-gradient(white, $gray-light) !default; -$core-login-box-background-color: $white !default; -$core-login-box-background-border: $gray !default; -$core-login-box-text-color: $text-color !default; -$core-login-button-outline: false !default; -$core-login-loading-color: false !default; -$core-login-item-inner-background-color: $white !default; -$core-login-item-background-color: $white !default; - $core-action-sheet-color: $core-color !default; $core-action-sheet-cancel-color: $danger !default; $core-dark-action-sheet-cancel-color: $danger-dark !default; From 30a2710114fc38d4b8ebcfc6ac2a94f58c5b6599 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 10 Oct 2019 12:29:26 +0200 Subject: [PATCH 029/166] MOBILE-2995 qr: Add QR plugin in the app --- config.xml | 1 + package-lock.json | 31 +++++ package.json | 7 +- src/core/emulator/emulator.module.ts | 11 ++ src/core/emulator/providers/qr-scanner.ts | 160 ++++++++++++++++++++++ 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 src/core/emulator/providers/qr-scanner.ts diff --git a/config.xml b/config.xml index 1282a7a65..cd9f0ab61 100644 --- a/config.xml +++ b/config.xml @@ -170,6 +170,7 @@ + diff --git a/package-lock.json b/package-lock.json index 956c7923b..074dd3600 100644 --- a/package-lock.json +++ b/package-lock.json @@ -182,6 +182,11 @@ "resolved": "https://registry.npmjs.org/@ionic-native/push/-/push-4.20.0.tgz", "integrity": "sha512-IgzaZd8KSPLwyLX1emRijlQ0Vfa3RlPPBx370lVH32c8zG3DFH1xfQQbb39KF3qmX5b6so0pGGA2holSUwVm2w==" }, + "@ionic-native/qr-scanner": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@ionic-native/qr-scanner/-/qr-scanner-4.20.0.tgz", + "integrity": "sha512-eLeJQq49/x5bdCVLotuMHZZ3YGEpSzuEnuX2vno2ugdGSygBm+wxIVSa9Nuz8HozYwC6oyii+zH/pg4SZ+4V9Q==" + }, "@ionic-native/screen-orientation": { "version": "4.20.0", "resolved": "https://registry.npmjs.org/@ionic-native/screen-orientation/-/screen-orientation-4.20.0.tgz", @@ -2705,6 +2710,14 @@ "resolved": "https://registry.npmjs.org/cordova-plugin-network-information/-/cordova-plugin-network-information-2.0.2.tgz", "integrity": "sha512-NwO3qDBNL/vJxUxBTPNOA1HvkDf9eTeGH8JSZiwy1jq2W2mJKQEDBwqWkaEQS19Yd/MQTiw0cykxg5D7u4J6cQ==" }, + "cordova-plugin-qrscanner": { + "version": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#43952839ce97887d1c6cad53c7d668fe3370aedd", + "from": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#dist", + "requires": { + "qrcode-reader": "^1.0.4", + "webrtc-adapter": "^3.1.4" + } + }, "cordova-plugin-screen-orientation": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/cordova-plugin-screen-orientation/-/cordova-plugin-screen-orientation-3.0.2.tgz", @@ -10224,6 +10237,11 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "qrcode-reader": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/qrcode-reader/-/qrcode-reader-1.0.4.tgz", + "integrity": "sha512-rRjALGNh9zVqvweg1j5OKIQKNsw3bLC+7qwlnead5K/9cb1cEIAGkwikt/09U0K+2IDWGD9CC6SP7tHAjUeqvQ==" + }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", @@ -11127,6 +11145,11 @@ } } }, + "sdp": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-1.5.4.tgz", + "integrity": "sha1-jgOPbdsUvXZa4fS1IW4SCUUR4NA=" + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -13864,6 +13887,14 @@ "source-map": "~0.6.1" } }, + "webrtc-adapter": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-3.4.3.tgz", + "integrity": "sha1-tjYGLu6abvFYrNDYUBtnhDS1bxY=", + "requires": { + "sdp": "^1.5.0" + } + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", diff --git a/package.json b/package.json index 941127fae..d1b669d91 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@ionic-native/media-capture": "4.20.0", "@ionic-native/network": "4.20.0", "@ionic-native/push": "4.20.0", + "@ionic-native/qr-scanner": "4.20.0", "@ionic-native/screen-orientation": "4.20.0", "@ionic-native/splash-screen": "4.20.0", "@ionic-native/sqlite": "4.20.0", @@ -98,6 +99,7 @@ "cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle", "cordova-plugin-media-capture": "3.0.3", "cordova-plugin-network-information": "2.0.2", + "cordova-plugin-qrscanner": "git+https://github.com/moodlemobile/cordova-plugin-qrscanner.git#dist", "cordova-plugin-screen-orientation": "3.0.2", "cordova-plugin-splashscreen": "5.0.3", "cordova-plugin-statusbar": "2.4.3", @@ -194,7 +196,8 @@ "cordova-plugin-advanced-http": { "OKHTTP_VERSION": "3.10.0" }, - "cordova-plugin-wkwebview-cookies": {} + "cordova-plugin-wkwebview-cookies": {}, + "cordova-plugin-qrscanner": {} } }, "main": "desktop/electron.js", @@ -254,4 +257,4 @@ "deleteAppDataOnUninstall": true } } -} +} \ No newline at end of file diff --git a/src/core/emulator/emulator.module.ts b/src/core/emulator/emulator.module.ts index a24a2b08e..5f9886c9a 100644 --- a/src/core/emulator/emulator.module.ts +++ b/src/core/emulator/emulator.module.ts @@ -31,6 +31,7 @@ import { LocalNotifications } from '@ionic-native/local-notifications'; import { MediaCapture } from '@ionic-native/media-capture'; import { Network } from '@ionic-native/network'; import { Push } from '@ionic-native/push'; +import { QRScanner } from '@ionic-native/qr-scanner'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { SQLite } from '@ionic-native/sqlite'; @@ -51,12 +52,14 @@ import { LocalNotificationsMock } from './providers/local-notifications'; import { MediaCaptureMock } from './providers/media-capture'; import { NetworkMock } from './providers/network'; import { PushMock } from './providers/push'; +import { QRScannerMock } from './providers/qr-scanner'; import { ZipMock } from './providers/zip'; import { CoreEmulatorHelperProvider } from './providers/helper'; import { CoreEmulatorCaptureHelperProvider } from './providers/capture-helper'; import { CoreAppProvider } from '@providers/app'; import { CoreFileProvider } from '@providers/file'; +import { CoreLoggerProvider } from '@providers/logger'; import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUrlUtilsProvider } from '@providers/utils/url'; @@ -80,6 +83,7 @@ export const IONIC_NATIVE_PROVIDERS = [ MediaCapture, Network, Push, + QRScanner, SplashScreen, StatusBar, SQLite, @@ -206,6 +210,13 @@ export const IONIC_NATIVE_PROVIDERS = [ return appProvider.isMobile() ? new Push() : new PushMock(appProvider); } }, + { + provide: QRScanner, + deps: [CoreAppProvider, CoreLoggerProvider], + useFactory: (appProvider: CoreAppProvider, loggerProvider: CoreLoggerProvider): QRScanner => { + return appProvider.isMobile() ? new QRScanner() : new QRScannerMock(loggerProvider); + } + }, SplashScreen, StatusBar, SQLite, diff --git a/src/core/emulator/providers/qr-scanner.ts b/src/core/emulator/providers/qr-scanner.ts new file mode 100644 index 000000000..668a74f5c --- /dev/null +++ b/src/core/emulator/providers/qr-scanner.ts @@ -0,0 +1,160 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner'; +import { Observable } from 'rxjs'; +import { CoreLoggerProvider } from '@providers/logger'; + +/** + * Emulates the Cordova QR Scanner plugin in desktop apps and in browser. + */ +@Injectable() +export class QRScannerMock extends QRScanner { + protected logger; + + constructor(logger: CoreLoggerProvider) { + super(); + + this.logger = logger.getInstance('QRScannerMock'); + } + + /** + * Request permission to use QR scanner. + * + * @return Promise. + */ + prepare(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Call this method to enable scanning. You must then call the `show` method to make the camera preview visible. + * + * @return Observable that emits the scanned text. Unsubscribe from the observable to stop scanning. + */ + scan(): Observable { + this.logger.error('QRScanner isn\'t available in desktop apps.'); + + return null; + } + + /** + * Configures the native webview to have a transparent background, then sets the background of the and DOM + * elements to transparent, allowing the webview to re-render with the transparent background. + * + * @return Promise. + */ + show(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Configures the native webview to be opaque with a white background, covering the video preview. + * + * @return Promise. + */ + hide(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Enable the device's light (for scanning in low-light environments). + * + * @return Promise. + */ + enableLight(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Destroy the scanner instance. + * + * @return Promise. + */ + destroy(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Disable the device's light. + * + * @return Promise. + */ + disableLight(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Use front camera + * + * @return Promise. + */ + useFrontCamera(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Use back camera + * + * @return Promise. + */ + useBackCamera(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Set camera to be used. + * + * @param camera Provide `0` for back camera, and `1` for front camera. + * @return Promise. + */ + useCamera(camera: number): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Pauses the video preview on the current frame and pauses scanning. + * + * @return Promise. + */ + pausePreview(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Resumse the video preview and resumes scanning. + * + * @return Promise. + */ + resumePreview(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Returns permission status + * + * @return Promise. + */ + getStatus(): Promise { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + /** + * Opens settings to edit app permissions. + */ + openSettings(): void { + this.logger.error('QRScanner isn\'t available in desktop apps.'); + } +} From e14b3ed0f8628c71aa5014d21b7832fbf02366e9 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 11 Oct 2019 09:18:56 +0200 Subject: [PATCH 030/166] MOBILE-2995 qr: Add scan QR option in more menu --- src/app/app.scss | 14 ++ src/assets/lang/en.json | 2 + src/core/mainmenu/pages/more/more.html | 4 + src/core/mainmenu/pages/more/more.ts | 43 +++++- .../viewer/pages/qr-scanner/qr-scanner.html | 13 ++ .../pages/qr-scanner/qr-scanner.module.ts | 31 ++++ .../viewer/pages/qr-scanner/qr-scanner.ts | 79 ++++++++++ src/lang/en.json | 2 + src/providers/utils/utils.ts | 138 +++++++++++++++++- 9 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 src/core/viewer/pages/qr-scanner/qr-scanner.html create mode 100644 src/core/viewer/pages/qr-scanner/qr-scanner.module.ts create mode 100644 src/core/viewer/pages/qr-scanner/qr-scanner.ts diff --git a/src/app/app.scss b/src/app/app.scss index b384030c3..064b7bfdb 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -1275,3 +1275,17 @@ ion-app.app-root { } } } + +// QR scan. The scanner is at the background of the app, we need to hide the elements that overlay it. +.core-scanning-qr { + ion-app.app-root { + background-color: transparent; + + .ion-page { + background-color: transparent; + } + ion-content, ion-backdrop, ion-modal:not(.core-modal-fullscreen), core-ion-tabs { + display: none; + } + } +} diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 7f19738e8..193426e84 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1868,6 +1868,7 @@ "core.previous": "Previous", "core.proceed": "Proceed", "core.pulltorefresh": "Pull to refresh", + "core.qrscanner": "QR scanner", "core.question.answer": "Answer", "core.question.answersaved": "Answer saved", "core.question.cannotdeterminestatus": "Cannot determine status", @@ -1910,6 +1911,7 @@ "core.retry": "Retry", "core.save": "Save", "core.savechanges": "Save changes", + "core.scanqr": "Scan QR code", "core.search": "Search", "core.searching": "Searching", "core.searchresults": "Search results", diff --git a/src/core/mainmenu/pages/more/more.html b/src/core/mainmenu/pages/more/more.html index d2d3908d1..4b2949e7a 100644 --- a/src/core/mainmenu/pages/more/more.html +++ b/src/core/mainmenu/pages/more/more.html @@ -31,6 +31,10 @@

    {{item.label}}

    + + +

    {{ 'core.scanqr' | translate }}

    +

    {{ 'core.mainmenu.website' | translate }}

    diff --git a/src/core/mainmenu/pages/more/more.ts b/src/core/mainmenu/pages/more/more.ts index 864402eef..ebcab3684 100644 --- a/src/core/mainmenu/pages/more/more.ts +++ b/src/core/mainmenu/pages/more/more.ts @@ -16,9 +16,13 @@ import { Component, OnDestroy } from '@angular/core'; import { IonicPage, NavController } from 'ionic-angular'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreMainMenuDelegate, CoreMainMenuHandlerData } from '../../providers/delegate'; import { CoreMainMenuProvider, CoreMainMenuCustomItem } from '../../providers/mainmenu'; import { CoreLoginHelperProvider } from '@core/login/providers/helper'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { TranslateService } from '@ngx-translate/core'; /** * Page that displays the list of main menu options that aren't in the tabs. @@ -35,6 +39,7 @@ export class CoreMainMenuMorePage implements OnDestroy { siteInfo: any; siteName: string; logoutLabel: string; + showScanQR: boolean; showWeb: boolean; showHelp: boolean; docsUrl: string; @@ -45,14 +50,22 @@ export class CoreMainMenuMorePage implements OnDestroy { protected langObserver; protected updateSiteObserver; - constructor(private menuDelegate: CoreMainMenuDelegate, private sitesProvider: CoreSitesProvider, - private navCtrl: NavController, private mainMenuProvider: CoreMainMenuProvider, - eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider) { + constructor(private menuDelegate: CoreMainMenuDelegate, + private sitesProvider: CoreSitesProvider, + private navCtrl: NavController, + private mainMenuProvider: CoreMainMenuProvider, + eventsProvider: CoreEventsProvider, + private loginHelper: CoreLoginHelperProvider, + private utils: CoreUtilsProvider, + private linkHelper: CoreContentLinksHelperProvider, + private textUtils: CoreTextUtilsProvider, + private translate: TranslateService) { this.langObserver = eventsProvider.on(CoreEventsProvider.LANGUAGE_CHANGED, this.loadSiteInfo.bind(this)); this.updateSiteObserver = eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.loadSiteInfo.bind(this), sitesProvider.getCurrentSiteId()); this.loadSiteInfo(); + this.showScanQR = this.utils.canScanQR(); } /** @@ -155,6 +168,30 @@ export class CoreMainMenuMorePage implements OnDestroy { this.navCtrl.push('CoreSitePreferencesPage'); } + /** + * Scan and treat a QR code. + */ + scanQR(): void { + // Scan for a QR code. + this.utils.scanQR().then((text) => { + if (text) { + // Check if it's a URL. We basically check it has a protocol and doesn't include any space. + if (/^[^:]{2,}:\/\/[^ ]+$/i.test(text)) { + // Check if the app can handle the URL. + this.linkHelper.handleLink(text, undefined, this.navCtrl, true, true).then((treated) => { + if (!treated) { + // Can't handle it, open it in browser. + this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(text); + } + }); + } else { + // It's not a URL, open it in a modal so the user can see it and copy it. + this.textUtils.expandText(this.translate.instant('core.qrscanner'), text); + } + } + }); + } + /** * Logout the user. */ diff --git a/src/core/viewer/pages/qr-scanner/qr-scanner.html b/src/core/viewer/pages/qr-scanner/qr-scanner.html new file mode 100644 index 000000000..dac2e266c --- /dev/null +++ b/src/core/viewer/pages/qr-scanner/qr-scanner.html @@ -0,0 +1,13 @@ + + + {{ title }} + + + + + + + + diff --git a/src/core/viewer/pages/qr-scanner/qr-scanner.module.ts b/src/core/viewer/pages/qr-scanner/qr-scanner.module.ts new file mode 100644 index 000000000..db7f83fa7 --- /dev/null +++ b/src/core/viewer/pages/qr-scanner/qr-scanner.module.ts @@ -0,0 +1,31 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreViewerQRScannerPage } from './qr-scanner'; +import { CoreDirectivesModule } from '@directives/directives.module'; + +@NgModule({ + declarations: [ + CoreViewerQRScannerPage + ], + imports: [ + CoreDirectivesModule, + IonicPageModule.forChild(CoreViewerQRScannerPage), + TranslateModule.forChild() + ] +}) +export class CoreViewerQRScannerPageModule {} diff --git a/src/core/viewer/pages/qr-scanner/qr-scanner.ts b/src/core/viewer/pages/qr-scanner/qr-scanner.ts new file mode 100644 index 000000000..49a2060e7 --- /dev/null +++ b/src/core/viewer/pages/qr-scanner/qr-scanner.ts @@ -0,0 +1,79 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { IonicPage, ViewController, NavParams } from 'ionic-angular'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreUtilsProvider } from '@providers/utils/utils'; + +/** + * Page to scan a QR code. + */ +@IonicPage({ segment: 'core-viewer-qr-scanner' }) +@Component({ + selector: 'page-core-viewer-qr-scanner', + templateUrl: 'qr-scanner.html', +}) +export class CoreViewerQRScannerPage { + title: string; // Page title. + + constructor(params: NavParams, + translate: TranslateService, + protected viewCtrl: ViewController, + protected domUtils: CoreDomUtilsProvider, + protected utils: CoreUtilsProvider) { + + this.title = params.get('title') || translate.instant('core.scanqr'); + + this.utils.startScanQR().then((text) => { + // Text captured, return it. + text = typeof text == 'string' ? text.trim() : ''; + + this.closeModal(text); + }).catch((error) => { + if (!error.coreCanceled) { + // Show error and stop scanning. + this.domUtils.showErrorModalDefault(error, 'An error occurred.'); + this.utils.stopScanQR(); + } + + this.closeModal(); + }); + } + + /** + * Cancel scanning. + */ + cancel(): void { + this.utils.stopScanQR(); + } + + /** + * Close modal. + * + * @param text The text to return (if any). + */ + closeModal(text?: string): void { + this.viewCtrl.dismiss(text); + } + + /** + * View will leave. + */ + ionViewWillLeave(): void { + // If this code is reached and scan hasn't been stopped yet it means the user clicked the back button, cancel. + this.utils.stopScanQR(); + } +} diff --git a/src/lang/en.json b/src/lang/en.json index 7764553bb..cc4d99e42 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -209,6 +209,7 @@ "previous": "Previous", "proceed": "Proceed", "pulltorefresh": "Pull to refresh", + "qrscanner": "QR scanner", "quotausage": "You have currently used {{$a.used}} of your {{$a.total}} limit.", "redirectingtosite": "You will be redirected to the site.", "refresh": "Refresh", @@ -223,6 +224,7 @@ "retry": "Retry", "save": "Save", "savechanges": "Save changes", + "scanqr": "Scan QR code", "search": "Search", "searching": "Searching", "searchresults": "Search results", diff --git a/src/providers/utils/utils.ts b/src/providers/utils/utils.ts index b3781a706..49d562d18 100644 --- a/src/providers/utils/utils.ts +++ b/src/providers/utils/utils.ts @@ -13,11 +13,12 @@ // limitations under the License. import { Injectable, NgZone } from '@angular/core'; -import { Platform } from 'ionic-angular'; +import { Platform, ModalController } from 'ionic-angular'; import { InAppBrowser, InAppBrowserObject } from '@ionic-native/in-app-browser'; import { Clipboard } from '@ionic-native/clipboard'; import { FileOpener } from '@ionic-native/file-opener'; import { WebIntent } from '@ionic-native/web-intent'; +import { QRScanner } from '@ionic-native/qr-scanner'; import { CoreAppProvider } from '../app'; import { CoreDomUtilsProvider } from './dom'; import { CoreMimetypeUtilsProvider } from './mimetype'; @@ -28,6 +29,7 @@ import { TranslateService } from '@ngx-translate/core'; import { CoreLangProvider } from '../lang'; import { CoreWSProvider, CoreWSError } from '../ws'; import { CoreFile } from '../file'; +import { Subscription } from 'rxjs'; import { makeSingleton } from '@singletons/core.singletons'; /** @@ -63,12 +65,25 @@ export class CoreUtilsProvider { protected logger; protected iabInstance: InAppBrowserObject; protected uniqueIds: {[name: string]: number} = {}; + protected qrScanData: {deferred: PromiseDefer, observable: Subscription}; - constructor(private iab: InAppBrowser, private appProvider: CoreAppProvider, private clipboard: Clipboard, - private domUtils: CoreDomUtilsProvider, logger: CoreLoggerProvider, private translate: TranslateService, - private platform: Platform, private langProvider: CoreLangProvider, private eventsProvider: CoreEventsProvider, - private fileOpener: FileOpener, private mimetypeUtils: CoreMimetypeUtilsProvider, private webIntent: WebIntent, - private wsProvider: CoreWSProvider, private zone: NgZone, private textUtils: CoreTextUtilsProvider) { + constructor(protected iab: InAppBrowser, + protected appProvider: CoreAppProvider, + protected clipboard: Clipboard, + protected domUtils: CoreDomUtilsProvider, + logger: CoreLoggerProvider, + protected translate: TranslateService, + protected platform: Platform, + protected langProvider: CoreLangProvider, + protected eventsProvider: CoreEventsProvider, + protected fileOpener: FileOpener, + protected mimetypeUtils: CoreMimetypeUtilsProvider, + protected webIntent: WebIntent, + protected wsProvider: CoreWSProvider, + protected zone: NgZone, + protected textUtils: CoreTextUtilsProvider, + protected modalCtrl: ModalController, + protected qrScanner: QRScanner) { this.logger = logger.getInstance('CoreUtilsProvider'); } @@ -1420,6 +1435,117 @@ export class CoreUtilsProvider { return debounced; } + + /** + * Check whether the app can scan QR codes. + * + * @return Whether the app can scan QR codes. + */ + canScanQR(): boolean { + return this.appProvider.isMobile(); + } + + /** + * Open a modal to scan a QR code. + * + * @param title Title of the modal. Defaults to "QR reader". + * @return Promise resolved with the captured text or undefined if cancelled or error. + */ + scanQR(title?: string): Promise { + return new Promise((resolve, reject): void => { + const modal = this.modalCtrl.create('CoreViewerQRScannerPage', { + title: title + }, { cssClass: 'core-modal-fullscreen'}); + + modal.present(); + + modal.onDidDismiss((data) => { + resolve(data); + }); + }); + } + + /** + * Start scanning for a QR code. + * + * @return Promise resolved with the QR string, rejected if error or cancelled. + */ + startScanQR(): Promise { + if (!this.appProvider.isMobile()) { + return Promise.reject('QRScanner isn\'t available in desktop apps.'); + } + + // Ask the user for permission to use the camera. + // The scan method also does this, but since it returns an Observable we wouldn't be able to detect if the user denied. + return this.qrScanner.prepare().then((status) => { + + if (!status.authorized) { + // No access to the camera, reject. In android this shouldn't happen, denying access passes through catch. + return Promise.reject('The user denied camera access.'); + } + + if (this.qrScanData && this.qrScanData.deferred) { + // Already scanning. + return this.qrScanData.deferred.promise; + } + + // Start scanning. + this.qrScanData = { + deferred: this.promiseDefer(), + observable: this.qrScanner.scan().subscribe((text) => { + + // Text received, stop scanning and return the text. + this.stopScanQR(text, false); + }) + }; + + // Show the camera. + return this.qrScanner.show().then(() => { + document.body.classList.add('core-scanning-qr'); + + return this.qrScanData.deferred.promise; + }, (err) => { + this.stopScanQR(err, true); + + return Promise.reject(err); + }); + + }).catch((err) => { + err.message = err.message || err._message; + + return Promise.reject(err); + }); + } + + /** + * Stop scanning for QR code. If no param is provided, the app will consider the user cancelled. + * + * @param data If success, the text of the QR code. If error, the error object or message. Undefined for cancelled. + * @param error True if the data belongs to an error, false otherwise. + */ + stopScanQR(data?: any, error?: boolean): void { + + if (!this.qrScanData) { + // Not scanning. + return; + } + + // Hide camera preview. + document.body.classList.remove('core-scanning-qr'); + this.qrScanner.hide(); + + this.qrScanData.observable.unsubscribe(); // Stop scanning. + + if (error) { + this.qrScanData.deferred.reject(data); + } else if (typeof data != 'undefined') { + this.qrScanData.deferred.resolve(data); + } else { + this.qrScanData.deferred.reject({coreCanceled: true}); + } + + delete this.qrScanData; + } } export class CoreUtils extends makeSingleton(CoreUtilsProvider) {} From 394dd6e24d8fe1bfddc00657ebc1be17587671fa Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 11 Oct 2019 12:44:33 +0200 Subject: [PATCH 031/166] MOBILE-2995 qr: Add scan QR button in login --- src/core/login/pages/site/site.html | 5 +++++ src/core/login/pages/site/site.ts | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html index 9a4fe01bc..637c8c90e 100644 --- a/src/core/login/pages/site/site.html +++ b/src/core/login/pages/site/site.html @@ -47,6 +47,11 @@ {{site.name}} + +
    + + {{ 'core.scanqr' | translate }} + diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts index 180e0ed47..4546cf012 100644 --- a/src/core/login/pages/site/site.ts +++ b/src/core/login/pages/site/site.ts @@ -58,6 +58,7 @@ export class CoreLoginSitePage { loadingSites = false; onlyWrittenSite = false; searchFnc: Function; + showScanQR: boolean; constructor(navParams: NavParams, protected navCtrl: NavController, @@ -74,6 +75,7 @@ export class CoreLoginSitePage { protected utils: CoreUtilsProvider) { this.showKeyboard = !!navParams.get('showKeyboard'); + this.showScanQR = this.utils.canScanQR(); let url = ''; @@ -356,4 +358,17 @@ export class CoreLoginSitePage { }; } + /** + * Scan a QR code and put its text in the URL input. + */ + scanQR(): void { + // Scan for a QR code. + this.utils.scanQR().then((text) => { + if (text) { + this.siteForm.controls.siteUrl.setValue(text); + + this.connect(new Event('click'), text); + } + }); + } } From c3f39abafa40514dd34fd0c0c29bf2300cbbf627 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 11 Oct 2019 16:02:28 +0200 Subject: [PATCH 032/166] MOBILE-2995 qr: Add QR button in RTE --- .../core-editor-rich-text-editor.html | 5 +++++ .../rich-text-editor/rich-text-editor.ts | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/core/editor/components/rich-text-editor/core-editor-rich-text-editor.html b/src/core/editor/components/rich-text-editor/core-editor-rich-text-editor.html index 20faba16e..4423c4b7a 100644 --- a/src/core/editor/components/rich-text-editor/core-editor-rich-text-editor.html +++ b/src/core/editor/components/rich-text-editor/core-editor-rich-text-editor.html @@ -71,6 +71,11 @@ + + + + diff --git a/src/core/viewer/pages/text/text.scss b/src/core/viewer/pages/text/text.scss new file mode 100644 index 000000000..4377e35e3 --- /dev/null +++ b/src/core/viewer/pages/text/text.scss @@ -0,0 +1,5 @@ +ion-app.app-root page-core-viewer-text { + ion-footer { + padding: 6px; + } +} diff --git a/src/core/viewer/pages/text/text.ts b/src/core/viewer/pages/text/text.ts index 6c8c1b6f8..935978391 100644 --- a/src/core/viewer/pages/text/text.ts +++ b/src/core/viewer/pages/text/text.ts @@ -15,6 +15,7 @@ import { Component } from '@angular/core'; import { IonicPage, ViewController, NavParams } from 'ionic-angular'; import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreUtils } from '@providers/utils/utils'; /** * Page to render a certain text. If opened as a modal, it will have a button to close the modal. @@ -34,6 +35,7 @@ export class CoreViewerTextPage { contextLevel: string; // The context level. instanceId: number; // The instance ID related to the context. courseId: number; // Course ID the text belongs to. It can be used to improve performance with filters. + displayCopyButton: boolean; // Whether to display a button to copy the contents. constructor(private viewCtrl: ViewController, params: NavParams, textUtils: CoreTextUtilsProvider) { this.title = params.get('title'); @@ -45,6 +47,7 @@ export class CoreViewerTextPage { this.contextLevel = params.get('contextLevel'); this.instanceId = params.get('instanceId'); this.courseId = params.get('courseId'); + this.displayCopyButton = !!params.get('displayCopyButton'); } /** @@ -53,4 +56,11 @@ export class CoreViewerTextPage { closeModal(): void { this.viewCtrl.dismiss(); } + + /** + * Copy the text to clipboard. + */ + copyText(): void { + CoreUtils.instance.copyToClipboard(this.content); + } } diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index fdec21043..f5c9f8f4b 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -307,8 +307,14 @@ export class CoreFormatTextDirective implements OnChanges { // Open a new state with the contents. const filter = typeof this.filter != 'undefined' ? this.utils.isTrueOrOne(this.filter) : undefined; - this.textUtils.expandText(this.fullTitle || this.translate.instant('core.description'), this.text, - this.component, this.componentId, undefined, filter, this.contextLevel, this.contextInstanceId, this.courseId); + this.textUtils.viewText(this.fullTitle || this.translate.instant('core.description'), this.text, { + component: this.component, + componentId: this.componentId, + filter: filter, + contextLevel: this.contextLevel, + instanceId: this.contextInstanceId, + courseId: this.courseId, + }); } } diff --git a/src/lang/en.json b/src/lang/en.json index cc4d99e42..8d279f23c 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -51,6 +51,7 @@ "contenteditingsynced": "The content you are editing has been synced.", "continue": "Continue", "copiedtoclipboard": "Text copied to clipboard", + "copytoclipboard": "Copy to clipboard", "course": "Course", "coursedetails": "Course details", "coursenogroups": "You are not a member of any group of this course.", diff --git a/src/providers/utils/text.ts b/src/providers/utils/text.ts index 3cac7f846..5ba186d9b 100644 --- a/src/providers/utils/text.ts +++ b/src/providers/utils/text.ts @@ -441,28 +441,20 @@ export class CoreTextUtilsProvider { * @param contextLevel The context level. * @param instanceId The instance ID related to the context. * @param courseId Course ID the text belongs to. It can be used to improve performance with filters. + * @deprecated since 3.8.3. Please use viewText instead. */ expandText(title: string, text: string, component?: string, componentId?: string | number, files?: any[], filter?: boolean, contextLevel?: string, instanceId?: number, courseId?: number): void { - if (text.length > 0) { - const params: any = { - title: title, - content: text, - component: component, - componentId: componentId, - files: files, - filter: filter, - contextLevel: contextLevel, - instanceId: instanceId, - courseId: courseId - }; - // Open a modal with the contents. - params.isModal = true; - - const modal = this.modalCtrl.create('CoreViewerTextPage', params); - modal.present(); - } + return this.viewText(title, text, { + component, + componentId, + files, + filter, + contextLevel, + instanceId, + courseId, + }); } /** @@ -1133,6 +1125,50 @@ export class CoreTextUtilsProvider { return _unserialize((data + ''), 0)[2]; } + + /** + * Shows a text on a new page. + * + * @param title Title of the new state. + * @param text Content of the text to be expanded. + * @param component Component to link the embedded files to. + * @param componentId An ID to use in conjunction with the component. + * @param files List of files to display along with the text. + * @param filter Whether the text should be filtered. + * @param contextLevel The context level. + * @param instanceId The instance ID related to the context. + * @param courseId Course ID the text belongs to. It can be used to improve performance with filters. + */ + viewText(title: string, text: string, options?: CoreTextUtilsViewTextOptions): void { + if (text.length > 0) { + options = options || {}; + + const params: any = { + title: title, + content: text, + isModal: true, + }; + + Object.assign(params, options); + + const modal = this.modalCtrl.create('CoreViewerTextPage', params); + modal.present(); + } + } } +/** + * Options for viewText. + */ +export type CoreTextUtilsViewTextOptions = { + component?: string; // Component to link the embedded files to. + componentId?: string | number; // An ID to use in conjunction with the component. + files?: any[]; // List of files to display along with the text. + filter?: boolean; // Whether the text should be filtered. + contextLevel?: string; // The context level. + instanceId?: number; // The instance ID related to the context. + courseId?: number; // Course ID the text belongs to. It can be used to improve performance with filters. + displayCopyButton?: boolean; // Whether to display a button to copy the text. +}; + export class CoreTextUtils extends makeSingleton(CoreTextUtilsProvider) {} From b845a1449b050027f5af046ce2435a12be44fa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 28 Apr 2020 13:31:55 +0200 Subject: [PATCH 038/166] MOBILE-3401 ionic: Remove resources --- config.xml | 81 --------------- resources/android/icon-foreground.svg | 98 ------------------ resources/android/icon.png.md5 | 1 - resources/android/icon/drawable-hdpi-icon.png | Bin 2480 -> 0 bytes resources/android/icon/drawable-ldpi-icon.png | Bin 1329 -> 0 bytes resources/android/icon/drawable-mdpi-icon.png | Bin 1687 -> 0 bytes .../android/icon/drawable-xhdpi-icon.png | Bin 3195 -> 0 bytes .../android/icon/drawable-xxhdpi-icon.png | Bin 4696 -> 0 bytes .../android/icon/drawable-xxxhdpi-icon.png | Bin 6272 -> 0 bytes resources/android/icon/hdpi-foreground.png | Bin 3461 -> 0 bytes resources/android/icon/ldpi-foreground.png | Bin 1678 -> 0 bytes resources/android/icon/mdpi-foreground.png | Bin 2245 -> 0 bytes resources/android/icon/xhdpi-foreground.png | Bin 4496 -> 0 bytes resources/android/icon/xxhdpi-foreground.png | Bin 7003 -> 0 bytes resources/android/icon/xxxhdpi-foreground.png | Bin 9933 -> 0 bytes .../splash/drawable-land-hdpi-screen.png | Bin 10631 -> 0 bytes .../splash/drawable-land-ldpi-screen.png | Bin 4003 -> 0 bytes .../splash/drawable-land-mdpi-screen.png | Bin 6132 -> 0 bytes .../splash/drawable-land-xhdpi-screen.png | Bin 18494 -> 0 bytes .../splash/drawable-land-xxhdpi-screen.png | Bin 25854 -> 0 bytes .../splash/drawable-land-xxxhdpi-screen.png | Bin 33932 -> 0 bytes .../splash/drawable-port-hdpi-screen.png | Bin 10835 -> 0 bytes .../splash/drawable-port-ldpi-screen.png | Bin 4078 -> 0 bytes .../splash/drawable-port-mdpi-screen.png | Bin 6232 -> 0 bytes .../splash/drawable-port-xhdpi-screen.png | Bin 19067 -> 0 bytes .../splash/drawable-port-xxhdpi-screen.png | Bin 25073 -> 0 bytes .../splash/drawable-port-xxxhdpi-screen.png | Bin 32436 -> 0 bytes resources/{android => }/icon.png | Bin resources/ios/icon.png | Bin 18809 -> 0 bytes resources/ios/icon.png.md5 | 1 - resources/ios/icon/icon-1024.png | Bin 20032 -> 0 bytes resources/ios/icon/icon-108@2x.png | Bin 5673 -> 0 bytes resources/ios/icon/icon-20.png | Bin 608 -> 0 bytes resources/ios/icon/icon-20@2x.png | Bin 1193 -> 0 bytes resources/ios/icon/icon-20@3x.png | Bin 1644 -> 0 bytes resources/ios/icon/icon-24@2x.png | Bin 1397 -> 0 bytes resources/ios/icon/icon-27.5@2x.png | Bin 1577 -> 0 bytes resources/ios/icon/icon-29.png | Bin 851 -> 0 bytes resources/ios/icon/icon-29@2x.png | Bin 1612 -> 0 bytes resources/ios/icon/icon-29@3x.png | Bin 2340 -> 0 bytes resources/ios/icon/icon-40.png | Bin 1193 -> 0 bytes resources/ios/icon/icon-40@2x.png | Bin 2140 -> 0 bytes resources/ios/icon/icon-40@3x.png | Bin 3100 -> 0 bytes resources/ios/icon/icon-44@2x.png | Bin 2300 -> 0 bytes resources/ios/icon/icon-50.png | Bin 1386 -> 0 bytes resources/ios/icon/icon-50@2x.png | Bin 2575 -> 0 bytes resources/ios/icon/icon-60.png | Bin 1644 -> 0 bytes resources/ios/icon/icon-60@2x.png | Bin 3100 -> 0 bytes resources/ios/icon/icon-60@3x.png | Bin 4683 -> 0 bytes resources/ios/icon/icon-72.png | Bin 1970 -> 0 bytes resources/ios/icon/icon-72@2x.png | Bin 3763 -> 0 bytes resources/ios/icon/icon-76.png | Bin 2076 -> 0 bytes resources/ios/icon/icon-76@2x.png | Bin 3943 -> 0 bytes resources/ios/icon/icon-83.5@2x.png | Bin 4199 -> 0 bytes resources/ios/icon/icon-86@2x.png | Bin 4378 -> 0 bytes resources/ios/icon/icon-98@2x.png | Bin 5008 -> 0 bytes resources/ios/icon/icon-small.png | Bin 851 -> 0 bytes resources/ios/icon/icon-small@2x.png | Bin 1612 -> 0 bytes resources/ios/icon/icon-small@3x.png | Bin 2340 -> 0 bytes resources/ios/icon/icon.png | Bin 1563 -> 0 bytes resources/ios/icon/icon@2x.png | Bin 2980 -> 0 bytes resources/ios/splash/Default-1792h~iphone.png | Bin 27457 -> 0 bytes resources/ios/splash/Default-2436h.png | Bin 40154 -> 0 bytes resources/ios/splash/Default-2688h~iphone.png | Bin 46270 -> 0 bytes .../ios/splash/Default-568h@2x~iphone.png | Bin 16374 -> 0 bytes resources/ios/splash/Default-667h.png | Bin 19833 -> 0 bytes resources/ios/splash/Default-736h.png | Bin 37292 -> 0 bytes .../splash/Default-Landscape-1792h~iphone.png | Bin 28130 -> 0 bytes .../ios/splash/Default-Landscape-2436h.png | Bin 41974 -> 0 bytes .../splash/Default-Landscape-2688h~iphone.png | Bin 48177 -> 0 bytes .../ios/splash/Default-Landscape-736h.png | Bin 38609 -> 0 bytes .../ios/splash/Default-Landscape@2x~ipad.png | Bin 37335 -> 0 bytes .../ios/splash/Default-Landscape@~ipadpro.png | Bin 44093 -> 0 bytes .../ios/splash/Default-Landscape~ipad.png | Bin 15329 -> 0 bytes .../ios/splash/Default-Portrait@2x~ipad.png | Bin 37447 -> 0 bytes .../ios/splash/Default-Portrait@~ipadpro.png | Bin 45081 -> 0 bytes .../ios/splash/Default-Portrait~ipad.png | Bin 15514 -> 0 bytes resources/ios/splash/Default@2x~iphone.png | Bin 14001 -> 0 bytes .../splash/Default@2x~universal~anyany.png | Bin 50719 -> 0 bytes resources/ios/splash/Default~iphone.png | Bin 6232 -> 0 bytes resources/splash.png.md5 | 1 - 81 files changed, 182 deletions(-) delete mode 100644 resources/android/icon-foreground.svg delete mode 100644 resources/android/icon.png.md5 delete mode 100644 resources/android/icon/drawable-hdpi-icon.png delete mode 100644 resources/android/icon/drawable-ldpi-icon.png delete mode 100644 resources/android/icon/drawable-mdpi-icon.png delete mode 100644 resources/android/icon/drawable-xhdpi-icon.png delete mode 100644 resources/android/icon/drawable-xxhdpi-icon.png delete mode 100644 resources/android/icon/drawable-xxxhdpi-icon.png delete mode 100644 resources/android/icon/hdpi-foreground.png delete mode 100644 resources/android/icon/ldpi-foreground.png delete mode 100644 resources/android/icon/mdpi-foreground.png delete mode 100644 resources/android/icon/xhdpi-foreground.png delete mode 100644 resources/android/icon/xxhdpi-foreground.png delete mode 100644 resources/android/icon/xxxhdpi-foreground.png delete mode 100644 resources/android/splash/drawable-land-hdpi-screen.png delete mode 100644 resources/android/splash/drawable-land-ldpi-screen.png delete mode 100644 resources/android/splash/drawable-land-mdpi-screen.png delete mode 100644 resources/android/splash/drawable-land-xhdpi-screen.png delete mode 100644 resources/android/splash/drawable-land-xxhdpi-screen.png delete mode 100644 resources/android/splash/drawable-land-xxxhdpi-screen.png delete mode 100644 resources/android/splash/drawable-port-hdpi-screen.png delete mode 100644 resources/android/splash/drawable-port-ldpi-screen.png delete mode 100644 resources/android/splash/drawable-port-mdpi-screen.png delete mode 100644 resources/android/splash/drawable-port-xhdpi-screen.png delete mode 100644 resources/android/splash/drawable-port-xxhdpi-screen.png delete mode 100644 resources/android/splash/drawable-port-xxxhdpi-screen.png rename resources/{android => }/icon.png (100%) delete mode 100644 resources/ios/icon.png delete mode 100644 resources/ios/icon.png.md5 delete mode 100644 resources/ios/icon/icon-1024.png delete mode 100644 resources/ios/icon/icon-108@2x.png delete mode 100644 resources/ios/icon/icon-20.png delete mode 100644 resources/ios/icon/icon-20@2x.png delete mode 100644 resources/ios/icon/icon-20@3x.png delete mode 100644 resources/ios/icon/icon-24@2x.png delete mode 100644 resources/ios/icon/icon-27.5@2x.png delete mode 100644 resources/ios/icon/icon-29.png delete mode 100644 resources/ios/icon/icon-29@2x.png delete mode 100644 resources/ios/icon/icon-29@3x.png delete mode 100644 resources/ios/icon/icon-40.png delete mode 100644 resources/ios/icon/icon-40@2x.png delete mode 100644 resources/ios/icon/icon-40@3x.png delete mode 100644 resources/ios/icon/icon-44@2x.png delete mode 100644 resources/ios/icon/icon-50.png delete mode 100644 resources/ios/icon/icon-50@2x.png delete mode 100644 resources/ios/icon/icon-60.png delete mode 100644 resources/ios/icon/icon-60@2x.png delete mode 100644 resources/ios/icon/icon-60@3x.png delete mode 100644 resources/ios/icon/icon-72.png delete mode 100644 resources/ios/icon/icon-72@2x.png delete mode 100644 resources/ios/icon/icon-76.png delete mode 100644 resources/ios/icon/icon-76@2x.png delete mode 100644 resources/ios/icon/icon-83.5@2x.png delete mode 100644 resources/ios/icon/icon-86@2x.png delete mode 100644 resources/ios/icon/icon-98@2x.png delete mode 100644 resources/ios/icon/icon-small.png delete mode 100644 resources/ios/icon/icon-small@2x.png delete mode 100644 resources/ios/icon/icon-small@3x.png delete mode 100644 resources/ios/icon/icon.png delete mode 100644 resources/ios/icon/icon@2x.png delete mode 100644 resources/ios/splash/Default-1792h~iphone.png delete mode 100644 resources/ios/splash/Default-2436h.png delete mode 100644 resources/ios/splash/Default-2688h~iphone.png delete mode 100644 resources/ios/splash/Default-568h@2x~iphone.png delete mode 100644 resources/ios/splash/Default-667h.png delete mode 100644 resources/ios/splash/Default-736h.png delete mode 100644 resources/ios/splash/Default-Landscape-1792h~iphone.png delete mode 100644 resources/ios/splash/Default-Landscape-2436h.png delete mode 100644 resources/ios/splash/Default-Landscape-2688h~iphone.png delete mode 100644 resources/ios/splash/Default-Landscape-736h.png delete mode 100644 resources/ios/splash/Default-Landscape@2x~ipad.png delete mode 100644 resources/ios/splash/Default-Landscape@~ipadpro.png delete mode 100644 resources/ios/splash/Default-Landscape~ipad.png delete mode 100644 resources/ios/splash/Default-Portrait@2x~ipad.png delete mode 100644 resources/ios/splash/Default-Portrait@~ipadpro.png delete mode 100644 resources/ios/splash/Default-Portrait~ipad.png delete mode 100644 resources/ios/splash/Default@2x~iphone.png delete mode 100644 resources/ios/splash/Default@2x~universal~anyany.png delete mode 100644 resources/ios/splash/Default~iphone.png delete mode 100644 resources/splash.png.md5 diff --git a/config.xml b/config.xml index cd9f0ab61..b3b791ea8 100644 --- a/config.xml +++ b/config.xml @@ -47,41 +47,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -90,62 +59,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - We need your location so you can attach it as part of your submissions. We need your location so you can attach it as part of your submissions. - - - - - - - - - - - - - - - - - - diff --git a/resources/android/icon-foreground.svg b/resources/android/icon-foreground.svg deleted file mode 100644 index add166f8b..000000000 --- a/resources/android/icon-foreground.svg +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - image/svg+xml - - MoodleApp_Icon_White_RGB - - - - - - - - MoodleApp_Icon_White_RGB - - - - - - - - diff --git a/resources/android/icon.png.md5 b/resources/android/icon.png.md5 deleted file mode 100644 index baafd389e..000000000 --- a/resources/android/icon.png.md5 +++ /dev/null @@ -1 +0,0 @@ -5e8ac0ef8768e0fad3284434d24064f8 \ No newline at end of file diff --git a/resources/android/icon/drawable-hdpi-icon.png b/resources/android/icon/drawable-hdpi-icon.png deleted file mode 100644 index e96fcfe457155ec9cb5876eda4ae2c119d6dfffc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2480 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 diff --git a/resources/android/icon/drawable-xhdpi-icon.png b/resources/android/icon/drawable-xhdpi-icon.png deleted file mode 100644 index a43251c56ebfee2d10407be4a8f0cd4637fb55fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3195 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 diff --git a/resources/android/icon/drawable-xxhdpi-icon.png b/resources/android/icon/drawable-xxhdpi-icon.png deleted file mode 100644 index 48ce4f3c994bd7f117b6052439623f36069fab53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4696 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 NdUp)9>NOm3{{s%&m}39{ diff --git a/resources/android/icon/drawable-xxxhdpi-icon.png b/resources/android/icon/drawable-xxxhdpi-icon.png deleted file mode 100644 index 53e0e9d67a8be831f7b46d0e28b3cd87b45009c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6272 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 OWIR=Qpg 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 WZO5e~V84IWF)K4WM78PP3I7MK@tLgv diff --git a/resources/android/icon/ldpi-foreground.png b/resources/android/icon/ldpi-foreground.png deleted file mode 100644 index d24c14f7d5323a4d3a2eaee8a9acfb456037cb55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1678 zcmV;9266d`P)NwfCThK zA#xE68buQlCDi!9CG4~XsfBlW1&MDa>Z1liBJo9^jHoe4jMNx0Mqn1`c6R6Uf4(_0 z{ko+fyiI%l$v@}2&CvOAzRS!uG>AkZkw_#Gi9{liNF)-8L?V$$Boc{4B9TZW5|Q%x zd=g#PO(NWgat1L=by6IswPHwS875c+s)?Z8>Dp5 z&T2QG-MyisK@HAsyk4?1K3w+5RwJzMk9vde&1sND&pGp$tZ zzUH)D1rTQ_<2dVT3~wAbwi@pUWH+u`p3CpSs&?2>>Zqg3fcFvFvz&=ZMy6&uBeueC(9VnaD54E7;(J>uHP)CGQ6FI||_|tCxp>7ZRK*AOTJlFsjJ5s$a4KI7Bv5TM+e8n_VN=81q?@ z!I;k14qB<1&KZuRruzP_g1hahBCU(=C}kWw%08Di7B?tRxzMe)u3oM#?{jLEek;7L zL1};lr$*UEU~l#z1CKZ=grljgvoI`|tcv=uoyzY-%Yc==(Vvn`jMqfO9{8ac?9$Hs z3@R^NR(NSiPOo!S$~XgHbSA{c(~0tPD{^1_b-?*2JYuVB(Yi+&7ZSiqzXnNb;2uDG z7I72e`6yFu25ncVj)-+Kn%2ITK8UN}2jktkZ{rgEAVZrMuYG&{GSySeg_LoC8FuFK zs!MMq?l636MVH${V}pL{t#}G+fG{#FWQgm>9c?_T4Q&^L0iB6801IQ7sLwYynKW%K zE8quWxB#LdRtKz2G!2LMIn{6X%ni@(o*#U-cY*qR*MhJowdHn6ermU^3JT za1+`ZY4bq2l_4EhgEWQp`Uv25I1&Nx;dL>Ss!T+AKgzS>OvIX|AtG)ih`0KzAQ-U1 z@URuAT z0wQPa+EhX0*aV-4i(IGIvv^(75K#{RG{kxrsH5%b-$V8`>c4W(&fegIF<=nHiyC4{ zLkw;QF}Zii?&ba|0kIjTFE1~0J!>rP8e*A_Cwkoim_dCU*=oGD#qYo^a0Jn_CxvL7 z2YXYWiFNPI7vML!oGp9xnP_3%8iQDlA$lf63lOclLNxw^rbZ?bFb4N2>b+cUnmCv1BEg=uekSjI)m8>+rkDbQXyB{wWOcad>5X*cOQQx4CGb^wR*t6NvW%(QGRV z#CzYN&0qDX?2kR@7JkqQzvosoRL|NHA92u^9B}~Zm*~?Ly@l8n`p^JyXK#B>^z6Od zKdN8%N_JJh?ReIjR6(3f#&q7Ujc7H2qI?0@ zT}C`L$vN>g_;)=H_eLht{V(F)Pji3TAv$r)z-@lXX+>=HJssP|rn{4TvhwwBBTh>> z8WW8#IcUrW%)enufc!uGcl-870PB{EyUm2D05F-N(XVeM zj^0>|`;$!MF{a}-vwwW%P8@6g+ai%jBoc{4B9TZW5{X12kw_#Gi9{liNF)-8M4~(C YKRE`@z@Xd^M*si-07*qoM6N<$f-ct_j{pDw diff --git a/resources/android/icon/mdpi-foreground.png b/resources/android/icon/mdpi-foreground.png deleted file mode 100644 index 41ba86c3988d2669d43bc7a3cf024eea9bf4c2fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2245 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 diff --git a/resources/android/icon/xhdpi-foreground.png b/resources/android/icon/xhdpi-foreground.png deleted file mode 100644 index dcb852e005838bb5205402d5ff398d0e41cda3c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4496 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 Y7oRv{EhOurT>b^o(|Y!_Rs$6Ef74%-r~m)} diff --git a/resources/android/icon/xxhdpi-foreground.png b/resources/android/icon/xxhdpi-foreground.png deleted file mode 100644 index fa39ca199fc9266f1f787a693d9410622e0c735d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7003 zcmdsc_cvT!*tQZSdWsUAM2H?q@Pr_U-jW!75G4#z#~57@B@qNcMDJ0?2u7JPL)7Rs z+8Bb!XfqQ=31WQmJl_xRPwyY_p0)Pb>s)(Z`@ZjM-|L*c_jzq*qRYy}%S1&*#j3BT z{e+5&TKjKdq(4U-Hg$W?tBbyR)?g|sw(h@$Izx($kBW+qRbTs|dC)uo$Nc^VAiQrU zpMm%B_{+i;dElLsh~bh7x93@|+@d;+?(Z$l!vvJ+qf_g6QfcdL@1UfawPQ=-+wKMx zKfd&fPRA)Z*wNpq`v&iMx7F*q!U+T3heJdYb;+~HZ)ejB#5^Dr>XDh9Pr~PhRv{}Y zP|q`ucG@96xPi5E-~P{BzEhluJwYnU$~?`QMI7pGCtlO@Wsr3+5kVy{N9*J0SSYf$ z_nAI#yYHDemTfN3W*zh!A+UbRs6_?NcR+(ODvW7OX-C*qSvyiwQ?-KC!%uw-wo;o+ z=IM495*Z&+fol_0R8?~=!eoC-|GE!3n?a|v5rcP;vUAB_4@5yZWoT2uC2?$I>cOXN z^;=#}?(Pz497!%`cTW}rDPmOo0GqX2gq7njct9A#_Wb-|o7Fro$ZgPb$vf)s8t6=n zAif)4Zf?zetnfn#&x3YucVNIqX@ zxD8Kaj`9a(_J~>MX3w5z4YRA_4rxtofcCZ-gwn=0+m4Y-gunCL=p>N{Aqr=#8xqoY`{#(anVa`;?B-K<$ zgZvbH2JM@>*XiGIIF~n^Aw|WnNO1C?ss*AH)ehZa1c|v0ebk!dpo=1`?alp^c-IpM zsQtd#FJtbIdUdb$dvt|Z_{QP-$pGcBl+zBdK61^&cM?c1U*cUiLzk~erSxL95I#P> zu#`?XaXlf`pT-JB7;`%Gc!Jhjf6_SwyvxK)Bm4b21}O1A8j}40Mb-2WLmnFC8jkI) zEiiB>S7{fkW=z+jiHXQ=Wbdb34_O?^+nR(it5+XLT2N1altgP?#GFRgwI;qOP?9BF zh9~kfH1myFqeJeUbx^UvRJJw8kezwn3XR-16_74Q1qhjP!DRdTd3Zn>?|^T$!7C({?Cv48FH z^>$;<<#Coyjv%MpscZ{v9- z|5W(C4fSkT?U+D}MHwe*<;O|PLDvzO`IL!=>LaShYnb-N?t%gcTXvd)+8d^+5V_!X zWcPhJU(N{6HE_`7|8}%V{>2AdJsuigPnu)ks^ZzlXFyRy!2)qYL+!wXcLm?IgQ_~W z`xp3hQemNLp!6Du_cC9bw_iMz_vIPm%UBaU>oFkJR`^@!9~!is$-L63$C&KvYJsxU z&b0mMnxc>n6twVmM!%4juxb;LboZY|%B zOnxbigd-%% zs)67C%s4tV8a}GU7oi`rsOs0+SZ0*MJr1j7t0Qbn%9(l9>W7&1zhgsS63c_ttjf zxYl(rvkZv8ez9jFxuBIm+GP!YbMkkRE7rsr=r;B{As|}^)JJ%6PZuJ zSFntF-|Je|n%c;&Ugs%MC|f{^eS|~ylFMzwc+x*Zo+Z4YqeOnCh^k-3o!uQ#B@b;> zcX;XdlzS-2ObEZ2tTL@aHJ!%P=xR!zP56HxrF)RpChW!GXgdsEpguD10uJRGidMx~ zERqSkf>{Gw4%fY6RNL+5cP1HJQY`ZFc;D|X9^{&rELXO!3sOQE%FALdP+ocDsI9_@ zZ3cpo3)PHUWYUGwM67-KKx}`XA61Rbh zC2iC4oz>MhsAaGI)v&Od(6Tod9RJ+9JI%Ql^UDPkxjAx4(ef3U@aKD~J!}QoRDstS z{kAk5Tycmc-5N+r$^RG_zi*dMSCl`q^?|AMy9>y&AABb9#XMQdw9B}O^J3G3%W;?8 zA(cO>o={t?K{)5&U%~0SK?;i=zhnKV1{6OTRQHp|7ric*DjCPR13RDCqipB1))1sj z(uNO9-|t)({P8_GuGiM`Wj~3Z?X>AA$11$n3p-91gOeeb>6t$r%qe<{Wr9t z;Su*d8XOlXLAWi)D2_jI)VCfgu_TvmP(a}@J3r7jLty+qpEY?rmJ;PoN zv#UF5y^om z>}w0f%ss!|KFvA~0;XMwMxCjWmt=SohMC(2D9vl0r40S z-lW!hp3}b*McSMx7go%9HYrt@FYA=Stc~EVIQa!R4ty|K^EUeUQ9j>iv$qvjGB)lz zQ=2D_rXD=F7$e3N;&m-BL&YmJ33zOojRpR!l%Hy9YvwuKx3y>t<55i3?8CmXe=393 z71uG<@2YD=d?#4V7sGWL@VMln(dCcR_`#^{6H^@u3_eZ%;=e2lj#Ph7}EU12@;n4 z6jUqUuzBCp6)AVkF4)MX%^=ynM-*@;Qp0^t!%lX&kaLB6`X%$NS_!V{dLY7pkd3(* zzG{;k+wbHjFUiKLtCYLM_kcnq+IWR70%M;P5ajoeUjZ;m+J@|x(H}c`6SD7#JG{Yd zdIzTO2>Kzze)YcE5eP1p&AWNAU^rh z6EfTwxs>Ln!06@MCli7S#hEP|R5G23BFj|N+}3LqcWSk>dqA=e%hGDX(3bN;rmv2i z+4m2nmeeJd&e(aa#GuKyCk<{_Y7kDn^bKwaaglirMzoZ)%k}P%D)qCmWJBu z@s#mULhvgAV^zjb+mOtzuoH9npFW1Q70H(KwMu#ExsTmLaX-aN1@OpWSK?;8#e_K; z6#Kigh5-i-hIVk8xR^qIza>?0;J|Ddq zg|_>(2`dj-m8w+uuJ<3!=ihJ-xT=JK6}(z#7+5T3x{vn>>ofml^mP@d$nHBcB6u32 z3o@)%NRrjzBW&wi&h?iYG=g)VVajJb1}Qox0thnqD+?G0DnPJ!M0Y5}%+)xuUh;5j zM6yY4OC|#P=*(U zX)Q3g*H9Z?-%^9h^=VK^v2rTCcK#NT`z8e_MJsPH?S#XDoIXoO15Q}orTRZu(lKsv zeF#De$ir6{f?)4q7hL#XK6zL!V!byXMe`J6G4s4g@>vCL*(KJe**u$Wt@#BY-<2{- z^v)^N8Fg42>2Ix8IPR^mrV{BQ#{;%jDAj;C!VYUyXRRG5bX4TjyW~*rwU56~9}d(P zUb~niSLxl5Tk?T^1<2JYfY>tqp28?|EkWEsIV@7K*8Fu1s@W%$5kU&~aMgN?@8Ftd4R1wdTTd)ywW<~}AShTu&!Eck$ZspjsJb8$)D{K z49Yg{mD2DqBWxP@6Zb5H{W}q88}r(w*bh@%-Mik6567;&e2Y2OH7rKS0R?e^J5}!F zV9#Ph`)O{phjV1W^l_AXR~;aEdYYZH_>K;JF<5bLMozT^esBN|-A5E;a-f}Bl!M~7 zj+J5~D`1POf)z@01}XbL#aIEw{AAnJ9EDicD}{HI#k1gZqV=Zzp#_cw-vUdSKbtHB z7=SaBGZ%~`F)4-?;LFv4?CYd$-a#Sfz9FGYHdUH$n=i8<7iOS0Yj=v|*t6U`f;@dQuoIq zE)X_e)ftEmuS8|_UpmcC@3F(md>WYosjkUme#qslW*)xLQf0}1_g!s7a$S+~X3U?{ z$;SsyRNs_4yC*OIuHUU?Trbav-&9UtR;Bu+y4QWuacb~Kptas6cy*VT)sR&ec0(Mt zfl;+Acvtm^f#Zfh<#Sa(1j? z+YsRUflxiz?b}fK=T{pULRm2MbFNh_=5vt51;E?&|x!|j?wZ*l_1{)reI zg6EH+hKywrco&?rCIJd6@jUe3Y!t4Y@H69*flBmu)QEl?iX=AFLTH-ikF?PN%ZX1xE}uOfVP3nAYWlBXrs4Habx} z$GB*t?Z&j^`!~K7^u;gQZ;hhx2Yj)4&tij;t2r7_r9;C>%nLN-*+yKHp8cK{j|Osr zke;T}R|$@EzFusZFD)f_nk8ap2h!UV=`-2AyG`TwUPC)^oSNaHDs*E}>wc=WrmyLA z^CkCMjs~Xgfbpo(5Y!jQg9hcFXsoFoo^HSmN0jVl85Nm^bXy#R5?UIVyDO!71ZrKPtOg`FPJJ^D+qzWZl`CjJ^9NS6 z(^h7#YDmXl5cM^?Kiq3uQ8y~YpP*&2Dl;Y2jrEk*##g_RPKU`$w#N ziZ1nL(ouTCG~oGpgy$qS#$X*iNaI%kyYl-(BYu8{QJW_9JUJ&XJ(uI~35asXUp~~^ zYJwv!C0r1VN{GFhpkyU%62c6tZGa=L{D=L!==o+ZY(Y?6X+1!&oeyw>V|=1mVwVB1 z=pyn-$)U2fIQm)@|nO7j@*A@U!=UZfoNeD2IvC8ed0X2&EHbEnJk zZ<8a@B0=_7TWi9VCiEa6q1qCD^IrmUu|WXmN^iL=Sr;fgvbQLCZiI0tSn(fhp029J zL1Zzl6jy@Kf8H?nKH>&WwRs%G@2eK)85&u(WpC^c{YzjDJbB#AGF#nk-;s+_NVjQpZ*J?6}v6j-F9J_(6poz zt0#Op!OAQ^t(cdW*B|;rDyU@iKjoJ549&eEd;(Dx6$KIZ&$T@7_aW-jmCrzcvVuaI zYaPd5x76J&gU`1EAPFRs9}Wrmmr8Suf%$KK{P!SyZj|b8a4*ljrT$BzI-lMP8t3C( z5dGip@`+JF2R{OjVwhsW%YLNXO>7cJw%VTQ!JE~`<`}yVH{90UTmyzUj|7a8Q=SVY z?1mcCK0Z(vB#bQ?*D0kt3$orEd}fxuw4)rw$bTeMc|sfRy0_Sq8kcAxYu$+a^F+BNbpnXcBmL5L}r|%pg=epEu|~5S*jr{ds2ZUWCox_Ztkgzj@*?H9D};vg*tp zbK-Jh4GKP~F^U$e4z69N?rh)rMr62S(xSs9g9AGA?OD|XnE16 z7)exs7#p&py+^F|i;HvY(u6CLKGkY%$ zqn_@4699m!^51rW_IFRWk(9{q7oC@`r7r-$^!49Hl_JW-1pr(J=-pR04a9EEGQ4*H zg%Nf)y3VWLw)rPXN(NFC5^K*(4j*`x_u>`{OL8Vlr`ym1g!aeF^X!6qACMb4X==1m zRY-cecnL@0Z!gfS?ez8FED|Mme|{X}794B8rU-%T zlgnx*?}8w+himKmnUs5^&1`+D-|PGT&;KI^BFW{}_0l!oKfbv{czH>=lF8(fsHmvo zp73P%Oh-hy77^@@E1Unp%K&I?#BXf8e5QR!Bx;i;GOX1srD__yMo6}6tHi^@-9>5u z(_kzk*T+bc+1c4)n5+&B8_j##6jMvXxV`GQxH#D%qxS^M8@SQWkXxj*9%4sT(@4w* zGZ+BC{RZ*T8l8TUiPDHiX{22XJ7}HNCg7`P#*qq>zZ@cVrhw>TMDw7qxAFgm#*#~BUO+J zDuFFmC|VC=fW6^Ek*S&$!rjVRzWb?=BvE$YhF$g^trA}&SCOC1*pv?DSG0j50g*Sp zHo);FMcMut3|tXAU&~%@*p0te*6t7!-}0MoxsUaS2I!MYQGC7RWMuH(IemgJl|YiP zfoOO56_YC4F+q|5jMHcCX~kX+CVu`O05{b^=3!jSnc|#lmK!gJ#?uNW6?9P)<|TVYS`p z($dTd2asu7Es5qmu7X~;C3C2yWubxHF(fW@YX!OF`-vHH;T(YdcDcquXbM-#>TAHO zQbbNp&Rq;{`3r3C(0AF}+<-Jc(kuikn%|Pwkp-=9RKM|2XA4$mYkpxyY_W}Krb)}; z3qhOH)YgU3dH`DgfiK2zm?5J_^!p&@E3ePb5JHxlf2_DUcN2Z4=Ol0h-M;$LUdEgq zkKU@B013}y-=^|uYh$OGqx#om* z89(wM2sKPx1Uy>xyM-~c+_nfPfR;R`z-%(dh_XtSQ_M6mV|f z60aNJ;*>kEMNFZ3-JrEoKy7D!|yafW=CL^d|KZS;Jsk$!a?!8pW(P z8pYUID$({4gDhn#MQC0tHm#a$l9fuiN{5<%PZ~@k zsS0ih%kQ*v`FU4Lv{mM0P);`C=E$vgN5}LCloiAdT8vTW0z@ia5D&2FLk_#%Q!6-B zs%nDNss=!!*{uXJ+df(pu}$#9uUUCPYkmoBhmms6aR{7Ko)Q0v7GEN z&=XpbLNtb|mXxAij)NxbZEiN^L1H~@G&7kt-qs_xo@g@yia#xw1bet4B{b@1g<%L3 zFM9-&KPVVlPY@#9%Te*}`>+y*< zGZivuRj_PurQMAS#{`}0E1m3|IYWb&FzMf zN)XugP-2X+$r6hIJ`w9(*t5lCKA+?g4k|wisyWH!N#Ov9sd<4w*5X`p?mI2bMp!1O z>b~GNc!I11QKCJXaqPuU6I2xE!``#?lc2T6n6n0m^@oc9I)v2)6QLnkIeo26LD&G# zSD0FCgtvFy2h0U#xl0u><}QnHXHQSU7v#ns&{e9J1#tO^=Da8-GzH@}v z{{~%?FZi_?jOW%@efEilds78Ad8Axc$_K!8y5QMV+BDh^Jg*SZc=R%n&1dK=f6{Qx zDbTaq6|c7Fh_mf=t{SGZ~C1pgO~Y%tE?;jW>^^=efdRx zfBub&{POxC>0ut_+1c5qwtz=&<>lqWhv4lzFvPousvg2Ta*nR_T!kT_PrLXYuu?yGdz3E@X=P2tj zYFttadzi|Nq%;yS5v`>v8E{x-`fF13IGXAa-zopB2mGmO-EuSd^VV)$TL{E?A(`k;K9y+xwbXmztCi6Z*PQTTRmlyea&N|LIlA0DJ&oeKxq4__wVK}W zgy(77_^|I)u#A3M!^bCe4=^adQB$)Pq1n&2$vdtSgu(SAhi7J_yTeB-pV&VaF4vEJ zwFnXE&*|r5jl|;D*GtMgHsNe1ZjaVWzeSWMXr7#tvGxLeSMdHUA8{+pu`p=5rH!Nv zwtn%wOX}p*La|21*R}LR7${T;S-MpDu2pYi{_Q>UE3Y_T8t;((xm_;jVRWL$a=t^) zrU3o98w;fkt^OsnX|~?eFWNh$Ng*oM{bl^NRs4sxBMc2&)rt3J6ck-9EC*R2y%?7*UJKDDNgBgD`ZsT=Fs^#s<-{*+s7zUY~=mJ#0f zM8kT*VxVfES~HObnwv}@aUGxG3&PZ}O3Qd>J+SQE)bP%%whZVbeYq9_J>vovQN_Lu z9s{|Yu2U&k2QM7Nc9>V3ggldA7e3lTZipx^(K_`zr+o}dolhgTo<*~S{Vd7}-r%=o zO`R7}e-kg7-m_c#9?zb2_`#iIeECt>Wobf+eJ_$iBgTo8*?6> z%pI_a+Hd9V-)E7b5I%gfIq@hFn16l@b!ttXX71gek=P=S$mxOl}5|s89Bv?Pb!(Tj}&o;A}UC3I#&x zhnvr5x+nN3d0d03H-4w>44pX$p+9yXE8Gg{J&`$d)`@bCD&`kXqQsm>n0l;>E<5`V z21|b0`tBX@l>6(j-8*-#h%5lp9HiJ!@dj9}$|vj{DnKu!odF5O{Q7`wKZbOVe1BaW ztu!z;NGW^WWJb^7uS8epWVpsT`#yoiw9jHDbZeOWMz0!r$7jcI&3n=$;N*fP- z%{P6Q`#6#CFwN0cLlBESTby*I zk7wK{hlNDbu}&AZ^u)j!^y@Z00Mih}C3*8?(kEMT>yoF!>78g9*JhM{8#r(O@Fb*e z9p;wy9AhN{+)M9ub6SYz-E1OL(Y+dUD|XR!8Gp)_Y^GhHU@;;S^>}*XvzGcTDmGPH z)cB)hwFHsc>tdEMg6N|jGDWOnf2KF2F}S9AHFYQ1P~!dZCz|5A6K6Qb$qj}TqTA;% zEevYYPSH(4navzFm{8Bc#l1FobkHR#J?}G|!G8CRd_7CD+KUd6ONzNa9I@fp^L;Lpp?N*>j(n@~cgh z9`}sv=MwLC@kN9R)VV`hDOO0-%o$3)5wlj_rWIiS&ulz-C7gT;JYjGPiEB@?MmaeL zj*iUdmLMB_!9Hs9$C0f9lEi$F;gI#@prr zMhmHGYn}5>3k)98b%?_XW6J7sgLQGV7cQ;6jC}m%_w3U%ZuQkZ3qv zqC=9Oxfh1q4(3z*_33j;L1UL~_tt(Rec3eVN&W58+j+y9Wj#2)_t8I9=7Nw=yo6W~ zBu)!Wn3b4z-xJ`9w#)?@EVno&vn1G`zEiD(0>H`T>uWh4vM1lQD z^;&G?XqP))tr_5xubyX<;s;C$SKF+5XmUaRobN{EGQ6=GzQKvxy*H#AKkw0FNVM(M za>N+bmIjp>rPK*zM^%7?o0aARriu9!auPOtn2%)`&?bxN)I5W{fuf)EXpj<;f3yux z#3-^pF@2);!_2m7TsUu!{bum+=6=;I3^>Zy*E~SG%U4CIbmx0RbewK^h}Ep3@IY1H zkc%8hsPGCDWW-0Y;C)1x1^lY31#cNo&*BQ4Cl((J)W9oV3`o)jZb_x3j|*7Lpzk&( z>USVq^R%Zvz|26FiO-Zd%PuP`zBSBsft0X6*)2N;aH8qKu6;RTxJvtIi52g7nj!C# z!|mrvK(d>yr>zL zQ&a}7^1B&3x$#@_Y-c#;Wrs!|>_{onT;yHsrkwJD@6%Dau`|_zjo^Y9i)y^l`JwAG zHMWYFdhz&=u=p6P_y{jNsXBdC)F8MH-a7Lr^hg%mKjQfvWQf49d*Vtt9^fa4X;Z!u zDtjW83XQQ2xN#+xocesp(_J90V|~}JE@XS>V?9H@43yGncc)IP_6QS!PhrTBmt1A$ zb6Jq+WM_CYh(DIVc_Ots;b+IIIyfFB|NHym*z+~pjn>y;d)?Ra6=YmKP1Z8EL^xVt zvzP+5=Ha?Z-B&>V)2%3`%{MF<0s6`Z4UU9F;##Ohx~gy9ZBc2-*6kFsSO9LaJ4POr(RY-?o=+|^Zdck9*PqN}U$u6Dyx2Xk%1rO!by2|b zC@3hbrB+5*FjeN(kS9isl*CI|U{$a<#($tYZ(qnP7LeS6Y1<#R;7!}zY&67fZ6{1z zXUO^Pj59jGT&B8XM>8=#zCvsfYJ(%T(1O1>ts`p;GF>+TnLIX%Ei0H`|ZDU92Qy7$@~t z4v#o(z!xfxxzexNiWW`wum6)#)pDEuHdo5k@UmRh;JjgKcL#_2I?QJlSUC`E&V)Gld{ zjAf{7Yg6YLIrF7UEQ`@Ic=r1|Z&xwG0xQF}E-m;>29+n5x{)76{Bq28eCigO@52*o zUhvYpI%Ij~W$!gePG|WN_tyktCqHBTY{vV%kJI;rn<8Zvie~YWogfPqko_Ju<2V7x zDcU+?BBIlCCNqN6Z=l|19~+z83G)TE7FM~S^eZV9BATMDg)?XNej=u}u-f^%(` zw(R)i|CsnG(qlHcBEsR06)AT;I5jDNp-IbbAwSw!hhGlXr{`}m+%BmM@j$dcd)NTz zOM-vid%AVHc#NAsrE&g)jRoxYN&GG=hi~L}F-_JO^Dk)6yt*p4%D`!Y zUutfBp^BJ?QQE9ahvG%a@;Ve&BK5 zM80=Kcc>e;3sEH|T|{D$rCNW;rt3M%#YhTOviA1M5Ufn9#PmfjM=)=}fCQ}(2eDgS zwbWXAy=$fUcD<)m8cg+POnB1X6zg(Ww)mF+bS}#GkpMot%+F8|%V<^7K0>GwDRX=o zBN-K2*2;df^}y-Vas;ROeUU{JUEd*oqsHm?2)SGGO(`SJ+f4er02Qw&?!|O z6k}<%-O^N7pfaY`-?iH96yqpOko4k^i_o&2bP$}q^R|HDl1m*RIeL2_W<%q^>D;vh zYIh>m4jz(&a2?-xhHl16)Dx8~Nl>0#w)5keBu_Z2JbG5}L!?NGZOl^GS zT*mp=stgSs&3i*!5M`lRY1fBHLh|AUhHLc&?n9qt+T7}b<|$_Np1F*Lw*;rNKU7C? zpQQKsrzsP9kX+uLsmGV1v^O-y9F4;TfU_;Simhb~!!%PEaRB|HirUkO_RN%ps+2O% zaRcfZ5~-CYyL@q?)=4R_S)6lo!SFuDi{C8hOruVgzQS{*ODXXSy=y#X=V&sWIF_@? zkSjkTwJ%cXL{~Kts7hAMz8x-t{Cb&b`_|W&-U`5$)rL#^emAHYjic&48U-2@3Q%sz z+Zv`F(YyOS#F@ADD!@X7yjwsPCb6`+fe!XY5AHR~pZm1vXu6h(`D^s!aM_FrdiQvq zHC2~YM|y^X@-*yMqrnj*>HPg?+O6RXRS0 zVbnK>23&JO%P_`%wiorSxOE9|jd#NFVYmp)cZ6+foh#O)$e&qz5MAiJ6X8cpdLBkT zN5d0*&q4GGNt9jait9?LUQ7*UD8_8MTtb|LDPP(+xHrl^DT~M@oQuHPv*|0Q%wHMo z69OIpH)kH$tLyMMJu?wTHcM1aUIiKnii6C%>?uY?wdYH^=BIP87>K4A)BWRVv=Hx% zcLBaZhcG(%MQL>IPKx8re}<%}{J&juzMr6{kGZ!Fa3gRVK@L;l!}}2L@Kv0I3ff%q zL>#%nD~7j@Qgn-n{V?z(zg#=Y3|Wfm^}h{oi%GS~b;>W;x&#IsI1sAG1Y9y6Dz4u& zA0O~5d5tbOrI7oGs5;Txykl>6v|3~!ao#V^5HYU4;g7-GHej0*wYZY+(4(A880GaS;SJz2Or?AQuZalaDvM%I3 z;2h^iYB1U(8%Js8exd3LTrrFIIB%8FOGowHf6N zCzC}xa1=D_k$ajSX@77@D6Tz^JLMjGSe(6sQBhAVp&%Cn5 zTl2OX>wNS&+Oe7#CPPGp(6a9@9cY9^`6OeYaV~k&`EhN7-)MKYu3s*b_T4qodzR|x zzy$ax#6d>u%91*dUbzFeVKDerTt9F=@$AQr>dN7(nxef=`?wmp8b?dlRau@Ckp~(G zPgnQCy$9}Y+pH?vYJ-2N*c)wE{P{yPa;R*SbQ;lh#Pq9<-)wB)7 zdU2a5Lbny^WVd4d45N)i6&UL;(X~w`9;D2pzEt@2WCpjRo10gMYgEon>T4bO2T|}h z-z4VT*!kpYpeoOZ{E?)3Mibp9U!plwy{&A4i?5=DD$_i^Q+Dsm;)-HXzL~~eebRBh z;_Z8sNnOLlf=?UOBiR{ryzv8=&J^dn`A2S1+2L^rxxQ&QHz2aJ%$5CBMbDYDHI4tk z-PN0;F$%o!+p^%v0ZP2is{#fOV;$IKm*KDIhV1^rj<6r=m11leu~tC_iZe=ukEIJb ziYh#qBW^AdyH`ZpffRSgU!DXdfkx6u9du!Kf9`QRa1JdUsw>h!fPDEUbVE|9S4p0x z)8$?ZKGjxAr&S&!q2W33tvGYXD>bvn(fl*f1NzYLRjsV0S7>K!AO~xvhcL2LKltsJ z(77Vq>Rc8dp}2=2kFJ@8-)NwGp5cby(B2oDXx>8^CwbglV%x4!-fKx*1OV=+Mb^7j zZYPs5)&+~q8pTkKCxRc=pY)zT!o6baER7y2OL_T8ExFK_{-p1%OHJXT*%Y@q%(xpQ z%cxwwT-fz#L9~mbq44N*X@jU{+u^th7ayj&<{t$YK>b7*$QEgClrO!NntlS@UqA0$ zbZh!6W>B{}e_uU0f@deoA??$o7d%8n)dt59 zQdA{mnkw@aMp!=Mcs!|y`UFVcG9+?Z1;D^&O`{s9pofeI zNkV|zY~ea$-eJQsTf$}mnrsWZXqr-VA?mOOyRx7`II)DW9-W~@kGzJ-4 zrr9kpq+Mok`)&R=f@uTSXtm%OG!ry?&m;cNBpxk38mIE znfq7yY ze2|Qxwf#{I?|?3b0}^F<1oFTOE8>p>e$b1>1F9F7cZ<8kcir^Ro6WB9t#kdcDXTIt z$uzR9_AE60Gj*BIy|qDWS?RZ}BAvsgR@cmf3JK`->~~C+U`XW3n#Or{Nk*Xx(oO~H zq$(kh;Kye159EbSq=04A^c5qd5-b^^-LCYwr)kyQ3x&$v#&O>q&;ALV3K5xw%5rMh zl5-#{!YSLca<9kRX{Ma0FIu4dJ~U=(X|!)3tfHXFL%|Q8^)qg|EC4cVo)AE0*KSJ3 zq$;i6#HFoshsl}S3g@eHd#H5?AaSTra!(CKg_LIC5FNqa3gBkvYFu<$P%y?Cc|O6Z zjF^EV$4`}~G-y9?4J`}+S1vPDw!#EjpA{9dmbLz*uiW|ONZ05L$tjR#UT&#lsH2kt zNMS?^((-+ohJ>< zWW7*T``K7dJ1q?RCf7-g@1Tl22rpc4;m-)KIx3=;WUId7W#d}aWdAIXi!9_c32>wJ z!tZIzii&gwqw9@dFk6imh+ayA-F#x~QGts5*Ghd+Eo?}DAb_%t44b9-@cO!m8TlV2k2q4r!9O1gz@uo)9It#7N9=X~-fWW@lz%gNqZKe_!1mK= zY3;onY}|ZBQEK{34d})42QSaVFCf5NL$6lHVC9gNq5PeE_SoZ*#43^3e`7gplW_8% zd^YQ-xz1oiLqwsT7XKv@@+JQOnXqH!X;}G=v1opJa`H%@p)TWlobF$$I!f9_5Ypgr z5RuwF4Q0;y7Y(`QXCm>zfkY2gtzi+hirh-|r>4^W?E%;r7#eyLp)yqjqfLY|RMJ6( z{$-qsHcz4+-{wG)!|?VqmJI5FU2XqU5)zX(|2ps)%GNRv+GhYZ`U~5@c-zzIM9Ezt zY?`|4zZl?p6~N4=R>F*5vQR7js{i37s9ILIC%q$nh?(*ji25UM1G06Z!j_PvJtHSA z{gG{|qCmWW`cGQHzbi3MtiRScg^B!0!AEF6E8&RyA2;VK_$MYOyJGtPh-d64)Zp7=5hkUv0!*iu7lu|8Rg-_#FMml1IJ7 zebq|8iIWW8slO>NWefU%^A8BnAweLJ-%!6R%tDz;PFb0IE9up%zfuDJ_Fw;3pWk() z_JKuncvSf6{+MgU=1AH+6xzDn`&B2WXm_h#glV9t@5de zdK`AFzbiT|)Q&5G`DX|k?MCB|;C@7b)CL$}ic-ZnJPD~=lgq9CZ)x;>KeAaA!s3-z zi$2dv9);CU5T>zd%QE2>wW}79vT2^BvX|3nN(3g z{2o5oFut102{TZ6NJG0Iz&G`6DLN>yV`Qy0rw^qAR&h4zORZiVf=Oi7Zd}(@XiW_v z)DQ{vdvh|ozMWL;pWB%$%8o;F-W(^L@iR?svvH-x%K=3N))1^nCVeapsAKtM#|=ihGvY445- z2>dQ^`^Hs^;GxBly>E{{j$B#&L+tnA)YDJ1e&6%#)aglqM>bw}SCdS?^8AB9)~En- zw58dJq*l$O{SqdXuQ!PeqI;f6@0@&feaSoa{z1=cPqVSusu^r~zO(OlvdUgs;@I*h z=i_J997f0`raV>wy*#v3Pylbfju#OS*m*?YY5fj?{ni2kdlUo&B6kV=ju-grbccw* zANPOz>-4{4^z)v7`J`Wr{$uq2bGZN7=s#Tihfn`AMgspB{U471;?pm~{c7|}M1WiW zwb3sT0dD;#Px|i~{hYL49RJ0qJqk}*_s+N$eTgr*77C<}MggeBSaw^^u)N>RZ5g zlOYwU@+YdUO&>jen72>H8!BSI_TRx4Y&YIBqc)q_@jrS*abb?yY9hEVg}Wkmt$Y^8 zNz@&Sw^4Lk1Q{=s_w}g1@2hdsnFxv#gpKQWe_79ZZoCU-(z>I4&k-PKk!SG03;=oi zpNE~mz z>*d3~?W);j0}tW~%15<~v1@WovEpMPGa2P0fm9M=o7oRVz_;(x4S&V}Ok{}UYw=6$ zmGoA>NJu&c(;|grD`qmoa#vMdzQ6B!C#CK_@a^@fppKVEFP-G|uj%!Al?}OJfp=w9 z&SbWO?mFxRLf6ouQJ`gXZZSV>xt8@2gXC_r>d+7iTMIkS%BeD{C)LIxK0<&{fdjWr4!*rLr3+}}AnCt{UASMK5mGjrZ54t}cw}htKWiYL$1~)I5j#!3F zkJ1-nvC5tK#M=9xOlB!3Dm`r##d7IcKnk z1j!+JBXHB?$O7dILKl7lH3Kq{B`Q^JHcpn^OSCgJT+&ev`H|mN!h+1y)v(p3Cp4DN z79B#lQE((q2Ig;3SNk(Ge0`j3nEx<5p<%kj{` zp+-{;SgcoV_oeLa#SURt%hnd(d=W?ECF1WR5dQ(O?q{M|$wV_hw2KAFr7z#iZ`oyy z-aW9M6{R7MX0NmJTTwQwena_vS1pr+%9TcEVa!CTX##0TTkBEv%8MgjrOqCh2}(k) zyBT=SZj}%V$wZVwY~}Y$ppd<8KIS3QMXm=?rW{ZIfmbd)d6?(YF*)l=-OFVcK&&Zt zqF~}?p4FJ`_s<_Dc_O$j4W*ImeoxM7$lL=@jA5FB_K+0ey>^s6+NT|Qyn6U|5WxfA z8L9lt;qdT)(Ik1|Uzviqp96&k)1p7!%Uh~pc7@n3miC%7S>+!{RV*JK$DcxWh`n~Q z&*O6AR&(k^_Z~LKII9N6yEJM6^|R?im6~18vRrl!;YnYQoSUQC@t{0U2`IRX%UDs-6WaFX*2BTSGLpTxppx3-Edvs>QRF>aJ;c5`>O3 zY|WTSPT={f24<|dDAqQOrdN1Ut`8=9x^&Q;oO54mcvMeTHDSH#QhD6X{nj!QAwHUw z%ZT3hFPmB7rk58|)k?}S&@v6Jln7evoL-K6HrDv4HFyzvAz{>ls?v4z&-y>b{cIJj z@jv?RnT`bXJLoY}N$z#L4d9zgM{ww&eKj`MgRiRgOw)LEe*o4~?4rV9;r7sa$!6tV~UaONDBG z)hJ|Unj3q>b`q#bGqT7y@1agMa z&yr9h!!BheQ>kI?EsICmT;0cPn`%oUkJME~0#TR>>YI@#>Al$wgtNt(V#G(BzASEf41+^zqvxD1>wZB(tGhmjS60oum!0a}Ce$A9cg58d z_I%f*i=6O>EO-+uq<6f!yjr?=b3{Mz09?Z;d?v|1e` z)!lFlt||KO`sKaLh|t zjnvPOzG4U?#qZ_ANFaIVeut#pbw6#(JKB92`AJ79IkQB zT*ZWb)sVHT`^=~crOmmtK?e798V=2V2{6L+-&#^~!7a$qcDmSF6^MfHYTE4-iXJW* zQD@<^A$}@+qW=?r&+=J3gLLW51Y?e$w%cdb(^Z({F>HI{jzK{heEL4wTkH~ukYDFa zkypzLn?4!83qT<+BiGyHi{6Dyr^XAyHWmh}7mAIftlPDrO(xpN;fR56AGBXu=NDGZ zzTKt`z4w8|n7yDxh{irjYZQJ+`J@xTIv9_V>7Fp;WG}x-vvLgS1d0N@xeyw{KyLA@)#oyKcB+Nv zt6$c#ul5)}J5Z7Np-I2!h!WG3`FJbMXqh?=4zr3pocSoc)$5vr@zDDfwOo%BF!mEQ znKY_Rd~hwC+_3tUFCoL^taXacypEHS4;RRSPR-RR*$n__M_dOFpseU#6YYYM9QtlZ zRaas4l9vDM_az~Swch}~Q?L4~mHxh}hkVm=P>rVsJ^%c^`=z*J#)HM-lYe7;pc+gF zJ(CEZ^C_JjK+A?2ur8o0gBJHwS66F;oBI|ze$?yJE*E-Tq35NihSAn~~#l2FF{q_Q(aw&rr>Od|V*&z#^Bkga{* zd{UnLachnMbwo0Dekraj5zI^mcTaXEQAs!=52E;*X_aEp<1eOS{Hz4MKKcgl3`sz4 z*$2?5ajd-nz`K6XIu9KYYIc8WzGj;{52bpPf4Cmwf6O|Ab?$g684^`K7UAALASupy zu*r55k=t0VDzt?tqc@`3?gc@{-i)n@R7 z=F2pTCwd2S)7^$|W5QymE1tMbJ*Q%obsXSxl^1u->ZUx?Ol`&`iDrtPs}lIATII}n z2bUCrY||=QJjDk4hAeajD2KrOVD>k5Gv+6-g0BwJjY=+%bYBgJm~bY&Vok|vE*bt9 z3}o@ju{3{ARngr2pqo+QoNwPNB31(oEF_798-G568s$t*OEgVdySk_ok9vOHA%8v= zH5RN^T?#AUDl1k?6@~ZdSuss_O-tD4C@bF90^ix6=@!mgzAjWwfqf4r*=xEEUb+cD zZy{-GfM3jC#%G=54wY{VJxFf=O8S7$jkn%TlYjG`3njknh)4_~|7eIR2S@>c6t}i! z^y-$0VNFfMReIK`Akl{x<4vB4-inhWu9X{!-uFLrhw($rDfrX5w~be8gM9l#2CwQG z)@83J$xe$HBwlk^f37@Gq|Wb6Y?2*hp;F6Z=08g5(7yi(v&^i(OuQe}6b)UyWuBa{ zIyI4RW)XyGh4*48@gmnxFMr!B4Vea4R-DfA_5Wh>m82qForb?U^*TM-C8eUwB5CMY z^PsrFy>iisKSZTqKva~Xm90$AA1Aj99T1l>Pme$ODM;hPD;pcb(O`FOAvr8(u-%<^ zqX3_AZYO{k6YE1)ze-B)gm~n*txrPXn^ZK_x8=a8@?)2MzrT8ICw{E5^ZNm+n9S=4 z<2q0&Zv~)8q3jjf7^f>J*EoISN0c}Pnc!2Imaz2FK~6gIoR(erlPkM6DCzCU>)Fzz z-PgwTkQd^Wj^^(bTF+eNtM^Ad?CNm2wz^{J=qt%9hWK)1mfTn`J_Qcf71e67p3eqF z6_YeKiV(N&9sR;J+i-8{#p?KkVQ5%QJBYLyvkb_WJ zR^;Igr?jUx<%D{jgGUjM69y~~Pay3ok+*Evb$cL25L=|Firzl{{f6V ze-b}kS33Knvt5GXiLQy*Y?zNe!^`#Hxxwl-Zu6)u>u!28n*>_w8b0l`k!Z|gAvQaU z_X74F;krgg2^Hd?f*gt9u&e&xek?##jMs}MI87Q%a+3lrAn#O>hYMjc)2ONoxe)!v zbTfi?BFXmlS}Q2O%Eioo(&WSl-Ai@z-9(37wF=QZKFK>J{nAad9t)`w$keJGb245G z^x6Szsd}Zah_L|AD9UMXexbZ=S#bmB{nGp94tb&r|Kp0WczHTb2X0m7SjrxL+?|Nt z(uJW{BA*5kPYt5)GJcSEe+Ftr>>2z|?%Z*yMb#vp4)epbqLF8D)h^e18}Vy)svn@| z9nNmZ6GW|5^PT5S#+S8sJ>2)gPShHLQ?L$mXBseUMvK>#CF=2Ev|E(S0c8lz( zFtDzlRQJx(ZOP%N7O7J&}UXOOZ#*EJ_of)s~&shCn!!npir|bO?-UU&+aI=n| z$4&X$6lvv)u3L4EHY0;sZ%OMFSofOlRUs~v?-1E}Bz%S8lbfpI{F5bn)vW6CuHwE% z5^nR_qZpX&sm_dtC)Ne$rzb@8@x@WxXOU!0mAF{D#uCH058IZLoNjJKQH-%}NZ5u? zNp9omw9%e|hu&cKWau?jV(`Giv!Yncc5MnO%}Ra=@3?B*66l2)ER2||{OB>kt=7_B zwF1M?3TlPtbT*HSzRm;S zCz8y$`VHk%GJ}p}S8*!F7iJ}=uOrH4Z#-(~B`(x|oOMkg75YIB<>;CL{LO$j zblP;}D5Mp;^l~}YwdzIw(#i?ibBCZ?4f35VXMWolXwlORw^c7(Vtz*4(Gp-dk|l4; z)D_2iW*z@9D#evN1HNZLaolw=%|}h58ai{?N!!2ekl)4|8HfBs0|$b1=^Z= zw!KS@zb!-o@PSI6$MU!=wLQpdVS8>mF-+;O^-tJxz&chY&|1pc!^4BWKQbV=seb5U ze3bY}yrW%LJr^AlNig1nJ0^q}5X1&nZNNov-j#N~%+>s8FM)hhf{EtP<+^$uvgHSGqG?^O}v4_q_BVqvr%2L4tUAbgqjgd8H zy-k}<;fNP2O^2+5pm(pdT!rz?jm9Qvuxjl_v+Cn?AyH-DF?DPeMp)UGG=m9U@*06< zAord}^2`I5)3}nA1})*5?rTUD!<#`TI+T483(cN&J*?@ItQJp&!|<$-UCNo_%I=rr=%UTye5rR(Dq=13)T#Vx+vfIK_^sEsI}r(@k0;_3Z-Q+ohFs zFw?I~Gi;I2Z=iz@Bv~ndSg1z3smUP82yT%BsGrG89q z0QEGeFVScHt8-PiHF<4Jgw#7#-sU=&Zt88R*fRA{IJdnmXpX&&vKi4c%B-a7>c{MDj7q^3M2zI(5YQj`vUEb?ub3-%OW`nwv#K?H)a?NEFX4 zJYajZDsmUgVd);wl%cKW-=;m!J}rWbEdnOefxpocqE7I%hld1iO9Pt(Nwrmx>+_HN zi`akiV4Hc~n8D7>S-v`15=9#}8Mj~;6;_72J&7dkR3P;I9XW>VaptI=k# zWFM^k^)PXesVH}36m(uMB((i`G(tUqe+cVzlCn{8Fxhul7S)?$`yxNbJfJ(v+lX<~ zi=*eZ-+JYQFF*@WjPy157eVahO8c>HlKRjo(2xP-nk8(%)U%F_@?y3Mn<6BD-fKnQ+mQE)?y z2-ryyIX{216Fx4D{6vwh^!wxxZ;{IK_aFGiRWSp)v}#GI2*+>*Xt*-{PwDBGP;ECG z?Mmhr(%uF705e#djIPwv3Xc1jW7?q4EQt`5M<5ia_BmyyCfk8dM{}yrjLZ(K%O^Yn z$>9PsA7f(_V?LK6?Le};oSv(?Qt)9f0BApN+>B_55RDmZOw#jrStp0Y$FQ{WH5B`1 z-&4o=WwahFdD$1X|6{^Ah5l*V~moUKpMIXgO{aanC3R8Gklmct2rHQC72E3O3Ab zHEyxOFb+>(~RijYr`rktop;UH&cg_Z5x}c>99S06Vh?WA!?}C6=DH89(mH z1{zDDKx=q^i^Qh0IAQJJhG`MNWsebouJew0-95MsHxIwwmK#o<`H|7A-CYs#_K(#9 z<{6)%7tr`H|1U_hd3~oCk~clyCA4FE@O+IaWJZVBSJG+F)x{w-cBc*Lr#E`H15IOB zDk@>qkn?OLt0^|Na$iq;?q2iK?yba?Pj*&NgwH2h>X1HS*acHyGn_pYG}*O^N=n?^ zwhq~%v|aE2(tjr|f^SNjnQM2oxBAJdj}5HVvhTr;hFl1b5p2Y!SD1ybH;}ES`$oTX zrBtjGw4LflnerTGzwMou%+!&Q@vYQtMf9&6-UIA$$?M`7w}lMj+FBwAs#+uCyT7VD zXOWtNDZ+AZdj^DKIqM=Vue3y5Es7?Qekn5NTQ#)!sM%K^Xdi^7<;Prld!!fpfzNyW z5vCuf6AtIa6Sb6qR$cJB-QqpTXNEpnVx~twSfp8rjP-*f2l{HOzvJ%SpCVm+(FU|G z)q<57!gtW-^UYKDh!UoH=ZL=7wps++^7y~o`=B8AjaC(dY=vSZFLO%TePF-;aX+%& zcB!5o-c_UnDujE!)6T%y%r%v5EI%NWZRbRVHe2xvx0xNvIiX7*K6)f61XY!E7jnSx1%p9@H0 zq?&RXBX#I@D&;pL#UynFHJ}Q+%$>x0YJOI&GOc11*U8FW)Xnm;$k+^)j0|9uH<8sn zmV=*_iDrFU4bVs5R3L_y{z5lB%mrDKKBV8#|e)U zpw6A6tAu;=TbCxQbL^4M#}CGf`-PG(V+nl5S5I3G2C|pL$&V^|{(}sBSnS!|6s%v? zUgHmkZ6P8}nnp?wH?Jd0LCbRC?0w)s=KzS=q1#7)!J+(5gM7PKQN$HLZ-Yx za`P@)Iady+?ir!Fl7~V*+ptndqjG5#P97KuDR=*oi?2hgh6VyK6M@*R#TP@UFfQ??4L*$0H7WK^B4QnlQ69T$4o%L zwjK#yT43VZ)8J6QtvXDyZEgZmdHd$nhhv2J4#fG)(SxR-!xZ}`l{IIGlPRd!!t>h? zzlCXRVnSUZzD;Jd(YU!@X|mixlK(OCDL2P6FTK=Q9~X1{`Ps{T4e2P;LHWw{$)T~^ zU{LI_V}N!66n;K1)5tJ^!Gsp-1UNJL|*xPE2phx-3Wt!BB}utO8*bYbCMkZ*%ly_`u{4V zU$tUC1x){&3h6(UQNKu)ehJ&()8t8TPQq15F7ND#YxP8;) KM&Y&lfBrAETl?Ao diff --git a/resources/android/splash/drawable-land-ldpi-screen.png b/resources/android/splash/drawable-land-ldpi-screen.png deleted file mode 100644 index 38728e3eb9118b77ffa76e07846ac5cba682c01f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4003 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 E19$(AcmMzZ diff --git a/resources/android/splash/drawable-land-mdpi-screen.png b/resources/android/splash/drawable-land-mdpi-screen.png deleted file mode 100644 index 6c94d5721dc58df0ab2a216c9aa8dbd19472787b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6132 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 G_TK;~oqjn0 diff --git a/resources/android/splash/drawable-land-xhdpi-screen.png b/resources/android/splash/drawable-land-xhdpi-screen.png deleted file mode 100644 index 34d11f804d0e0f9c7110e24fb98b5c5ce2ac7e4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18494 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 diff --git a/resources/android/splash/drawable-land-xxxhdpi-screen.png b/resources/android/splash/drawable-land-xxxhdpi-screen.png deleted file mode 100644 index 3688f573275eeded7a7c9a0ce881db3669e40520..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33932 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 diff --git a/resources/android/splash/drawable-port-hdpi-screen.png b/resources/android/splash/drawable-port-hdpi-screen.png deleted file mode 100644 index 8c7353e9d34e0477d8e587c125b3a8ebf22be408..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10835 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 diff --git a/resources/android/splash/drawable-port-ldpi-screen.png b/resources/android/splash/drawable-port-ldpi-screen.png deleted file mode 100644 index b5605fe7217723a014080fd35b1755563a818f21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4078 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 diff --git a/resources/android/splash/drawable-port-mdpi-screen.png b/resources/android/splash/drawable-port-mdpi-screen.png deleted file mode 100644 index a3f133a165f9245acb5e398ee6cfd4216997f6e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6232 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 AVE_OC diff --git a/resources/android/splash/drawable-port-xxxhdpi-screen.png b/resources/android/splash/drawable-port-xxxhdpi-screen.png deleted file mode 100644 index 460d49a8487b0472acda151ae707e8b2b6038b6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32436 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 SvIS5AK2xLfh6Sgu{`6n>ZQ?}$ diff --git a/resources/android/icon.png b/resources/icon.png similarity index 100% rename from resources/android/icon.png rename to resources/icon.png diff --git a/resources/ios/icon.png b/resources/ios/icon.png deleted file mode 100644 index f41b1f803f81f000f94f0c185431034ab3a96a35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18809 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 O{?Jy}16QlPjQS6d2!AX9 diff --git a/resources/ios/icon/icon-20.png b/resources/ios/icon/icon-20.png deleted file mode 100644 index eab5d3e35dd00d7599ef3513f965bbc6de829acf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 608 zcmV-m0-ybfP)L{cJADH zxGa!D)6W2rxO(+!b#=9^t*wTJhMJn1j*gC*8e}2L32Wx)* z{KwCqK!FQ=;fuq>R<)$we*EhHn`_@&)IL>-{W`S>sOI;@^`EOmzceZReft1zIY{&7 zO`G1mdk^y7ynsJt9RK!rfmFYF@TEilbA{mVYuiCmxAy~G{-se7UGv&CYhJ&81B#*9 zfgg%EzwK-Ty6Nwm`(HcsK$@>^18Kem*4%)h`T6r_KYs#!^7q@kkk6$&KlgM31%Zmb zb{T%I5`o!#;B&3imnN0J?@%>EL;vreZ`0g9WitHS-T>mgx%;I-;Zq*t@5`G&zPPdb zQz8533ZcJm?xAS@2MPLre}C?1`ZnA5_qmlI-lrGeS7m&g7yRepDUexDFMeMT{(VXO uzfUhwLYqpt3g`roEB@i-(jh<7RxplvFjT(nV4XV2@!&R z025-O$)Yi)G+PFgjh2>me9$4j5nZZ=WCUuqQC|F@ONQIbwn(I!@L^JDtq}s+PTG4* zZ|_@u&b{TXbb!MbX0%UEZcfg<&+|L~=bZc8b4A%ZWTGOt2>zdg8HS;0nxZI@Br}|` zEc;J^AvDbyP;b3UarSqD1zx@;f*=+b7pJDCMn*>Z`}m`8BC(C zt}YslA{UxsfwWQ5{tzz`wDMUU7#OIntyQblAdZK@)v#tDSFhJsS65F=e4g`y94*dJ z-<>6|_{b}#sBisr2M?f3g@YHGw{u~aIBtO5WqhFc5=X98>G}WWQjy{Nc%JCB#uBlUS^~ivYweLy$U&~SipU_Rg z7=|q@EC~AxIvtL7wMuEVm`z3lG)TF{V%e|Pm&p{bJgts9%Lw;A%=IYlmf~Gf%u#}M zigBj|bKDOJfDyb~jvcutGug{+A9_=8JRYB&orMm(NKlWU<8ZpgQl-vd(LQd3rq*bc z3Wd4K`lh!l@m3Y#5+@-#Fx+MMv4_$_2kFRFIyyy+w&I-+BQT72ic`H+Y$ml~!bQSP zjzl7BiqQmvr(MUMmAv%K{^y_4zwl(mt1mZy_|d7k*&pCm=9|+=M+piIav}OV2iSB% zh`#D;z>YqE^6x6e-Q~>B-*dN^O~KRC)51nYoq#Rdxr_3aCtQ%yQZ_cvC5?io>0d&y zib$@f9M+OJ^9H&_Q(2ls)B4g2g9r?|of3Nf@`l+K@hdtvHwU$Xf17#m>KWTg+wO#0 z22`wDPQ@ZL;-b(@ER5uWAdd|8Gcj^Fr-_T6xo~nD;F+13rlzKR#l%?~1Vy1aFnc4) zD@K=iWIgy$E;J9G+zvP#4mUS9!`sYFoz4d%K)0OP3Ve7yxc9ceLIG)QZH>iZI|ml( z<@osc($dn7f`xA_7zbu{6rA^MxwGJNcC2GBeq4zd$CZWPZW-=D<5))t5jetmt%1LK zn{!m~lcwjt-X1tTd@yOh8$w`hyPy&Q>?Zivd8o-~ykl>&<*xK+udh>l{zT5PeGimt zIy8CvV6@k$>tB!;PLh}V$&2s7l})b*b7EJ2BQJeGUV0zKpVMz4y5J;Lc*5TNkX3jDV~f8qMQ{=P9|ivoauJaS-Ub^C00000NkvXX Hu0mjfcve6z diff --git a/resources/ios/icon/icon-20@3x.png b/resources/ios/icon/icon-20@3x.png deleted file mode 100644 index bfa0ecdba7165538ede6b5de241689e893d167b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1644 zcmV-y29x=TP)P!&2V&g|_d7 zJ?EU#8(_-7OOyA>$(#3mIX(TH@AI7JJcs&C`JnlU&?2-5EkcXXBD4toXrTpcJkP`R zDTO9{9LEvLMF(9pXhJy`-{j=v{rmTuo12G+hsms-7&LtMOi-3(2L}gRT3XJYJ$v-% z(Y(C8UAuN|+O$cjROaXBn@pxB0}Y^7s}-bmXlyhZo0^(xYHAK1Jh*M!Hnm!TFjEjo{P?buR zoSY1-k&%&ESy^}Q-X+s}d<)Sd3gwvi=>P{zplE!2Ja|7bF)<+_L5U5ZV`F1M zk)Pr@bVXwd z=!)(+{8Cs1XdWBfKm=dDe0lfo-2e)>a=9E>flN7v!8AbQ!oot=L8d_;9)kRQ(fvI3 z0_7GeT?*04sKX@>TVK~CX4c)f2eqn7WvV8rn<#dka%sbYL zTHDPUuJ^hyF-E?8UfgcbaD}u5>XPN9!luBc^v+;<;SrHe$WYH2D{|mLla!H*{s*=iLM(qY)DT}Pf1CERN$q| z#F7&f(Te1vEg|eD>DFtNba60MxSTEtrH@EvX{BLkJ_SqZiWs)@dmNqY{FH_$Y-ng` zZ*RBRY$GEh27{r$zaJ9Zy?gg`Ivx0Z=Hm0Pqy(ibPWAf6_2$xWOG(hUb~#-tq01uZ z(oni21T_b433(HWI+RQ4;vnkqO1Ax+mwNj-h~e7R)dh&IyBB$1RaGUGN(7+1vLkKApa%oh|n;T_=+Ayvxc)U2o2}Bev3ZjeFGSx3me!gR( z<|TMT>DM?tfSeFcX_i{P$^Adj9!eAFuTGx{43)~2iLf43(+v#rAcPITQ;^O7$YW3c|dts*>HX3o>nwqG83zCDI>yJpNf&kmkpW@*- z$Cd5A1kvIqHgd>XZr~RT&3Oym-QDe>H2DJIW;LhtH|oQ?@+8*}L|%GZ_G9*%why-( zNB-ql*1qT4tO%v^0;Dsvyqq!zqhKAr<3z#U7nlc3RVu9ybX}%Yfj`^xlXH6BKsPov zwzajn)eQK6aiTZzm*08Kz!TU#?S zGN6+74QPT0hkmHy$HvBd1KL5^+}u1mI_fjf#Go#9<~v`3_B`(U1oVvme2LJH9eNqm z>G+rwiVF6EWphIZ*}IX`lx{V1Og#s5CZ%10OTy`4HU5hSeXWu@^ehqsRK!A3hn85* zzc&js6iiTU;&TdWP?r|2L{;9b(5Es$TGYoe?EBA5pKuofjcZ6@{BQoR-}s>p5Ypb@ z(KP6O#K1kR3_sNF>;}!y&KrAXh2a0`R9M69m}^WNRTO~vX-rHkg_c683(K!(@gL@la+Q{yA$hI7^^)0e9m+Ch&<99gX4}J}HS0*pe zTCY!wO%ZJ}VY| zw<{2wsi~B%RG(1+2ci*{%{A4PRo=Dv1&uCS}#9okf}6~ z2(?~X#IO}y;Lrn90Ukm+GN zpG9cY;O~QbnCX~kB&!rFIZWNXvWta;ObFM)`1rUui5QXr;!-rEHTQX)Lz zSatDP4h;n$e1*8Kbygf-tBi71Nu4DjMCT=xg9TkIdTZnBI`D!B1g-J}yWsFmIh^x% zIP(zZ2*@e`UEULr$z-ajso4%B>f$#?c3s*$w44a^RUIUr{{#rG&;0!S0|eC8)|Q)_ zdmw;3K@GRqmZ07*AVHx1YHe-xJ@)$y1RN_XE8c2h-+}zLBJwn8@p zTtj7{Pz_um)J!=pe3SC^ScaG*FFw@Ej^L;0A?O8p{4Qz6EG)k*Jm*|00000NkvXXu0mjf DoCKB3 diff --git a/resources/ios/icon/icon-27.5@2x.png b/resources/ios/icon/icon-27.5@2x.png deleted file mode 100644 index 07b03695d6fc44923e03b798adcfc24e00adc577..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1577 zcmV+^2G;qBP)#MD;9UL6QkMZ~@v1VSkBuTQrzrUfOp|Y|vJ3Bii zC1uyHUE8*8i;0QJ$jC68&5w_g7nXMU_K`@X_sZ{EOrdibBBsgMqbv0bYGK_%8J2)1N_cRmhc#yOZ zu-LwKyB#7lF)J z+?R-)7l`cVVT5DSD6ySL&-wvd=EuufII6svNVeBx#)CX-zg_2C(oWe3lR!w zd3bnuU|^uPw--i;YY6IPj1E%kb()AR+9Ug793>$$S?h_M7s(<43sV+_IXiqsXQX72 zjLZ)vvewe3Q@(%(xZ(!J?(S{~YEMsvv9z=lq6bXBBqE}Zi<2p|hD3!`fFKZ%bRH;_ zJg|u{1QLezM0Ox@fPzprD;yg)b7R-;3mV|*lqQo2C~>&}4HK7_mq$j*U(v_wv`9A8 zwaC6$-AK7STA}=MuiR?fgb!X!gg&Or(l~x`Z1sMRmcK`nOuixl%{C=Lu+eo-{ za;o^UwJeUC{KFL`%*YjhMy$@6q3HOKf+x(_pgzSoq!Ley^TN{RpHF?aZ$s9bs&{rM z6JJxk@v3@ng6iWB-#uP&0;&p}9pPg;_ZA86SU7L%qA)NtM7r>}kk1*^Ag~|v#4R6y2qn4ojyNiHw4ys^Wy~Bd}!OURON+{7~R739Ur%$7I7on0RK6{ot z7|GAgcvG5A&wlb0ROx6Ml)YJNfrk6XV;>i$v7^7vW;}ylgU~c#!OS&G{|_sn6texT zHhaq#RNFD?>QUNw3al$Ye}L@$M=9T%n@g%XMSXO@`8t(a2$$6BNmDMd<=Qlu0q b{j~iLc+yqb1ELzS00000NkvXXu0mjfM>Fuy diff --git a/resources/ios/icon/icon-29.png b/resources/ios/icon/icon-29.png deleted file mode 100644 index fe94321bb00eaf8346091043a11a2d3e2e430164..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 851 zcmV-Z1FZasP)KHJzIz^`<$?AVK>F zdKLIGrkQTjb;Xhhn@N8_&>+oKti1?vY%0E}hCeD8sHmaA+T4PjbLZ~Qb?%Qg(~12s zBJgnTx%WKxxu5er&-2`Svyy+OW$kl+p3AZYY_ znoK66(Wq1^<#M?~p-`$+ZLO{0P*7O@2fz*y&q}$*Vljuq(cIjOKr)$3qtWQ~`kI;= zq|{(AEX>a%9}2m`F!OniS)FDg%Snb0S0>>c7e&+QbRvNgi9{-u>U26pM5C5(=t{0U z(|E~{SePK(W_YIpVr393fxYthBO^8I+)*z8z~k`*0)fTF#i^;OI>UvkN{wDut9x8g&hgMKZOb zQeR%7DlaQFG+cSvW~8w~&?Dt!_DB+s{E;5pOAHqo1~*Ic_{27q}?Q%m#3` zU+iv_nl8(`u3sG*9*KgD z!=vorS*E9uv}Cj6{bJ7HI=ridw$o_)q~9SL*Oy?g0!aquTypwp25vYU#xN|&R|VpN z{@R%JBOa)lELF~ffo_L$457UCQKirdd~*|6l1;}6r^J~c``s)uymA}g>@1+ija z%_nDucjMv_{9YC8$Of$kNzZ-pE(mdTYR&^U4v=pjr|aQ%F*N6Zn}@{3wsX^sCaAz` zYVJ8T`;7S#5RFuV`uK`^|ALwsVj@f8VgwY8vm;D&MNs!o{zGUxLf`z#r;RC5Y$oIW dfBwJbegi>!v}SyfMNR+!002ovPDHLkV1k93_+5OWa`8WrWqT=%`u5O7%Ys^_g+i; ze$?~cEw4XlwvsgqEbr##=C(b3_jAAZoOADe0rpK*0t8$ESHKl;1zZ7F!1Z1jhM{Si z;tF)&Ju&k<%hIdt&@|J9UUEIWo21e zS&4~>GMP*)7DF2y9i5Pnpin5}a(P`{9YGNOWxWqB%@x!qNpfOhqPe*_CnqO9K3*b` zNTt%axH#YgVvR z#-@FgIe-T>nM^G$EudmZNC-p>ggFE|bf5+0d?D7TRdS_f|85b{^(sC66aHQbcH~Kx z5?BGTHiD}nwy)iRR|R7gPXo8@*H4jJ>%)Z%-`LpL*Vi{THa0RcGBh;Q+uPgS-QC{a zo}Qi#F5%T{o$jkvDdO4oa+#RYZ8Oz`u|n!29eisme6QaHGr=mJS{c&$NF2b27qpiy zUAlAU4nF~2^}T!dLe9DeZgO&xN|PL~QV$-MFvr7}brHBe!U+nZ8pNEa;j4Xq4kFyJ z3uLza_W7z;_>2pi(A?Y{%CZo4&_ds6G(NxYIb~dI;u>6(aoKb$lkbib4;4viVAZZs zu_g?w3L+Ym#Jjuk<5AerKo?wYGBu$@QzC;e-dAHc+=~}4x^D5Pg`Zx0DSuZ~Gz+Iz z@fAKoqGi2YE-QYc?0RoArQcz!@mO>bt_>sVePHTwu5{EPWMNDenzGlW~Y#nO>?-)IYPU354E4i67IcTuFSl^{My!>YEKbP*6n%UaQLb*Slt zn#30wcL>HfOS~gvb1I4?g!{?9)#!1-UAXS%;_Jml1rkF1-f#njdiCKn>?q@9I7fuD{hq&XAj%3z5#d^2WtQa@N+?78e(98r;Fb z!IF{^&qTIiodJ?ATwh(UX&V%mFL1Mk%j2fOb-N4-xPHd#q3p35&QNeF z(1jDt8t=IEF^+2jSQ^Aw^>*`TFL=jgAGKNy5}25!Gv6<`IMJMBdg}@7Xb@Jp6%MA@ z5%!M7n3p_pjsJnPaJIrK13AkeQ`zI@)=V#(@cf^w0bi?vO>aKNPV9kjxd9k*1x})t zFAi9~I%w%Cv~(SWlio^CDNMr!m$M`mS56mMPQAjJ6|(l7`PLr|?&@-u##;^>hvgx2 zN1pZE314p$kJjsG$D1Pe`p_(em;C~+fGgk%xB{+#E8srbxc>uL-QZWe&O-$N0000< KMNUMnLSTY;VFh9U diff --git a/resources/ios/icon/icon-29@3x.png b/resources/ios/icon/icon-29@3x.png deleted file mode 100644 index 0756d9fed2942eb63fb5798f1403bb43fb7f40fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2340 zcmV+<3ETFGP)-AY#S(`U+-n41cg9i`bnmKky*zDSyBuTs7?xSI3WaR$+ z``4~rJ8|N~!Gi~P?AWn>{d$#3wS4(mj}!w$#2 zy}cm&*s)`K_UuVbO$E(Twt?n^gao-<4rkPA^~#kil}e>dCOdiZB;b1`2!f)3#CzZL z@bGX$LqkbP$+m6VKpvC>n1C6G$5#07y+@D7*B zWV(9wDu`dTY88YO!VWP9ZJ^Lcvrp4%wNMe@%Cl$BdJ4*qW2S@~^~9>Pv$MRseB;KA zsIWm|Bdha^M-8q4WNB$>P%mF?7R-Qxck;vS-oAZ%-@bjI1R}3cD8TR#Scs}>dJP7G z3k(K>&1U1v0@~?vQha^3b0>^H{wPomhvU|*Tf27cg0zSDqu@^`@|+Y79XbTrgpA;$ zo>e#vYcQA`uGuqD7|-O7ZnUwnar^e|;QaXbc$D_4AR2swL?VIpLVJ5VD~Ea^Y$C$+ z=n&Q0>iFg}`{yU@H_PnxM&`4rf^0iWbvM%^eJ;u|dDLuDKnr_x+}hf@bLUQ!{FCc^ zzzsNpr@&B6O-;-%f+Us&Z8ei$*NxY18!Jm7@)i+?7ZN!Oh@ANoeF2fXkU0E?#TY$S znQE^urvBYNTP(sRy8u2PKYk3p1^2?751Ef9Jnt4X2+i`Oq?H=wv-TToCb+1szl|MV z#i#|Hg-a}Yp~Voz^kT8Qqd)Z`OVKihQT9Bz%v$$r>Oc3`=mk|Q!hG}(4h|L-6@mDO zhzKZw-~!1+i)NcxEQU|C_zRqZS{WnL8q?y*{DrpWO0w-QjIe^AS&E}s!6Jr&-!5{~ z(F=*gZvqsuse(bk+&?`#6x!O_3JMBxb8|0Wz6@I(SPq>zbEc-I23EMR96oa72rLZ& zQ%Xt-S`h|>K$Rd@r=`eEI+0Z$Y0h8F=+`ZqN<3Ew96AB<$xo~ovQSzD=7_M#>CoTb zfAi)|&W#B>)N({TN`JDP;gDDfvkB*MQE;uPEX{Hnq0;NjT^r6I6Dj3yGBh*ZSOw-{P6M0jV_9GFFk^!aPQtdSR?RIfb;3;=})i8rxqp8B;Ll{erOMz2)d^48RUEqW~D3EQk*>Ka7(~ zS8FxN8m8K5*sf+fI!5y=G+1cEisS9K*VO#+Pqt^hj@tJ|^A_{j8){_XlCj@uo!@=? zBG1the(;}TzhA@5qnvfLSWM);VY~eC>`;Jxj=zlXocwL!$MI50oI)#=sT1XDnNp=t zs+4SpgCvC#oC1?8td6#9*>dXCsiC1EWK-w&-;I^aEk#TDW(1vpdfdX^ki%>Hz?39v zpbgCnOf8t~1xSjjcP6F@Iw%Sq9Ub-c^?n}y(I`0P(>uTUApG>Mgu`1CfAtGl>S{$w zvU2qb5xc4ZDGY3(-*km_i{=g5V;Mb^_hxZ}x! zuzvO%rbZaV95oW)9#zrA@Jy#n4hoMRJ!)uZ;HH4Snx@C9-?bLJ!vBIdXTOgG?DZte^3&@r~_@Tg@A;0{T$X&n% zQN(z}C~-dTo#~XxL7}UwtG2e5kAl+y#)H+)s6L8d>)g0OXfGC$MgdtWw&l(v8;>w* zNt^FCuy^JhdcY#!bTu>KIUe5Np+NoX??gd_|AZ1ahaUw+0Y&V>g$uiP@1BA}WHyM+IrCxv=P@t`g=amM(m0DQl8b@}W&x_ZiM^QO98UG!g;g_8O$n9) zS`?L)m91U7c6@xCen3dfQm6eys`!?rpiBBHLYE<`Dy>R4G> z86F;9U0ofb6p-eYmX@VUmsV6%c({aOMwm<{xm#r*}6* z5!v&n_Ckr&Qn<{b6Z#H^VCFBTx4}55c5$$*Y0000< KMNUMnLSTY#$zqrQ diff --git a/resources/ios/icon/icon-40.png b/resources/ios/icon/icon-40.png deleted file mode 100644 index 125cfc7259f92b700f55b46494d1007e2b32f7a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1193 zcmV;a1XlZrP)plvFjT(nV4XV2@!&R z025-O$)Yi)G+PFgjh2>me9$4j5nZZ=WCUuqQC|F@ONQIbwn(I!@L^JDtq}s+PTG4* zZ|_@u&b{TXbb!MbX0%UEZcfg<&+|L~=bZc8b4A%ZWTGOt2>zdg8HS;0nxZI@Br}|` zEc;J^AvDbyP;b3UarSqD1zx@;f*=+b7pJDCMn*>Z`}m`8BC(C zt}YslA{UxsfwWQ5{tzz`wDMUU7#OIntyQblAdZK@)v#tDSFhJsS65F=e4g`y94*dJ z-<>6|_{b}#sBisr2M?f3g@YHGw{u~aIBtO5WqhFc5=X98>G}WWQjy{Nc%JCB#uBlUS^~ivYweLy$U&~SipU_Rg z7=|q@EC~AxIvtL7wMuEVm`z3lG)TF{V%e|Pm&p{bJgts9%Lw;A%=IYlmf~Gf%u#}M zigBj|bKDOJfDyb~jvcutGug{+A9_=8JRYB&orMm(NKlWU<8ZpgQl-vd(LQd3rq*bc z3Wd4K`lh!l@m3Y#5+@-#Fx+MMv4_$_2kFRFIyyy+w&I-+BQT72ic`H+Y$ml~!bQSP zjzl7BiqQmvr(MUMmAv%K{^y_4zwl(mt1mZy_|d7k*&pCm=9|+=M+piIav}OV2iSB% zh`#D;z>YqE^6x6e-Q~>B-*dN^O~KRC)51nYoq#Rdxr_3aCtQ%yQZ_cvC5?io>0d&y zib$@f9M+OJ^9H&_Q(2ls)B4g2g9r?|of3Nf@`l+K@hdtvHwU$Xf17#m>KWTg+wO#0 z22`wDPQ@ZL;-b(@ER5uWAdd|8Gcj^Fr-_T6xo~nD;F+13rlzKR#l%?~1Vy1aFnc4) zD@K=iWIgy$E;J9G+zvP#4mUS9!`sYFoz4d%K)0OP3Ve7yxc9ceLIG)QZH>iZI|ml( z<@osc($dn7f`xA_7zbu{6rA^MxwGJNcC2GBeq4zd$CZWPZW-=D<5))t5jetmt%1LK zn{!m~lcwjt-X1tTd@yOh8$w`hyPy&Q>?Zivd8o-~ykl>&<*xK+udh>l{zT5PeGimt zIy8CvV6@k$>tB!;PLh}V$&2s7l})b*b7EJ2BQJeGUV0zKpVMz4y5J;Lc*5TNkX3jDV~f8qMQ{=P9|ivoauJaS-Ub^C00000NkvXX Hu0mjfcve6z diff --git a/resources/ios/icon/icon-40@2x.png b/resources/ios/icon/icon-40@2x.png deleted file mode 100644 index 25fb10e3ab26caa547d5ff1005d9dd947321c41d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2140 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 QHtY<*^}r#gN^D@#zk8uc0RR91 diff --git a/resources/ios/icon/icon-50.png b/resources/ios/icon/icon-50.png deleted file mode 100644 index 462c1ddda1e91ac88c845d8b2a44fbdee8491f3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1386 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 VOBWO(i9-N@)_py-4=Prn{{@(Izi|Kn diff --git a/resources/ios/icon/icon-72.png b/resources/ios/icon/icon-72.png deleted file mode 100644 index 948cb58bfd283f7c6161d91666ab6309791c33be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1970 zcmV;j2Tk~iP)wW3%+wGov z4_w-E=_nHec%Pg!rOaK$W1TXUAmN?pP!hRh%^B; zluBjPf&rwGHRu4LSS&tx@ZkOX_tDh6oLsVHg-Bqq+^=81UQ|?+kdP1<7zjKNU>pnp zD4h+i05E*4uCC5#G@@@<>j?aBFocBsn3|e`JeHM}1rY`7gyZ3qS!zH90hyMT25FFc z065>kX17_HSEkWyvn^h<(=Q&(5y@aMKxRuxNdX?9LMz7&k0V%ESXgFe=EH{%kyZ|m zIjemox*^UN1;!!G%*>oScMkF!Bm;015&$46Ju%>iP=uTTd7t&uy67v+-9LX@?p!qW zeM@y~sEdV6>nbtz)>-~+w?4W>n{Wp_`u~CI1I+uPgM*H_FM=6^?bqt86mIPJ3@d&c(`?7f z{qV{FyyAVf`Lm7f!^LtDUb+)I;f?G3sBSGy&7oOe4H!y&w{G1!eE9Iuqeu06eN|Nz zJfI*478Vv36coTkC?G%qkJzGA%Fu9CW};$3<7X_}fz?N1APd3(@7*_mEEi!#Z;@xy zY%@>hrCWt!C=T!5y*n~8;!+tPY)AtTmH@Uiv-7Vpl`>4BjEz+ORVcQd^qbT9gARB( zFOvT<*F|`x7(4Mcadw}b!aUM#i;MSA#c_FzOC;z|02~t&vqG?_NR>54$TW4UZBviz777|Y z_uO=~fk`S%a~@S0fSvF%|9*;f)bhdgvccFs1P|sno6!v$|IEUDwRh_ zSc3-x)Q~rB{DB6Nt+_aeP!X^sx&k1rQ(eVQ%Z8Q0e60ynzvDWD0rNJteX@GRpc;f7 zq3gB+^^LR7^oc!rqWVM9f;3syhv6yliln%R^tiB((i5~A4eTIM;$cQunR&Gi58!3H z_(SWY#5O*JKI#ZY6O%+kG+w&HDRaWw)4ofbPNvPq6{Zl^ta$tO?FSDYECFM0IXgz_ z6?ElJd$owF5J5heEcG|&#FNLp$e%u+ua&sE8SQQ;jHruX*_^zDq)(nnMPKb)_%PpK zY|X_=oJFf(;+ANLqRAPL!BCOf*4EbB+snOm0-Jt9d@Y|V^+n5us1T7AB4bqmQQ~F( zwFYiwHJcWv19fZ`@^lJJwo|$TF!fgB`5Yb>SupAsH3L=|;3RU{E<&%Qi7Ai4P$(Wb za-^xL$qg8rl>J?z-_)yjUDoqpR!^4{j43R)} zKRG$MslZ&b{3dvgy%J#jXO{xl#svE&oIQTvP6GY$Dls^*EEsJizt3Q{EzA+(!Vs7X zjgRp{p1bNE_T5$D#Uad@k1tWLqRBM@8zriParHLl6b+p#u}4eTvDZw$)h-KmIvFqa z!b^884k`7;j=#CEAL9e-)?mk9XF`J;qTPwBeTdqy)$GUI|C+?^pr4Va_7Zv((HH}} z_xaWshu4If2hMPAIfL1Z=RXFWiN;umA+dO^jJos{kBcm)>1sV*D|H&u5Cd^Yp4qpW z9rQ|cqsb|nm~?Hpfi{uL4l>Ttgn?%WI=JRF6Ty67>5U)`S8-taYX1Yv{O@#28}0cJ zo4d&Obcmps049J5U;>x`CV&ZG0+;|MfC*p%*gCO)0TfKZ_u^Y2pa1{>07*qoM6N<$ Ef|u8zcmMzZ diff --git a/resources/ios/icon/icon-72@2x.png b/resources/ios/icon/icon-72@2x.png deleted file mode 100644 index 57192935c1180a9b18f1044eb59f655a7575fe3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3763 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 SUs^y!Xa>5*I#mzBG5-M^oC5~{ diff --git a/resources/ios/icon/icon-76.png b/resources/ios/icon/icon-76.png deleted file mode 100644 index a646758f9b864d73de272fba0c03e1986808102c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2076 zcmV+%2;=vOP)$js-U!@|ps@_x85*_IAJ1 zQ%Y%X8B{>m-IJ5%w!P=x-{*dRzu)m$@2hE9xQQZ!hcp=nZ~OZCs;a6|Q&VGNVgSS2+Z&Jq0s=5n*ldf8j0_102@DL(&(Ei6 z8pf_#pgP%y2f4AMqocUEI3XcHDwP5i$ORrKkw{EbKq#4Q;o;#RV03hJV`C$}ly%TP zV@NQ_^vH*Xh9H*q?%fNn=;Px9ib0H7AelFK1Rx+hh2-Sq(b3V>6mYSS=6Dcqa=CoV zmMy-%zTkBL0ARo%S+Kz)fFTzzUc}Pb7LbJiHFiC_8j$7*6Aqf1nhqa63^4|RfGps9 zwsf;-IL%~cX5#CZXDP!YWKdryzv<8ktZw-saqMBUZr!?-l#~QM3ATc0;FkX?owd6{ ztfr-YA-U#pF-`!tZ#)6-Y4UcGSP!h;77y1TpE+uQHny$f|_eSQ6n8#iv=ym|io zdB~Pag$$QUd_~f;@d5giLZ!lu$Z!U4M0lKR99@V|vo?XMGcD(F+OX4IF(*uAkV~x# zE*z_EZEY|;E-604WD*~d^vLd))VauF0vpXOo#(8uLT*%e&2ZLs)-BaI1eAv*? zV4AXZvkgid_^`FLb@7mJ7D_oH*@rPNO=Sw{91kMPmR6o*raO`TB4~v?6QVKOllv(g z+d!R-WN9U~*iJ~On@yFMwUV%^2$L>qdW6XaNAig{Zz@Nq$`&YX5$1S81|m=R)88bi zzdxd`Iz*igLoUsEa;_Hy^UR&{B?Tu3Bz9K|Nc`>K&`?Cw%b_9SaG4ZnW%E1Kc6cI% z%na*}J$v>vH#X?&j)0FTvpsFPsC+$L^8u?In-gb7rKv9@ke))$Cqh>w7>lIE)kYld z%Bdv&mY907@3pN#qF{fq%ugis50(arjUA5tHv2-c=f=!gfb*OvUnRaqh{tWsj)k;%2D!UAaXNv zO_1Zck@>;w)G&u8hJmUtV^L1BhE%vhp}Y9pGY5%_@@vU1h#pHrCo4#CBr8{SD zX$4767$Ds&Ar%;M%qC>{azkphNC)s$fj|H?x+6mt78bg>xk0_^n2^|A%gf8%-QDZz z>P(+FAmr`ax4~VjtE(Lo5<4d>-l6yeJslI$G-n(*Z~)eg4hxB?Dl02XN=h7D$-%)v zC* z)B?zY5VTD`Zwwj;>La zY_q+doS;qykn(l&N4b(2>!`e-h1Qc7UnkODK-V{oLLL2l!1Oh(801JdRTM#;38T)y zYq+r&MS?fdmlAEdEA?1ax&uU;KPrMMlu%{6Kxd9EDZH0e^FDb>gsyKIg?a=yIrC?$ zJ$pQh`$=8PswTPm6IQKU=x-GC6!$24YJnX$R!yLDxCYMK_saia+`uni&JPybyc+Tul#000x0p$^nC^2<(1l%<6YKkj!g+H=VIe!n&;IUB2> zFy+StACer`l8NT86P+z3;Lm*=w`~V8wRf0~fx~z5ZtJtD30ZqvH7NL0-|^iBThZYt z#vZlFcrA;_%AQ{=c3rKk7L^qR^)3CJKctuMQ0gfAIk#&!fkSMuZzWp5fw!qylm80z z8M83$UqR@A4A}lxP~zmN+JEIg%V?p3|6kT^>+y2d4a}9U7YPT((d55a=4vqr#Chl* zyIE9vpPlT?y?gf#BNC{C(zw>O+gw>$SzZ0@X!FzY@v&WdfV8yqyW!z{jhGXjz}NEO z-)ArwOlPNRBv&W`s4clFp?d3I>}C zvnHpckan!}KkP4qLZOxV8I+yfL%iMGRqTtdw;BGtj@VmFrsI55IyyGSDSelG{Ojtf zJJ>cdGBPMg&WX&4g@xsfl!OFrsldoJQBl1LGXTD&rG-Z+0M#g`*C~(J;2ajSHmm;s6-iz$k5v*%yP`pb2 z0qxj?bHhnr_^ptP`A#<`{5;>N%vi&h&=KH$80UUCZ~np~79n`Ly$qE)Mx?eB7|D>o z`Rm83X{oxQ>YhomK2u_gXhGZime$strQY7EDq#o&a{c;s@78b62 z+&1C%sMjb0;uWNp;fa7&kIUfW>3a|OMEQOt93~lNtPD&a@LxH)Ilq~G%_9ES3e{B@ z`qQz?V}4R^o~-h#muK5eAkP9hXVQE+WsPP1XC)yX)BZY1M^q>DK_9u(YdE_sOyMnS zW!AY)T&NCVF|nI7iGn1>V%O;H2Q#h;hEo5=4GzYge#@J(QXNwOw!>R=sUi3L{iWSX zQK9grmtU4XMdFvhIsh(KR?_CS)>ifuQTLQ@vt|N$LM?cQkdP2>Z*LbD!R+Wa8EjE9 z>z>u(YnHcfldLf7Jp})lt=Isg1`;z<6S>r*k2Wq&4?#Og%;Gsl4%=E?$F;;?Hxnf` z@?;A9aR=yc(+GMAkW~%anlyt|#Ro}hyQJN?KZN9B)79|ZorD1W^IXewYa1I&)uX_K z$ID9wKR9<-`ks)+jOWX{w)xF!`+Y3pmU$Hd!Ol{V<5m=m%5Q22?T*iSamVl`cvu)JFY8P zw+a>O>gq-`#~xY_#&f=e`FDQydwr0za)drx&FQ=;nJ;@#&?)7y#JYCqx6r4(kO}@h zBAt>(g}hYrH($Wyr)QYZZsL?~a4Tm%>#3=sl!(q(HisQaY0u?Y4Ws%b6%`eO1nw-Q z(?Pbn#0%+bw$Wj@(bhQ+uThst-9Ag0mc)6on9}hCXe-C1Gnn_V>GUkHy)eG#S5O(e z)P%B$(h$u37Tee;BO*fK0#Y_-B7k8SawWRkhi?+dq?9XHDt-##ng3X|Z}VtXTwaI1 zpa(>5T_kLgK4=A-Ik36)veSMZb2MLPsyVor`N=`?aXaf6H);~mq=9VJSP48=Hn&0H zmSPXz6$SPfa(te*Vd+c~@e>lNX24}M$AG%%3TH>$iwrLp!r%FDH|52yTfF@pG;KW+WMRQDUp>who7pV@~I&^z1%%N=4&KvYe!UATHjlK zu4d^s6|T;m62n#nsjRE5g~#!VBiM(Ah9uZ%gW)dO=`Qgi6lnhDFPYd4=S(bC*?Cn&Z7`hLt20opiFUNv0`*EKN}fyTv4ioZSCU+H&> zjgOB_r4wcz=&VrKhKFPd6>K2MQz&`OmfSt&r1z z{I<8ZLEE$4F%e;5$7}D3reD~#d%P>Os<&q6oz*jdp5ZFhJPloERr1GOo~Z=x@KUf^OIemAfmd`2RX=Rf!C zeif@5VCQ${+7lh3{ZawNKA1b!2k4-&132D2gZr`ha(q$-CCnYDWAZySz0`RY7qG+R z9K85C3e(E(qWH&1lqZud)w0;Bj-QN6D1$LAyITqR>>B;#8{ufyxj-y^`2iJ|EZ+}! zMr&5<+qUlRxIP30fdK8{=m_7rOP$LPs9R<&-dq(7T&HPCPRJ;9Wx}!{jHj~)^VI^w ztO_)!56+Ia3knL_&~wU+SS)sejDvKa?lYh#)@$ll43W{j#yJU4{$n0x+sa1~$oAlu9TWO_VIA(Q~#rY|9~`{&;0l*?UtM@^5{Uz{#}l>Zr^+(CP9vG>>6YvC0s zUZ-Q7YCA1mb}t6wGAFu$rp3xE{QSFbkNJX2i**EPSZO`+g&}`79LLTgCC&$7;UhcV z^WMxlV3Ti>HyXQIubyyaZK=LozbVl!ur5JyalXf-_V64z0YbrESsyHp<;e~Xi4Tk1 zmVpv28N>j)b!)yO1pUN$Cc%rn`&#noVTdNO4~Ck%cb-w;k%Co0I7iP6lQ8Ud@xc5D zxjqyZ-P?4x{Pj!`p)z_;e>w*GX5of(jjH8?XT_tkwef4BU`@jCGZ_^_Mx>gGN>qOe zgIgFv`fj>ktB>`96O%Z{FSVDC?uwV^GS)~A6?o^A*m|U5`!^Xmuq@emOyX?jr(~O9 zsT`Gflf};tw)F+Z?=5>gJ+cEPR92g+gWXgkX$oFa<}IF>SJ- zw6y=;Vs}YNNk)mxfb=apdURW2AOUN#Sk0fK^d=}?KxNYJ@`!Q9Yqu}{rZnGM&t4Xc zzI>W)&6A>lQHPyGKYxFR*OBs3 zq*7yK$U%}FV+u}i;*)W@S$QQtldXM3_M>q_mdz0tFRrYCs3zTpQtqCe7bw@(qNa<` zl8+M${9kv&rFM2HP{;d+k<6Xgv#qVPs3e&HDoAUImF)3)-a%-=pY;IRtP^N>XlNB0 ztzhrb$3sY#9WJE{Q_ZHz2BWMgwPyny@xhS1P{@_(SGa_=x1d~bYI2XOMvMPtit_v& z;y}VK<^*nx9I2@%Nnx(=8bXf0dm@_88hO6|skBEyeV`>6pQLdQZz2hho| zJbWoz+iLg5b8uf~SHn!KSwMp%u7g)+IPhJynOA32>AiWuPgwcnr6BvS&$XKCa5oUX z$#-<0v1NojNX;o;9F)z)h)&$=@)zx$eDbQRXgz9r69tzN80vzFmBy~CT}(*g(}^Q* zlLS>&s}=hT)7z`nQ9zSH$528(awgz09iwiNL>9G98zah&xvv;{pH4<{(4*!P4QjlU zzKq21ds9nG=!bGB(P&EnwgZhAxy#~p`r#Abt#AEN@T7g~2KHom$d4qLY z)ptrN;l}=M*PbeiP#g*2kt5?%xh`VtB?id~iHCBAG7-VqB8Vea)IgJCcQk~UawT#k z*d80_$^00OV6L)BP=D}8y+aXzd}^<^<(034a-=x;KKqiGk({0gX4bZ~aX`-`hC|lz zse>*6E^h9-R#wTtICi&?5Cs)M0S*ppOUoo+9K_e(*EcOKjVu=cR#3P?d}5H|ENWVM zD?m6WH#fz$-c*K~*<-KwGF}<260+vRx0wY@l~w;>}+y975^`ah$+zCV_-K`739_$fj~}4Nov3^77H|JA~n3V z|Dochc7+@Sl7oZTQcu+1xVtCJEFe(!^eLk8vkmlaIx&;Mij^~QhMCk8b2pyKMQu&i zU9+eu*FBRn5KM8lZnXE-_{al26E@IptgA~c7KVpaG1*lm@0FyoR81oY5uPsOo2|f8 z8X^D@!H9(jOei8g{p)aceORFk`}0DAMdc`q`+K0=quSRbTZtA1aO?2S=auKk1$xu2P*6rstUBa=`=6dBx-gwaZ70P40J?or A1^@s6 diff --git a/resources/ios/icon/icon-83.5@2x.png b/resources/ios/icon/icon-83.5@2x.png deleted file mode 100644 index 9b25425001dd78b65cc4fa557fa2b8c624470c83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4199 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 WJn~EmS-#sG;OS}^Y9iDfBL4@M%QvY2 diff --git a/resources/ios/icon/icon-86@2x.png b/resources/ios/icon/icon-86@2x.png deleted file mode 100644 index c791d4cab0737d0bd2308874cf4a1a10be794ce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4378 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 F_z(6z)F}V} diff --git a/resources/ios/icon/icon-98@2x.png b/resources/ios/icon/icon-98@2x.png deleted file mode 100644 index 01f600e0c7faf336f63927cdbe15d1d8e93b880a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5008 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 VR~G6OUvaRHhKi1IwW4MCe*hI~bVvXI diff --git a/resources/ios/icon/icon-small.png b/resources/ios/icon/icon-small.png deleted file mode 100644 index fe94321bb00eaf8346091043a11a2d3e2e430164..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 851 zcmV-Z1FZasP)KHJzIz^`<$?AVK>F zdKLIGrkQTjb;Xhhn@N8_&>+oKti1?vY%0E}hCeD8sHmaA+T4PjbLZ~Qb?%Qg(~12s zBJgnTx%WKxxu5er&-2`Svyy+OW$kl+p3AZYY_ znoK66(Wq1^<#M?~p-`$+ZLO{0P*7O@2fz*y&q}$*Vljuq(cIjOKr)$3qtWQ~`kI;= zq|{(AEX>a%9}2m`F!OniS)FDg%Snb0S0>>c7e&+QbRvNgi9{-u>U26pM5C5(=t{0U z(|E~{SePK(W_YIpVr393fxYthBO^8I+)*z8z~k`*0)fTF#i^;OI>UvkN{wDut9x8g&hgMKZOb zQeR%7DlaQFG+cSvW~8w~&?Dt!_DB+s{E;5pOAHqo1~*Ic_{27q}?Q%m#3` zU+iv_nl8(`u3sG*9*KgD z!=vorS*E9uv}Cj6{bJ7HI=ridw$o_)q~9SL*Oy?g0!aquTypwp25vYU#xN|&R|VpN z{@R%JBOa)lELF~ffo_L$457UCQKirdd~*|6l1;}6r^J~c``s)uymA}g>@1+ija z%_nDucjMv_{9YC8$Of$kNzZ-pE(mdTYR&^U4v=pjr|aQ%F*N6Zn}@{3wsX^sCaAz` zYVJ8T`;7S#5RFuV`uK`^|ALwsVj@f8VgwY8vm;D&MNs!o{zGUxLf`z#r;RC5Y$oIW dfBwJbegi>!v}SyfMNR+!002ovPDHLkV1k93_+5OWa`8WrWqT=%`u5O7%Ys^_g+i; ze$?~cEw4XlwvsgqEbr##=C(b3_jAAZoOADe0rpK*0t8$ESHKl;1zZ7F!1Z1jhM{Si z;tF)&Ju&k<%hIdt&@|J9UUEIWo21e zS&4~>GMP*)7DF2y9i5Pnpin5}a(P`{9YGNOWxWqB%@x!qNpfOhqPe*_CnqO9K3*b` zNTt%axH#YgVvR z#-@FgIe-T>nM^G$EudmZNC-p>ggFE|bf5+0d?D7TRdS_f|85b{^(sC66aHQbcH~Kx z5?BGTHiD}nwy)iRR|R7gPXo8@*H4jJ>%)Z%-`LpL*Vi{THa0RcGBh;Q+uPgS-QC{a zo}Qi#F5%T{o$jkvDdO4oa+#RYZ8Oz`u|n!29eisme6QaHGr=mJS{c&$NF2b27qpiy zUAlAU4nF~2^}T!dLe9DeZgO&xN|PL~QV$-MFvr7}brHBe!U+nZ8pNEa;j4Xq4kFyJ z3uLza_W7z;_>2pi(A?Y{%CZo4&_ds6G(NxYIb~dI;u>6(aoKb$lkbib4;4viVAZZs zu_g?w3L+Ym#Jjuk<5AerKo?wYGBu$@QzC;e-dAHc+=~}4x^D5Pg`Zx0DSuZ~Gz+Iz z@fAKoqGi2YE-QYc?0RoArQcz!@mO>bt_>sVePHTwu5{EPWMNDenzGlW~Y#nO>?-)IYPU354E4i67IcTuFSl^{My!>YEKbP*6n%UaQLb*Slt zn#30wcL>HfOS~gvb1I4?g!{?9)#!1-UAXS%;_Jml1rkF1-f#njdiCKn>?q@9I7fuD{hq&XAj%3z5#d^2WtQa@N+?78e(98r;Fb z!IF{^&qTIiodJ?ATwh(UX&V%mFL1Mk%j2fOb-N4-xPHd#q3p35&QNeF z(1jDt8t=IEF^+2jSQ^Aw^>*`TFL=jgAGKNy5}25!Gv6<`IMJMBdg}@7Xb@Jp6%MA@ z5%!M7n3p_pjsJnPaJIrK13AkeQ`zI@)=V#(@cf^w0bi?vO>aKNPV9kjxd9k*1x})t zFAi9~I%w%Cv~(SWlio^CDNMr!m$M`mS56mMPQAjJ6|(l7`PLr|?&@-u##;^>hvgx2 zN1pZE314p$kJjsG$D1Pe`p_(em;C~+fGgk%xB{+#E8srbxc>uL-QZWe&O-$N0000< KMNUMnLSTY;VFh9U diff --git a/resources/ios/icon/icon-small@3x.png b/resources/ios/icon/icon-small@3x.png deleted file mode 100644 index 0756d9fed2942eb63fb5798f1403bb43fb7f40fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2340 zcmV+<3ETFGP)-AY#S(`U+-n41cg9i`bnmKky*zDSyBuTs7?xSI3WaR$+ z``4~rJ8|N~!Gi~P?AWn>{d$#3wS4(mj}!w$#2 zy}cm&*s)`K_UuVbO$E(Twt?n^gao-<4rkPA^~#kil}e>dCOdiZB;b1`2!f)3#CzZL z@bGX$LqkbP$+m6VKpvC>n1C6G$5#07y+@D7*B zWV(9wDu`dTY88YO!VWP9ZJ^Lcvrp4%wNMe@%Cl$BdJ4*qW2S@~^~9>Pv$MRseB;KA zsIWm|Bdha^M-8q4WNB$>P%mF?7R-Qxck;vS-oAZ%-@bjI1R}3cD8TR#Scs}>dJP7G z3k(K>&1U1v0@~?vQha^3b0>^H{wPomhvU|*Tf27cg0zSDqu@^`@|+Y79XbTrgpA;$ zo>e#vYcQA`uGuqD7|-O7ZnUwnar^e|;QaXbc$D_4AR2swL?VIpLVJ5VD~Ea^Y$C$+ z=n&Q0>iFg}`{yU@H_PnxM&`4rf^0iWbvM%^eJ;u|dDLuDKnr_x+}hf@bLUQ!{FCc^ zzzsNpr@&B6O-;-%f+Us&Z8ei$*NxY18!Jm7@)i+?7ZN!Oh@ANoeF2fXkU0E?#TY$S znQE^urvBYNTP(sRy8u2PKYk3p1^2?751Ef9Jnt4X2+i`Oq?H=wv-TToCb+1szl|MV z#i#|Hg-a}Yp~Voz^kT8Qqd)Z`OVKihQT9Bz%v$$r>Oc3`=mk|Q!hG}(4h|L-6@mDO zhzKZw-~!1+i)NcxEQU|C_zRqZS{WnL8q?y*{DrpWO0w-QjIe^AS&E}s!6Jr&-!5{~ z(F=*gZvqsuse(bk+&?`#6x!O_3JMBxb8|0Wz6@I(SPq>zbEc-I23EMR96oa72rLZ& zQ%Xt-S`h|>K$Rd@r=`eEI+0Z$Y0h8F=+`ZqN<3Ew96AB<$xo~ovQSzD=7_M#>CoTb zfAi)|&W#B>)N({TN`JDP;gDDfvkB*MQE;uPEX{Hnq0;NjT^r6I6Dj3yGBh*ZSOw-{P6M0jV_9GFFk^!aPQtdSR?RIfb;3;=})i8rxqp8B;Ll{erOMz2)d^48RUEqW~D3EQk*>Ka7(~ zS8FxN8m8K5*sf+fI!5y=G+1cEisS9K*VO#+Pqt^hj@tJ|^A_{j8){_XlCj@uo!@=? zBG1the(;}TzhA@5qnvfLSWM);VY~eC>`;Jxj=zlXocwL!$MI50oI)#=sT1XDnNp=t zs+4SpgCvC#oC1?8td6#9*>dXCsiC1EWK-w&-;I^aEk#TDW(1vpdfdX^ki%>Hz?39v zpbgCnOf8t~1xSjjcP6F@Iw%Sq9Ub-c^?n}y(I`0P(>uTUApG>Mgu`1CfAtGl>S{$w zvU2qb5xc4ZDGY3(-*km_i{=g5V;Mb^_hxZ}x! zuzvO%rbZaV95oW)9#zrA@Jy#n4hoMRJ!)uZ;HH4Snx@C9-?bLJ!vBIdXTOgG?DZte^3&@r~_@Tg@A;0{T$X&n% zQN(z}C~-dTo#~XxL7}UwtG2e5kAl+y#)H+)s6L8d>)g0OXfGC$MgdtWw&l(v8;>w* zNt^FCuy^JhdcY#!bTu>KIUe5Np+NoX??gd_|AZ1ahaUw+0Y&V>g$uiP@1BA}WHyM+IrCxv=P@t`g=amM(m0DQl8b@}W&x_ZiM^QO98UG!g;g_8O$n9) zS`?L)m91U7c6@xCen3dfQm6eys`!?rpiBBHLYE<`Dy>R4G> z86F;9U0ofb6p-eYmX@VUmsV6%c({aOMwm<{xm#r*}6* z5!v&n_Ckr&Qn<{b6Z#H^VCFBTx4}55c5$$*Y0000< KMNUMnLSTY#$zqrQ diff --git a/resources/ios/icon/icon.png b/resources/ios/icon/icon.png deleted file mode 100644 index 23aec95340a23ceba7add60fdae144517f25fffa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1563 zcmV+$2ITpPP)n==RQvx<9&G|Mqm|K1y+GoU=>*ZcdQJ<&@}Dl z!sT)~olf|KBhkX@@px!o0BiUFI8G46zs8F61Ilpj_4W1p_wP?nPY(|dcXxN6K7G2f zvT|Z#0-b%KtR60cp;uN`?%cUEFfdSCTU$|4QBY7Im&-FUGSbu2MIupdZtm376dL)0 zbOk;zpWk^TNzTsB_Vo0eJb5xdKOe}XQfX>xDs&VIMGhC4nVEHUb*rnZ&r#7WSdkr( zD$rS2Sm^BREGa3;%F0SfNdfVcN@cb$)Lf*crC}I0G&JOQ%Rio5=r)KFTxc{JtE#Ht z`AQ@b00kO9ALa`j#{nG-y12NA=Ef@u7xB=Wx9xi)CR|QL33lx5?LBtv7$Aa*02BsGVO`Yp@4{f^1P-{Fc?cN?M($Z$L4Gs<-IdViS z7DI}_?SU1N28$?gHI5}FORn`9Saq#t$Jd`xdI{0+CZX9yXk!WOZmz`=4R4T*ag;&r z{O$}xn7P|~B4tIO4Mp0X`5=wLF@91k7(x4B5vjq!uR zC#;=MpFZ^~jSk+ud-vI_a8{vINo81nRT^{VkQE?6wg3}!4iTDIqW*RE={N7=&IWMF zroFa{gRpDTv}Sn%X#2dfq0R;y2)eiQS7Me5(CDUHwb!(fq=sbVY_jovFZO zO15RlRj~5I8w;k<(%kg>irKsHrL{4h2!;Sq*00I*gWG-%#_g~Vy-zg81#ml(Am{AH znk{V*!a6rM7tD&Dh{yWq#|G?jh2+x`*@;4VdA_pzsI2OpT&-3!GBUEfyv(ho>{o34 z?-EUWLm)J}95))c8@Sm9i=%;uiyoKDMqMl*+2rG9 z1>7zBC_^@H*$7z;27}3D+Q@3YXVptAtp_c-L_#N~AeXhVHseQdbK2#E*Bmb!tRA<{ z!!pDryO@V)7SX2fgN(=^6x)>&(r*KvRSk29h!sV7c{wWN__D*tO6nz~?jZONQio_y zvT9@PqaTN)0%D!+CNyEJ_ilx-qL)s8=}uW8ouN{G1}k@INQEe1Ei5d&aN$CM%x7O0V9MY_2#%>9}F5{%wQz3)RUfQ{d z2-JG$NHaq|+48r7|KM-MOjwI>*v>}^{}%|X0;|9(unMdKtH2tFKLLTUtXcA-oXh|K N002ovPDHLkV1o76>9qg= diff --git a/resources/ios/icon/icon@2x.png b/resources/ios/icon/icon@2x.png deleted file mode 100644 index e18bedc519133f71d74a87bb38d5eeb2b90b6136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2980 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 Ypt6Xm_-WMF*}wK}VqmUcuj>-~A3x%}zyJUM diff --git a/resources/ios/splash/Default-1792h~iphone.png b/resources/ios/splash/Default-1792h~iphone.png deleted file mode 100644 index e725ae10140c220e69cf6f2d81ac38f1b836e28d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27457 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 WvKV}_@iNx7Z6@a}&Xu3Ne)nI}v&UTk diff --git a/resources/ios/splash/Default-2436h.png b/resources/ios/splash/Default-2436h.png deleted file mode 100644 index 4e7fb644cf8fd443eac5033410bc9429ae2b8493..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40154 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 GUi}}ZsP{Sm diff --git a/resources/ios/splash/Default-667h.png b/resources/ios/splash/Default-667h.png deleted file mode 100644 index 6c2e7b17e878ea0cb9b987ae7dfafcf1c2c3cbbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19833 zcmeIacT|(xwl{3qii&`Uh%`}A5a}Ihu>sPhHvs`@(z`%NwhdHzH?$~KTId8qiBcu> z-U%H8p#}m;2>Bk*+50>9-20s|_88xJ?>pY|N3zC~@yx6;=Ui)+-6#)$LLvpeU2YXNxO3F*tKKokM0}3 zoWM`heKK77axi!3k>K#|)S#4-hF)xL+gEY%{@{fM*_oTUFAX-dZEY{I#D6Npi}-zi z{qbXiN@RnY-DZOzaZK=p?ZbP|dSQ|kG(x&$ozNMSqd(jGK&<1{tB*dxd>s56vEaOr zucwa9@{EKPoj7(6bL`k-_G8BcPX5_kvp;q$`~0y#n%@(S|9bk>#7G=Frhod+<`2TZ zLJtuBchLVDF))q)I{ts||JR6tY5dpm|9k2GdEx%U{QtTC|FrP`82`VQ{y#D9AM^i< z{r^?^f3M*DHwoTfWc(lU|36xAuG#-zwfs{%|J3JysKp=J{f9pNOSSrgN&l7p->X*t zvj2axTK!}G|2+QxBh~VNPG10-kZFs&X+_k*sLv^=d*B|v`TGGy1K&y9P2TC$y_w7% z^Ym_x9r8_l=f1AHV%b1_O%M|)T`^G2+u6W-_&awaT%co#&e%aIe)>Z#JFwMA-{!}O zc7!CWKo6n)Kbh1h#mwvbbNjWCR+8kwu=$fRB|@f8v|)H14HIp*8OlSwkm!AM*eVq) zH?i`tqj|JSi2>LmE@{KWxZ@OGYD*zRQlzfESpDWUpq9D4)}rQW9k`PI0%KU7P&@Z& zIaIlSG1~X1P80R~V;-r%Lk9t13ZH!hB&n-TUF7~2NdH^LDL!I!8}S1ZZ6Ge8!_giA zLIwKve$9u5ZQPvFMep8^Z+DNA08a1h^T3w?uRS33kJ$xI>Yu)c0p#RwUojH;r?b!h zo)9YmXwKi>`=^(I0Y7F3zVuapQT+Mxae3aOkF=iiog*T=nXy_!W=(F-0z9QPZw zM2U^lEA?uUMBC-a%p1PFuQ0anU9%CuD#Z4T!2i(Nc6R`h~eP% zfh7pz^8SHr+$)}I z4$C_w3Gk~@Q64Vp#+f)^O~=S}(6AZeLEgoYo=2qH{avc1Rkham{Yk*!<#vAX{$jOF zb0`Cc)NS}19Jo$Ml080DFQ`{rTbr=l?cz0Yux^$mVynm?{DZf0WK$7LjuDG+y1UFFTy`nV?p~f#- ze5h$n9st;uWPNpDZshL-w#@MXU70H3h(_|N5^;W$7eFsvIfn8#e33~AG zNXoa1Zb9kR-;~(6Da`Y3)Pf@S41}^y=uz<4pANvfR&)bulE&8dKGEr5Yi^+}vNK>$ z*ni6J%2|x?lD_6eAyTu)b z5p;dMOH0x$4o`Xut&{hCpnPn_rRrh$1<|TA!iD2E7JG%E1ff0toGlF_42?^`;H)NU zC|W;%FR{3?E{6td;O|^NGOwMo4Hwf7O;luvUw&{^+*v6tc%v3e>IndpM-GsRL>_TB znVFXhG%A*sE^en9_9EAfO9P~eRjSU@G%l!2z|4*Ac(0tfGaQXilrKlj-c626Iz@_P(r_Aiyv#C5AJQ!koM2t0WWiO`F6BF3n=1zk!%uz65O@vsQ7Z zB16=KZEiEstTz+{lSSs-wVJt6l$oopwpMR`hdYB-m{7ocxWRvT{4tEEj_i_GrwN9v z&jj*^Fbn!%&mfW50-;aXayd)R#HHe4{ctm*?DK-xZ6|tQlpcl6!@UwH^=Kardj2D( zTV_%SeQw~rkz=PYQp@56prj!?9sCwE3lB7hqmMKu^W5w=ES6UC`1h^NQU2z*61xQ- z2oJnb4UCDNkB44>?<@>hL$1R2QU~5;X(sc;OnGbU9B3!Pbdf?Y^QLFb^Lqw;1CCcJ zJtD6MY@{ynZ$5Tcysk{6&ByzP=Y`yre`#1r`|LEIm$}Uo&gXhXoBY7H?{dG5^~Y$c zD!479gVg{tC@R_;q#PNVxL=8NsWKTL-U0dBd9TOXyn~mz__h%H6PWuKU-iF@ELR!3 zol>vv+qZSFwLZTOx0!4mY`n-*;d8jc6YA&JJ=gKZB*8kcpxkL&-)!)x z_=J8apowx(C4lNk+3pA`Al`D@%3Db~o2&x|2(WJjxO59qUyTusl=BlD6%(IAUCFT= z+=>z$3fErz+~()@HwY8coK3$m#Xb+H{&S??3R%JiDgCGQx!1UQ=Bd ziE1PEB;5$!VF<}ohet+J_Xn2flHkyqTRIbws)_C)YeIqVrJ5YjF;g#X4_9bWj8`s7 zBMdC(aPeGqQ!1u~s52z8hpEB@H2&bNM>0Z5B7|g)9uJ`1Fr>q8T}TY{>149fLp{U( z{F)AQz!d%j>(ZgXKQ&Tx!xE^F@XZ^V=rXG7{N<(>~R`Uc4~ezk-~Ij~Ca8 z3qwTelJ9>)U1?CgvOKu${Q&D^YkB1~AL786iuUV2*lTL{YEGGhN7EjGr(`u{X|+2e zF2y|CmdIiB04i05!%7#+1}9LQXy5hZpXM+rA#|^NoB%bP#TARx?YU63rw78Hu+3lN zelU=yw86VwhSl1Tt1EwIRk!(ldS@hG#;Rv4VQ71ufa5xD@dK{ zGcKwuG9Pux5N{gxPWa_2kq5HA&nKso1eaE>3ZuaTYXv7|5d|+=4`>1*?XA(yu)nQrbR6QK5@|ze;(u=kiun z9c#Bq$*SyfNojLINen_WW;*Ua)Lfwogdk1w%I_>C%6h#|m^;ZO?iMdTn5T<%DQS?w zf(iHEoX$B_@j{lrq4zFS7OUu%l8QiIw|EO2v|Bcofus)y+0$8}ep#W?4`PMbA5mCq zt2nI(b?3l63*WjmO>`J2xs^QVI$Md{L;RcVd>ZF+q$*U7^T;K*M-xOiyXLsyQu4FU zEzY9%>&QK}Ubjj}p^n{bnZ^79n$X z`4F~KF<6m2n>Baq$|Qe8HC)WEpvsygPjreweirAF#q=lj|5G;p@F{??5OJmy^t=n~}!X^zGG2 z0xUXqy$B&Kxmym0AeM6NI=$|K=D*?yHd5(hvMF+(N51%;f;ZvRwjeH#!dzif zlu=iUM>$0G*CWTXB=#c*S{E|CcskELYd{3|xaro3fH`&EEPwS#;6WD)uE?0PeNm*e z9&}+JMXrVU<1xcC)n}*=;)hGP;Rn>x;i8;E8A4U#ZypWCsM728zh!~yvqM}UJtPp% zprml=fhhWGy|@Cj6dIA>oPJFJz4aJ31b-A6((IBV<7LvAOX`%r27dU}nwO*QKDcL7 z(8s~|p(C&Tf#b(dwLU8u;GGVI^-2TC_g6$oabA;Wh6;r@eXF_d+V=IuvIKDJJFiYo zmFj?P9%|;_s$D1&D~p9Zl5y+v!3UcB_A-Dh7 z+%JnY8GX34UOl;?2@|%6G@mF)FJPDUZgFT}n z+{@7!)~c>|zL+QiyAp|G8wniLFncRjgy4}bVuf!Pj&y_7-8`uHuhmJ5ZSh%Nne!T*iFg<&fUR@Y#_| z>Q#R1BefNFep;F%H4?%>G*7-Sz;UD&>3o2|rn4}abw}V>c^chtaSt=M$9tp-Z7|OX z;!AlOk+~7)CDn00RICe_?wj4 zwi%i}3@p26J$|w+F8?*)Prm|e8?$n=FMZ&ydSvFpks#OmNvUT!U@vQkT3eXA1!So< z#i6x4Du1&fPF^VF{q~yL!pEY*M3@9Av^oqC&Id;My)M8O)Yzw6VtJKGVTpKo7h>vt z%o8E|!do{EB8`tKMHXPe_rh!HxiIBS*lT2l))_y77_A$ z=tAy6MH}hIFz`_RX8cqTIhgV5xN4+^CV2b6Guz#OX2gEnOX@o?F?rWh>T^cHraOp3OWsb&F-9GXq&XlE9Ai_nqzY zB$8PfzLKs5by_zG==1qQBt9bybYJFQ`pK?KF}Js(lZja(uqW$a^j+_<6&)hX--b%h z8yw}uSr^VJUA~T$BDNLI%`?qi5;*w+THEa3)i|fZGbqS)E8~bm=hP6AWu@PYRUp13 z#!U3>$-bs@k`;;2YnVb7 z;j$i`BE42eC*<*9=XPCq7?GYQ2J!WkEHB8pSBW|61}Jjr5_D(T=b%@Ki_tT^56Qyc z$oWLcQpkE`jCXtc_#N!fx-Co&u zEe5?XBCyl53D23!>(m8(b^y+ADSL;mPurc=N8Wn=55_VD2xE59kz9AZ0grUr>tel4 zbM@Hs9}b`c%w?wa1{=)@@df!&ankdbA++hr${VTDA^UE^zx&=iGdHZz($b>)PVi*5?#sjWW@Vne z@s@9IA<`Ldq|-`rti3mL1i2)4R9+IQe2*9AZ5P`!uQtux-5WQ`Y;%i=(jUJ8mgm@y z-Qu5P#aXU_jVv!egx>*G%-e|SmW6rzxQYrL`f)Y0%(3QjO9$w&yHeI+Q*$B`>tt3b z_q5i>%g27h1=uD#-y^nO+}szi>cWEmYR+XMGfifY*AgwyAGcQ~JVZoX>=!vm_SsG58fhNw@$=R;iX&K7i%><&o)BE93?Uw|g#SEq}K# zT1GsJjt4V~6fs@bpWL|Qypq!(VIO{Q7!p_4BMJ%$SW0wdwhBZY?uK+svn7fYFfsR) z`WpvJ7v&tc$%8E%xsXy}1=8%TYBY-b*X#tSt(>sS~x|(bkmAIBR0eluQ)b$x!E!@1{B{BswZvhuCgb>6Hu+*)YAzSGcP~ zh(=$au?>AeNr(&wTVPX?&DA=Rb?nV(00JjW-13#0`g|bTOm3<>3WzXn?xkWCj}EXF zam$P49o@Jm+&vxrAC$~Fg7b3pGq&;PPUBr~e~bfIre;TBL%@80cQxfzUNg}Q!7tmj zxkxs%-XI7H4vR&Cwg>0pI!n62(Qfw=mzNj6tj%WyoNay5Y_5S$j<(A39Y5a5{!1nu zf}}RGq*<+GcDTiAe49TEKO9M}I5VCCb-eGrLh2uKdw?945H}uuidE=hsjLsqi`jw$ ztN2{u4r>VQIcH)U<6|sqBA8PHk}|v02sIB|$8@bMEHtv}Knw_Nx$aspjm9QTN2<(Z zNbtQfS<)w~Z9S~hbT8^nV1JP9lI%*08Z9_Br9(tW9!H-DYh|ic!%Du|4nJ$xfW*y&^mw_x{3is_hh{#d?ykeY#N!b-iq zrs;FZn#55@l`vO>XPO3A$Jru(g|Shx_Hp{o`_s^ad~F#XMc2+R&4qMakzG0`35^uO z^60EiP0ycLfM5-JhuLqhoLj)#;ns)Kn~;EoNLf|A1S~YiEyiMsi@QNn#>2Y#^y|IM zZTM|a2-dr?T-4E>FYTO+@)Goc`lXjecs)LM)4=U*VzZU~M(W&|*h~Wn(&cz(1!JpJ zqmUkM`GJ}}xqPuVMq;PR34sX+<-_R;jiuzHtJ-5<$4X7K%cK|LX?5~fk~_IA-r^PO zleKzYM;KqO#|5OEzuHIES0|y>%9Vr;eh$lOj-O< zWL5#8u33xz&?z?)C=IhbN|X(99S~^`acqXKOYL@AFk)@Te!NPJ=8*DT%(aN%l6PG! zo#PF)&#QK+%Yl}+Zh122+SJ*MxJP5(Qu37Tq{B_yftT=&3Ta zT{tFGg>&p4xQp%uX)Ba!jnD4yhV&mqv(mrzw5i{VqZ9FnjK<%^`a8(n*%wv(?$g)T zL|ApJ&=}>OeA-#04|iG}NjybJPWkN|!6v>5|Da5mnItu)Q%t$fX7;w;p$98FIRFIM zg4*~ustx@X!#!tsEPAz{I%(vq;qX`^tc*&4f}7H#ufEG3P?dPm511b(kMtQq|Ov$$bZ$UgiAg% zCtp{}<{JS@9;*rluYTHu+Q2PC!O*ZTG*ox#I+CNY`$w!rBv1WnN~Ae5`C9g!-+sc+9KGO{7nY(i=5Pe5NfkZMEC}K3M3_Z-5PQ@5(PPDg4QfME~O4TnU(~- znjcY5z#Jl*8Eacd0*MTbILRf)JY;wHrHld7n%nr-mP)tOW81lD+dBj%VQF#V$Qlq^ zoIA)rp^)Yf?98QDutUaA&~1WcvrZ8fvW}`|U;A2Mo(IHD1qB&m^R_1BdzB|`MXz!R`Y7moLPz6bchHx>0lx6| zVv7{hQ3+>i61BN_V92BY;HW|sy4V4N;A0zP>!Br)8;5(U0W^oKFbHyP0XnwzE`;0z zdS=);smU!7Kccln)$uZx57_k7@_xmPf?jE6WUoqV&c=H1Db}v`Et79derg(Rm)1zu z?%KG{rD2eJwBZjFKE7-MmiZ%tv&L9sVf-JADjF8Y@SQLHs0*my4mx zZH=um-EXxu8-OUUVeoH@7VnNAjxyrL&#mKgU3X>+MpzCP3+H3knlB@5f#8-jB7MsH z#X6_Kgy@gKeKi)4nP+GTMMkWuCGRMpEHaNoZ?0rxnYW^{^8x0${+@Bg@;%-!o(_S> zr(MtwW%9>#!9mbpc^qjMV_{%(U+8}uy#gQVUZ4o~xOcOVTUp47spM*{RZg;lH^suz z-ZgsQEX_!uDnW2gUY9$l1^m1LH|FFU+bq(=ETyy%-#Ce~&%cLB;6Y{9e$g$Hw8<9m znS+cgy)87jg@l{o*E}Zcn|zr3Rt*$*ghdoegZeQKIIDBrjRGC-Piow@^uOoRpMIyU zn47yYa1E^5jr~HHj)a=M?CY);H?rOU%n2;$PUWPZAJazh9m2A|J9E-uM2k(Z+4obp zodosrdWfCB@3)v67RluX;=tLtGa;BBq$?sRP9PU;Nev)1)G}241>Ovhpuf_pGlKS+ zw+l*2pmXooUZ}&^u6}IWx86Xmc)oizQe#%1?R{D*%mwfy#^?+(*qE%?qxxW`&vUPb z6!{SE5KT$mN;FR?Nb?En+=_JX`PCxTD>51@hh?+Jl4c(E9*BZ^*=pjO9Rrtr<_?=q z@i~;oaP0T*NbVzbx++`Rp%q)k)#R(&IV=hk24(BF?H=@WZET;ObhJ;u!aW|B7azO` zKWMOR7g;*FvP22!zxn7$a>ulK&9@z^IUOtEC8OqNCzb2*io2)07IjdBHHMxROcbfH z@4N`#TZ=mKtz7@H7bWPxYj5g>=}MLLKu-JD(T*q<=DJ{$=RcsHDgqUmUor!CIdU{P z!njKY_I-B-~vI7*>C`EGPdW?6sp@aX81Q z+q6Ya{2M2kLNBstc}40a*!i!U=~KkyRm-;}J#U&J7vI@BHMI|(!{gb09@Yh$hAG(R z9SN2)rgDyGUacz&lJ!8daw}&3V17<&8B^=*^&b`>2$C#BmFFf;5mQ#H69g=SpO?jR zyp2?FN#3NmnAGzpXV^5XO?h%;f8ega=!kW~{|i;4M}AW89G6 zA=M$*wXvyUV?@k+%FDlOA#ca+Ia_r8OuNDUB?U<<$n1c4ondBmMVX(!a+YuF{njXW z${4z~(GeGFR~Wvv6R$U@%B{SM^gA)TB`O*WNzoC0Y<%5>du(dkEo-{GMC+44MDLMG ztmJ}y`vYC_(?DZ?A>Vwio~UV(g@5_?op9YpEXw`;0VXfaf)f#-YQgYx0?l+n_B!&o zY+cAse3n|Yd%n#{17Jph27sw|qNN@VRd0h5j^q(8%fBqnpQx{WkoLfO zD=`%Lj$)8qKlG~Ay9(&Eih;y>`OXG?^Qj6x1d2h+CfMe#@-kj%)t=%W`>+q~l|s_nhG4UT^I?_o-JA3?52{7OXjLWmV0Al?_AeoGfqBxfH- z5p@yqy`0u}TuIY}dqRb~&;Nk@^@Q4qFz3XX?aK8#teCn19 zeIR0lF2^i&xUf|5z*L{4@_ODdN8MVNr`dAu@pt|R4Fsq_5KVQ&UXG(fXccB=ZHBq4 z!|;7%fo6GB#d_Q%*(SH3)5C6L)u~-5&=Hc8Q(N2V&>15Ej*;i(h066ra7ja&2v2ZT}9h&gOb%`o%lNbxvu!)Dx6-ovvt09;-k>t|V*J^9Qj$O%4iD z5tPRy7-gbuQ^fRbz~vSL`VmvRl7q1llT6pq7|v(`fA4zFS+Cy3SK%mS`&{dWRRf2f z&ikZS~NL#j8Q`wY562?U`8xZQH>@FboRJIVMz{oA{JM>kLNpb6*X8ZnO zqQqvb#3w3L4CF2>NdwpH558r0MX*c$LU918c_ttgJ)kM-hC9eW>pQdx7@%x5 zVkPlQ@FAXcJiGl&)ukMIqOe>=xs}v*Jdm&qgHn>=tUo@BWmWk5_RV5aeNY?0KK>d= zzzY4=KSYAmg}E8Qcyuh&E&aaC&g+hSJ#-yyI9F(dQQUu4bEL;$B4^F*ZZqMXzIdcr z=iPK3P!c|SEAV!!l)Y-il`;UTkmlKR*5McPnmU%wDAygAJ<0i{uMv_`YLmgrb@U}xdC z(Yr5A^16P`4_@Rnc2H#Jm>+^)(t!y~$4KNI>24>mC&CMnzT=DY;k1q&LNwUZV40Wp zRbViI+X32o34q1e+!c@v*qBNWmsz(tx_^HZY%ZdiX5`wtB;K&lj5h5MAy}cv zF}4)UTLL$<=y0gPl6a?b?Awr$K>U#qw8nRvrVapUI@MuvQNLg_9@PLG#T|tcg=~js zzR5{2J900-u%?zyqa)S626B|EGm}kb9 z34cnl#UAnl=UaM>G-QB@4xo|;*M_woK5U--{zeu^gTW6M`JKmoeQi}S^=gdrt&pE0_{=cYeit@nU~V?PLE@K zL{``?P^};uIUt5!CTOdv~R!lQ4;K_OG%cU@?F4etU7%st0cH3iZnXEZC5L z?H;CY!%hZ#JI$+&9atRa6p1HaZ>bLmpGwO`b5 zQy^pOcl;Y4+Zb>A_9GDJGlbQ63HoK$`Wr_6)z}VrIOA1TZT7N{9yp&*Ql-9tXCdi- z&EE8m{nfz5SYhOpL@{g=vR_AEo_;=C%h6ytF)x)LTrjJ0GN=_WLT=?(cB}i&`*rIi zSvS9H;T#c4ADuWJJ$;cCO?-eWdOdm_+H3N~ckt{fQRo$`?N#;o!qMNTTCW1%gH2Mi z{0pSoEw}De>cWg5)mYzw@%0xl(?<7(m9_b$>gV{DzTPhP;#k9`Rk%^wKnwW@BHR%oJkcx8>l5Ut(Y%#&rB7 zyVjN3g}yHi(1+hjPtZq9*$|%iE}962XWc4k@>9E9pZUBx68EFTWHUS7fO$AQ*-?$o z-D*}oYC1^*$hW+2BYJcy5!%;+%h|6&n>-MIxhnbpe zmcIP~Xv*~MkJ(z9Ca%v4gkD5NO_lxFkRT=81Dt%B#9EJPrFiqUo=(P(=hBCBCyu-P za#}(x0c2cBcLd{=r}(XDK$_%_6omBzxTGwa$KnwU-kRX$l8cRm>>kd8fEH7M zh@)NC4~52kfQ?r;%1TKIJ*|0y@s+p73~K{W*C(#+lhv^cnQf~+BD>@1(doKV?2*{7 zV`H#QR&f#`aeTeRC4K#6Fu6CJU&V5$)E`G?F{eY{2#;Y%>ab)}jU;U=p9-TjPcYDm zMT7P-G z!8lWJFa}#+@FrThz3GnI+nOCVGrA-Xa+NuVq`mZGn)eQ4yN(sx9}3YMTqz%%yJYq@ z7r#{~$Yl0HrjUF&L{7m5inT3yKrV=!{(QK#=Vqz@Z24NSor!}o8&9?67%l(F8UKYM ztt4jpWi0Yd&wxzvXO@2_IGjUBwlQP-DI+db)(fEft z)u7ZmxVaL~YbK z;ngap5#a$^`?*?^OV?z2Md+lFIQJv=6vfl^g}NMZlA5QPZgrDQM|4U z$_DyUuQ%M@QJ_Yw;r!G|g_vQuQfJON}@Fsk)VFtXRU8Fkh0xP$~9gaGP z+)vqvB59!qw68Yni%Eksj?5Xgpp;U*@6;soW?NgVQyC3n1q&e@gl@Z=EDoNhhH zJaJ$=I7jcw0Kd><%Si6QbpZpVryzOTunE3znc^-g2C8qBJQwuqI;!>S>RqTIBeCPn z4e3*!4}hr7h)J!}3n=RFkXH~KavuO3qkN2W_n!J7GngH;o30s}bbh<6OdX|fch19R za|R)2f{Ex~)B=!nbE8M=&qjO%Js? zI{-s7I&QPeUYpd+_lTq~AJEU;+h0=iIG3s%?(W-(m2tL;HUlXiS#&f&8S>K1`X6;< zz60C}9fbVN6qNRl?OmlQL$Ga0*`8C)N1xs60G_+>ru|MyvAQNM0{bXy^sD%(0-uv7 zGjkc5lngz_Hx(*adAVcSJPaY^SNo*KRA{tyjhON>sQJ}R+yX)*T{EbUc=z|El1n*&H3ip;_^n|%Y&eB1?ffijou)G+%q|N>%>xeNmU_TM zui=uy9iwK1iJYDGLpXj5cXf`bop=^hJXgYsrunwYAlP}fhcOl&W0h|K=zh@-umfEB zwD&;D-q8Q|jnjoSb_4g_eK!Y&)h?S#j#~?Y0zIU*2W_y)Mo%TF%_AS%Aj3YniS$Ab zyf<&@*X~JQm+%jt-cWOYkqXosm|E+CT z3u<~t5-v)-e;hzM3|a~dCY=yfyvie2lr)&@XY-pDo>Sy|$oTzn5yqtxVQ&}N9D;V2 zotpSf?7J7~RCBlul)|6IdLbr$;|IWjVS9b=37Ko?@99?>ezLJHQ6D)*I-;U*Sn6Drl~gsh0DXEe zxSrn;eT93ws#M)+3C)jf=)V)f5w`v$aLJ4SfZMaXR+A-!i`i~x5WK;M$cj$My>;Rj zU)*4?8jFmEyMjW*(K{Wl5i5w_m)$Bk*SgZMN2VaE$;gx{O{|Bz)Ql7heu=>8caT^w z-VyGI{a8nOu_6QC(TF z7Tg9sQeTQ3chf!pOZKESVM({>eoGX&$`*+;84O&1@hQR#lrT7FEdUCkQ9#X6#hDn3 zlGZ$$#0yge3(b?pZK^rsneDS!Vf4<^Jhm@Ea#}lmRW@qNq0$u$_o#J{Ed7)qAmQhz zn6Bt=;m_O-DYU~Z3TEHJpL&Wqob`O`KX%L$M|L^rsKTz`LVEdJ%b2Q!xWy=+2MpQi zL)zHo<`4u=&pk;Tp~J7;@UrLzO6A9E{BZI-8qX}x%LOwUJry2PLJ)5lq(taa0wK0j zi?0d?3QQvna`%*AN3HE1;n7n9#clX*EIRlNUr{0I34y_-ogX4gJ7>); zUwn@yft@VW<#uk?UX35hL8=?snk`sRW+Ihq4c^&Ua@_C$arUct{63=cGQ=O3*#@A< zn{K>~=LqQF%L6ly&?~S;(oDg`O$@1rB@tou_5z3Vi>J&wuLnx~s~Hd;+t=$6@^`|h zvB9B(?SRA5anhvv=CDzM7FwQT5b0O2Ky@eO(=%cH0|f>P{Q{DrrgVW`7<0Sy4MM}? zICZ1)BF@Arxfi>Sg?>WUgjCF0@Ml!pdGD(v%Jl;iF}B1+SjvKDa+x$K^1nn-X%ncDdBN99ISFKjIAI6&U!QZx_uPdGrKK z^!V7#ZdgEfA6z({Yo)!0M|eVI5tgnFHY3!1w(LLE>bIe~YWnp6&USh|pq z^^H~J{WTI9*%$M3HMSWrZ7BYvG*?mv6kWAUiKj^X!)$~ucK)Iy3 zxMcy5OaSx&WS(zvNM0*yXp?T9bbTV8y;G8>!- za=v0z@_F3+y7S1Rtl-cOaPg3)1L_R2%td97=OYt)tt;lKWHCvX2ZK1#U-uBXJEyv@ zb+zHkECucNuAcP5dv6YKj8yh;1hZu&v&rw;B#IB!$+e^u)wUZQJ$`#?4lP8-}m|k41v+HoEG$J1>voGH?Ze9e&tw;Wq{sH3}6i#vjY* zitD=?RfV&Ne6uPHYLQh?(UAX{`_P1nev~zcM&I{6@XzVwONNJ(-V!K@xSu&qO?E_^ zqP7nXYG~)aGSYUf_TObk8~uDWFp1wSn<=vYuHm&boJvxojzKvrq`^ z2$Qf7@ObB6q3op}NXiFpH)yPEa`TY(Jh{K0v_5b|+ zet%_2+sa|CZ)ZMW;y8cEtfp87T8~VY6v`pGz%nq1A8x{V`yKSXE=3&x9pyy=U>rBH z3m6Y=$)i>Js)yi4&adH`ZqmB6L{YF_{T!IBd%5$dbLa{}jkLn|n9+ zclgoqkMd+pf%Uyt0z2M}0&xymyhX|;(8&>{b!^u~jAlMrLN>lE&T+=oiE6l$ ze7vcZixUEKqp7sCDLEyqO zOuJ}>O+K-kKC>kSp z^4K$AMT*Y<+5Db({MXa3rWB|aV|@D0<{MCS1)%t&`9=6I=>fvOLjSAd|Ihyaz4X6E z3{2y{j{h(A{}<{1dEx%U{QsH$KP}up=Kt@d|4)qj$Nc|O|9_G3|9|QKqTm!o{Pve5 z=YKEB`-`0aLxBHOng7|6^RN23TYS#R!>Z_UtzE%Md5l|Ccx^#(1;ic@G zOP8);E?v6y_0|>OCze~Iy}&=W-@Vjzx^#(<^y1IuO9@F2E?s(bNkR67hC60`(km(2 zB5is5w9jVAH`qYjVq<^ICBytZ6}L3w*VNDIp0@NA{ZEnhsfBRJeXq z$M!i&VC$xQa;{#w^!{{{{?27UI4BwLm&k?ue{=Mn_WD2X_#30=2tW^i=KYP)BM>0a zpLu^{^aTk>@n_!O7`3YblmE>78>4x4VDg`Ne`EAVX@BPZjnV&_n*S`|-&ONp^ZtgK z|5}c}q2|Aq<8P?>ujTj~YW{0E{)U?WT8{rUh5rp}{!7h&jsBzXe}S1lYWd4@|KFp3 zOX2^fn*D(N{{Mda|8(_#QzAf~zxLAqd-R{3_CNZUf71m1qwou;{0pf5?&#lA^M8EF z{|Gbx-vEgWunYd~!v8hz-!g&!1QGvY0{?pp|DT=qFKYhFdH?Sz{NJ+cza091ocF%~ z&i^k!lEVPt;9ooF?~eX06Zkh4{(Tr*DzVReOe2}9BwNFN#o^Jw+*-pVZIxroh__g> zRQWc8tNYJA)vz|w#O;}eWO%-vN~q(Rn#0hVFQ~)A;WFUae?>U)ccCWwDUquwYIvVu z`KnNkyN-x)6E%#2I4|77>ZO zKzwVoh@K9e;eNI?tkGI2F{jLlA7$n=Au4MonjJP>I!7!k+&7GTFs4wyTK{T>SLE zpB#<6U_HJdq5rqb7q9s1^1r?qkO{c;zr^{kC;#((?`i+>H6X&rM$mUQuKKrG?6&>92UHUR+vPOSp>8DGl9?s%th zaFueBFyzO_>n)7}vj5PWSl`tuu|d~9!ju_8K`^EQy3om@7$c4wR3FGzZCr@aFRGpm zN@#%(d$a;Tf7aBxQcf=QE)%UUWdY|NVucBXD7HQhevA$Vw{6efR zpwtV+erOE7Higl?bjQ`!!PVI*KdZq3ttL?s4i@x-FgOdrT;F#!WA{s&a-Xsx)2y4J<|5)zL zX$^22F=No&VUN%>Y&MY1p=KdwXJ==o**_Jw)4?Ftc-X=d6BR`^=fu;8Ke6Vbmgc{< z(L!l_g0U+e5_wK}Ve4Oz-+!3IvV9yL9_BWzbq3xbH03^bozmbP#wHtwotBESTJ9?{ ztn;JbD)OL+l{hdA@WawSbl&>?qiV`?ElW9(+HS1;#>F0MSNj^>+vW=4is4rtDb%le z`{Uzd^{kV_HmQfA&dc9FT$Q;;!GqO3VNPqf-lF(^Q+5sK70Ox9YZcv$YtcU&04ZMLM>-_EQKHYa6nZVouT zI9Plzxz!9iT{CVx-mD9bB?kcQLMzYntGrK-#>%aXUB@h}QsMgwY{?f^$WgI!b7o)i zYY<`iQi|8+Y)i0&?mrPlZ_?SWPFRiFeiZ%a4P;0paZzYH7-C=!4iR1P1NLJ;eUbhB5V57cH zYiWiY^FzLKRvemrrZ`;`YQ+EkL`=cM$sv3BACOrQ^LQAw@awg+V$75HXBM3`ODW@x zKIdi#k*sP8&r5x`CS`*6pHy!(5gL0ekTd*I(<4wCZo%4cX7HD8xn(G=$WD~H%I(mR zdar{oUyo;MpU^8Gjsd_R2uQG2+~^IUkPG($0QDD8owm?sHL&oDOCR;b=-Xjlev#;I zH{VSnY7KG5D)-P|G4F&oxhdtEQ!_I&f%_8qtW+YHXWY;LqWr;MJ?8*HBVqmt<3{gO zWSHbpu<;3_hIQCO3E+KN;sO;dMFGIqVe++$x2z6JV|k2?mdgJ7UhiNE>}Ogc1|a}5 z>Cd+OPmge%TwEK#a+ON!FG8&cT+k5_5ezbZ6RzXnL_u)g?(N$DdatiAf|A=n*re(6 zfT~ozyQ?)J{{2M#ZM0Fnr!Q0zPfpk~A0GQGqcu0bnn}eKO%kLkb zWCAGq?t(jRE^IzIsfdn_26l4ZKMfDiOAE@{tOPt-VlrHy3+$s8+t<)vD+>ZP3u@ycKHgXv$o9XtG2Q5+tE;>HWn{RLv9|d~?M!a~36oZV z&P<>~=y(>x)A#@Iw8DqL_S!6}+oYC+xxcIiKGn3H?pn|YHBsZp$LoZv2{2*Oe}3-% z`8xabUS1-DtYhQpK7d-BKlMk73}qTC`{$qsCo{F#NzhIJf`V=`3+YGsVIwD@xT>(a z2jpisKS#~;L(~^LAB>RrbA(c^xC)5~mLx&gzNq2U8uJgWqDOD|pY( zVqjpfq_P`tE1va}>pN{_$elIU%FN6fdsq`Ycq%GXNANw?+^o9vX`IQW=23^qgs@1% z&^HYomllavFL%Q;>IE7n@4-jaB9O<{pd6ovZo8T_>(mxwgo?BaNMZW6u~X*B=El-V z&OjmV7l`A`BgMu()9?fM`SG;W{-~LvqM{56w=sV3$PV4A7zV&*vioeHdbUa- z@ay=nE2A!{IK#!IQf)HpU}sHhQR_sY%319wHrpwfUXfBfLQ;qizW>4bEX4UobB&x6 zlt(iBbf{mhMksb+q?q8cR+WpLVZ``CL7oe!sdwPuoly7PX}H)ytKv#<7@O);xVW<+ z44b*_$b;~4@`g3L%_$g%vEB{z7I=Cz^mTc)xOL=is3Y~mY0nq1w)R8fShldKC~+6n z%|6uyZSKN+k78~Wsoyhq{gP2}UzI;Avp65Gj`YVavh_{Gii?Wio5{D67sl9?&tAYb za?wA}$qikk_wp~JfBrycoYPIevxM!2&Dt={dgVplELMJ)8pC~LwuzHk5-R9Hjh-0U zj~7bJxlJ)QJ@88|TAZ}MX@J+0TrVj;7pbc+Wj?Rc-pM!WYpiGe4Br>n=AOPbw$`JB z5VZ1Lbb}!uiH9W$S@6^ppNhaC4x&DuJEMgiOhT-DMF=cC{j`??%uVy;xbtumGIn~* zqiAWAEDlxQIUL-pp;|Fc>EQBt+-Raad5j%l!Pk3+-<)UPf=E|vHwO(D8G7|e9Gv{V zDRpa`O1h%@^XTzciio&wYgV z;?erYmXc92&A!kz=n4vLS5Fr`jzYw8VGHylz3?^8n}dgLOmq3?s?G|H)&^D9-D-7I z^@4SDqi6;-NqWtLAZ{t%27J=|On$!{@q*U3i2N}fsrN1Zy_JjCmyV1XCQ;XihZm>x zBK2#94WCNH!@(!VJL_Ns=S@&7QM+q%34pt0wN@IFY;{s+)yriiW_NoV7Tw4@kdgh@ z50;GZ#V56z_`=F@Q}#wmBr_;+A=h4*{gM6*Oz7KcLlQTPJ=qEFem$W0VM6`Fl8N=VjQhnJ>|gJ5k4l*J*HkUUbaxdRq)dOSF?kuR3R&g12V5v$g*C6N zkmHoN(_*(%pM(&Z9^iJp&XZRFoL=rlxvjAAn8Ks@@w^ zB+g5HTC+^)FT3C`NA7RV*UM{CG$2Slz+D##o_;5m-f_B*^GSs3Ca!BitoMtjsVAW=YP;7wdTwbae!K$Y}C;d~Y4!L6vqDmvhBx0>`Ue{E%bTE`0!& zhSJ#0cCV}7+I&3cgdU0Zw@B<6Mfq;5HpeQRK0tM#M#KGO$x{Q_U@Q#_(~%&@m&Qh~ zt2`9V-c@$;+VAi!2{oqb@0%X|96T%vMm~L?CJu7x6l_xSHy1O6V7pM6$&TPMcujhV zaTtN|G(&BMDr}>%)$K&wV|{opx&;qLRT+5c_+STX)TM1eoIOWH(sh)8+;HHtQ57F%^Gb4c< zk~QG3lJ2m5n4PFYGJ&pUoH9cES?z4~AtJcnioUzpc=D-i57ZLt{os3TR<^*RP(vhu zdppNF?oID8JIHi3aCsr)NtT#{C7tB(1B#m^W$^v=&)jrl4AgE);tO@#1=I6J`fn)P zxZJ$PJq{C6$Z7@hf4Q$apS}36UV!1A?P7nqSm$Co7xR6T+)G4>ldoaHp?=t;hvP=| zFV*O6bN(mi0ELg(CPntYk$Lxi_~k_P)PJ}g)Y*j!+vq4QcVmGIjCwwxZURb-&6-6)?h z4K^L}U)Eot&u$$_q6j^PX`m$&V>Dd?@yHRg(^x*X#RX zbr5!S$oZ!zxqN}s{&O>FRAran+NvWnv0)-AdX>67ANGct%vIK9<&@zeBgbP`C{~zB@MO$4%$rj&c{kHSPJft)jje zpGVSqvOuYSnd$;mDEV9@n8S+W?+dnp$U1aYZL*>c)2qk8jk_Sd7s(5`}*44ns?KT!-qh#aC^y{0&MCw~r zk!{)X+Hfv0Q0eS1zsOKA+CydT#9;p-G0}#Nwi=ecA^L{#Hm zxyDS$FVwNy9wLV)X0?C*1EX&=c5S7y+FM2=-LF$_*CsMcMXX7e%h00I=$i6 z;p%!{x|s;04tVV1$hWa{sN})Od61)o6!k8TZh+;IudDd;MBQ!LMFiSqnxL3XjCSZT zNa}gg#`TV#bBa(ry)Mo-cA}F4ML8(dMOW4*L4CTiTFm2@3Gq2?UY{ixd+y>8esxIL zfUbOwgHwuf+S|mTg_EeU<#GZ@FljB$xJvYzkp^7J^>Sh!Q`zottE+wP)zO-Fx19am z`-S?K=zH64Ix`y4)*nnMJZu0w?vp(0k!SM7POeZhxx}2>C-HDQZ@cYxM;eIDGleG= zN2}x=5}Ih9I&&+yl_R^eL$240=9<$P-Mc)ja|o49j=p-l-hc$aPHi1t4%j9e`7tJK=6vnvtD=SuCffxb1cqo&BQ1sP66j+8)ACh^4hlDYW z1xQ!*LBvLMp(T&?j_I2z)|98r@UtJVjmw_A03}&*?}FnhDtgFo{W_N05I|39rcwD4Bcb}KPB<ea(IB&lY$bSSL!4?iA*Z z5gx881kp+ya0n;#v{kW88$x@_Gj`l)dGMCAb+M{F&j@y!p?sGw{ZxAoH9@D#Io9Kb z>#z;u>2kpU>C_v7>`4&t!VPH~-|+-E-PD*AfEELc>*U8*|A(H-A0F+d5=TLO9%s^M zb9%l3Pw3pCI^Bx*JZ`Kt+HEEGdZo={+Vb`5p#J>e;o-WP2FFBjCF5AR z!?@`198u|}vr^xR>6Qfp^;JuGcU6R}j{I5}UVyH{D{uDMm7prE_R zgz1d;%ko_}vSRfB_da@+|2SQ(X7k&ZM-EKAI)ZzAOy?O5PNcKeE8_tuINjQ*6|bR( zt&+&*yieeWG;NJ-N!mH@-3_A2o@kMjw&0yI{wn7S@!210Aqpc6~mHIP#h_89i@M+j9Ez%ae4^b`Y}I0PauRCoG|8- zk-|Sm>SCwUym%%GNQ^&>7bI!w9*k(B!u51D1}Za2bHPl!8kMH8{UXXRk|^|G$e1bD zkKY6_o#h&jf;TbUp5M5$WcRfYSE2$jqzWmC_<8O#b-XLfn>DKxj^A^bK)gTaoBT3b zlQ>T%7jIpqAto(ug=+b^92c6$-2D_GUj+}YM|xyd6THH_OePsz@qiByc+vO#`2xJT zr5qp3HenbA9``w!qt8}JE<4N3M|N;~3}h*n&szK1Q3@PXD^$e*WbBTAMy)=@UoHe%Xnz8per__mYifLNkht*o~1(K$ZW537k zzH-GX-sOzjJhL}%r zCv5gftzCJ0I$~O@_X-*Kz1qAINA%0+m^6nikxw0Pq;;UOaz-a?TdP&rwy;y?XSNI5 z2+@3Cjz*YSXLY;=@~-O2_%LJml}Csx2EjqW!TKos6=%`H7^OtfwTn8@l@>KSo=6%& zhh5tZQp9REjkW56&UkIg6Ku9QspO37l;O7j$phfjcXLBmU0OH$r_f;V&f_c)dSEDxC zjW1ue$ab(Hw_!J%v*5mNG=@kq*N_zLzO06r&qFJ5Or~*Z+dlYtdET z=6LuqLq0w*s*lRNl~}}dxccbIU{w)vpEx*@O1Gj3_;Pvr=3f+{tbNJpw45;mINWL`)(#N1?J*pzPSY{nt47u?)=^;O`g*kO-4%V*(B!Ni>c?}s z2%}M94)H9DL2q@7S8g8U`C`U{Xingq7*F$+Y%4y-w?48WK5hzAjLCh%z% z?WiZuWq%P+f)-K=44;EngP+(sVlRz7S&5{RG0tsHjdEw_%98tisrwwbbf5_}_1mUq5hQNR56&Z>;o{q`=it7k8IU+x&GQ%R;6 z@Y*l4wRYqi4o;nDfqO5hF;H-FvKq(`zc3()!pAk3AvN!4C&{&3(~A^~VA8V4lBOjx zq^*=!K3Aeky{m8#^Z=?APO^7521iS?uPw=|oG2uF>`;Jmju@rz$?w^0YeQLnn#$_V zYPn0LJgKRn%ImVfG2%j(Ixu~!JKRr};Jq-xJEHcUo{OrR*Z#VVF|A>x?GR88(CeME zj%*F3<|nhOz2oSunkL2z)8%Iv^;lo$5-y-j{fO17gXFRrRUk<-II7bBaht9^l{mOy7^Qli( zdaQk2<#(iL`%9l1a!9;6!m>QYhoDHs<~)A4DBYDPuEY!@v_*@4Z2p0KHzMM z3X^PU`?l>^?||lEh9EEVtH1Qb=_)XF5Sb7pewX157)dHBODp5MCJq1hous0y^(38_&+~~ybclv8d zUUK{C*th;xl7eWQ+lZv16LEMZyaSVV!QuXvQk(%|E=OPoc6#5I(`p{IU>-?KGEq9X ztTw+mDmk>(i=-4hN0spi;@(Fql}Q0i5U} z`r@cDYeU3CDtyk*_FK>!<5g0Cl`e2062t~FAakC$Rf*vYqa`6*dV808iWHKtXIdiZ zxypvaOUjaxn)<>9#s|p_;Q9u;;87I#>3J>}b!(fK4pt~vnGPx&*TLo~VM;-|lBUP|c7i9<>0d=9 zSUWjd?r1lLgS!}PmYrC(I+BS_q1625Pk-Aj2B9qUiR~1mZz)aOS7^{HXl^bTS+gHy zI~mu4B`K2qjvIz)C<=bPzP3Y_Da1O0i`t2Z`dR&YMu?gffFGK(D%re4qLI%;47 zrLbXkOPXQF0*7D2a1#1M6`~1^Q-a*c6vu!p?4WQ<;9&QBgB}Ls8w&xtn1E={7lFKb z<4y?^LXS!904Q4dOP!>h{8S^6P2{&3ElIOB*l>nz@L4&(_gl`XN1+N8x=NUg4gJ;wBZiX>|-7RcRBo zs%1NjpV%H0j1N7GMY+c{cvN~Hz7J2uS|u10Z)PnD1=WPd=F?9g9Sw?l*1B$-g~BQq z?llM}ihb?8n*?56l`5>(36ZK}^k($O!3Gw66$*N*w&!`*dfZ;83gHW$fG17O&bfCp zo(07li#a9W;~mJ7o|O>;k&KOEgUR$sEJjLpllp^&_{L<1FqC;KUSgq^Czg7Vh*7Xs zKm@sAPpw>0OR9dLT|sYoq)MLBal6$QL`d@^MhG8v0t2^btPU&f?}QR>yy0J{aTzS` zp?j%PLsob+9w2aQR$j275b_NBrno0K+2aF(Va$I_=(}2p$%g+IZJIY@eqhtH)>xUY?i&mDeFRqpo)9=$yykctP*qL~cPWAegRH0C_ zW^vVC==9CjE?pdR@=bZ}cz>o6o7qVDr_k^$uz{^N@^D|n%kmzMHGEFU{xu=exw5XC z`L#~_4IkzsZj2c2WkDP>Yx(2UxHL!OIi7TDQAW2)(bhQJ{fyApsw+<;}7{|BbVe$Z-F`jBzaL=P>NRqd*7?# z=pRnCwPplazOj=}vJ*k*T`%)tbMe#?bYR20+i8nfvXtZwPfS&RmwQpzZ6AxWaCoSMz?ry$gvNi@g@ctu3q~i4@CS&OZsG; zLb>?HSc4#+z!9N@8CUWNj+^i7Ojw%nsHfULSE)}9J$y5bkAzrGk<1lbxn1!(`eb*) z+V)+MqhXidi9R>m115j3F;bA6UY(4-z|wt=@EzfYV{M{RR#sT$vDtZ*jE6qIyyGmA zxH&vl-oA*|egET})eY&5)xd4&eh(STjb6E3-dsw0VXNerpJP?V!4KD6 zE!4)6B?~E1`F{Bv?ZtC$zrqH7m@`ts%sR^XJLwaaOIILPy?O5rP+7=4i>(5=5lJ=_ zHg4@@N-@+<$gc9RN(v~V!t?5A^a&ricxXvgQwEYalJ%`E5Wt0TD1$JF?HRrQQ8)n9(bMv^t!AaJ$FA|LB{KXtM#%;M!` zz#ZKK6+a6XP3jeOSrZ@tQv-b!Y4OrM4}iv*4WKPYkcGu!d$tA8(N1h>QyzH{6v)xR ziHgWQKJ3fk1-GNKWES!toQgMQzif=XN=_kBq#P~1lEM_BY`-+pm$+HsLiqE!Y_#EE zFO`I5^fUUQ5$>4dcSDuDOeJxjb*A`s)u39H#k_^WI0tag3E|ND!e%%A#Ih91(=Qv# zr8Zphvo(RLSQ{N>8E->5s-U9ig7ah3`(|}_;oo#wVFs9%xzx?2f!YYZ-W2X)t;U>t?CU&(J(iCy9t^+aXqonzVB!~cZFHgC?4mhbV= z1Nx{w2UGA0C%35*zlCHvb{uln^>g*nm*!eQ((*|R@8WCcdoRr+MGaiKPVjR%Pn6)} zqN{t~U^!9mh+5S0ZTOdNxs=bxczLn0c`-&~W25okDT(S1 zkyL*&{I5_aCm*0iZCJS0`>o!=$mY@704^0)q6Telb)n%eik)DuQA4tZ(n$Qu zKwk}QxoIg{U+~@*4hPy09)2kh3F^LOdjs&ujg3I7luEW!e}=-%yR_^c#*Nlw5>?M; zmPBcmqU_#|3Zi~d^&B;_Eq&bYI-_g?=no5_fe}6ex(0FUW4nwt8@74+1|xoFb?xNIlSj3hsT2L!o;oS7vxX6R zW$&G{R-y=+Y4u_V7hkd<*-C|TuRZOZ94m09U)Y>6|~7xF`4Vs8AD`^ z7SV>v+rw8)m#~)dpzp|)!NuLsBmo4(v3o)-*%;{XQ*k0-|!cVZLcmS zcDn0KjC+juR%I*ITe_xqg?W zv^%Uvb(q}vQA791>`fZh#lVk5-&$y^O;zp5h+?O~%*Z(rRQf!hZkSrEtsasT`Si`LBR5)8 zs5en+z$>=FM4`jOdo$DXEu{;r$!}mvk9uBS(nsgz)%PWiE^AZ&|rM6eE7Cudm?djf>DDTH(cu7eH68 zsN1H!8LdQ$@}#kV-BL^Lwp_|*Y1MD|5Aliuj^c{S>`=Cc4w`1WltL$49X$injqqP$ zZZ5DnqiN2{WS(I#PP)D?HUB(!;_TGm^jy+dYN4ez#qz-7Buy)|YLn`Gs!$Qa%FFp* zy#P{R%?^ybGz52v$ouG-vD1APrFd5 zokmL-?*5u`zbD)L8tZ^){vC@< zp9Q6zNmCg&$e41~L8AO-;I9_+_sF^{g6q?$!dd+y(X~#65Q;m@p!8Y)7wLu)K{zj- z41a9WoQ}>Q&jX*+^Rp2tVSe4r6!_VHQ~eXiAZ;% zwR;}kt8u2Uj|*qpI@EA|GH5mp%$66DObBXX5YJL1Zk?;eoS65&M>cpjd133swt z+@K+kK7fRpsn>qaxobl-uK!Ghc5_e%SLvfon>xX8C@sGdRE@HEoH?X6ox{Ee7DNuF zhM1vT22K~QH@MNbxGN#Nl-^952{zr?Xf0hYpAN2+%u5Z!wNp3lL_UpyRoUiS`igez z^nqN@l;Xnz{GY9o+Ta6`AEMRFRVR%jt7=!NzBvrXsNB(qMmnk+OQiO1zS&d!N&U*u zumBb;d_iEn#*>kgSK5#Dui^BFLh|NvPFlV>-n8K7paUtQW`AqV-?kr?QuHArbg+UW zg-Y9X3$5FIoM-)-Chuw#SG_sLSZr<$X*t!q*{)HJk$`&W6;qgT!7OnQXV*qPNQHR~ zy1{YmsmGg-%c$7xoKl}--OHoB*B+hCKSUZi=F?w#>`4bIF)BV%O_n?eNK~`kyhJ1V zS$|hB(FH=jD`>o0V-Cc+kwnJbeEjG~ZeL4;n_*wyh|u*|E_HzHcY)X<5!>vKQ1UrQ+qAN$#p&8vrv zL>JDO_k0jKl#%Hr4kP)KUPTj_bYl$|3uAOO!_&Sej zArjMRGhh1x#}pzAWwYTs_7y4DmC#zebN{qxhzlkcAG$ZGFTIy>`+_QwZdFQ?OvUc@ zNwL+SQn(<_ORTnT{{6xncA*GaaPE#CG6ZR?<(p;wtS0ZQQtmbbai=AQm35(%}`gU9#bF9ikKjf4d-Fc6ecaW zTR&5Z*;!Bf9 z#f=yP$9I4h2A!3P^q*)`5D`3b6%sdW0Enl3GJzTBz%PLjV%Yx@d= zsRg30a>&H+H`>#17rHrMkRcH5Sd#P;{rkj~F7=I+_{JQ|k(wHZA*C^br)2+2Q zYACqZPLjgm_aJ}L&WI9f>DVW_JHSZ-LEAxV;D`h{7s4ppQP&pa$;+P{nBothSvdjC ziK>rUI2WjVD+=EXMj)YO`RjlQJMH*JXt+l3`@D^9+mpH3L=Fo5X0WnC=K zN69k1t3jBpp5r$frC7<+r3D~3xQGup5Uv}TN+5C)up3_gl_s;&r~O&jv%UfD%LUO8 z8qGkUexgmz_bDmIq5P_;mNHVj#!Z{Tc^d}WNqXw8Od6P=xHqApCxgGw_~@R=xU*c- zF1BG3W5|DaZ(LA!x>jDRt@8V)PnYR~%DeLU5uS{?t!Awsz9_#s34T@~%HV~KkkJ_u z^k~`YFnmS-7~Utix|L&4scA#&B3qVreh1{X{mdZ|vr{_%k}o`8Wg#st_P-*H>4|w#(o3VKf%z4+%@UsAxThP;fnY zVn0@90fj<=lS)!Rzsf(XH>jWzBgkx3m&ua+A zGg?gZvsAL&=MdUZOC;?FmG)t-g{6i0LN0Bv=AjaEnlOu>YUOa?P?MJ%1s2lmHm`pC zuuF}0fzK;a%m^-1dm!3b9VR-+L$80eGlxrCGgN(eylI<8kYT8gH=5*v8Evt0>71-{ z!vdto)N{|3%vhkB>?a%~>^UWD>msH9EFnoCN`--GsoCDCs=;I|Ueqq<>U(iDH*jXR z=e!oicqCTVSbK)>IOeAsd|E|K!9|W8fkeENEJR9u8yZY!q>&fz6c*j0_lvHucs=Ny zq%$EZk22$gu`14$dLJBPALu8$_X z|2pmEm*jTuALX2A21Jow!;dJbQw@K*LvVBi4+r=)9ih| z7G0k03e%Ww8~`}8mCN6SAxRbzFM4f*=B!_7N^;3uYx$m}V3#u~5yW%T*c7s64R47n zA%FWDHET5oGu=?HwEIw-t`jB{LfY1QEgO3SJ<_NqQq)hNvLb-nNNh6jV}Upy->~)Z zu?R*EuR)V>cHDiW3&CR=o66!fX5h$BCNGi;Qspv-0&TJ&SPv-5_dLO5C`1DN1*K+f zc}3a`2(2RFJp9-LA(6q}1EyX1Vjw9Zwa|!?p#t?hqdg?H;4?{CG1iWTk7Mq2@wG25 zR1!YkaLpu4kBgPL)oloYtIJ==@`DJb;h$}0ZG>~i$OpEP@5DWJd%{MK+!VD&@-8D}|gGAEQqNN~=& zP_MGAtc>GVEiwRU5`a`PYd)9ho#sfEX8n+)X8+yayS14H)I;}s+Pyu~8KqkOHA!>q zmk(8T@RfWNccOHzP`<&Ne%NidYZj7u*hz|Bb_->-a$Ckqga$R4MTU(JHonzqvM(Ez z9mNr(4@xG9!WD$a`U~5-(GG=Ks1FmGDnI&(<`fRtT&u7kZSsk^0@&*Jp&{2h`7VQV z+i{Qg&W^D{bIb69$q}HM*VH6^VF0_W=z$jdEl}Q^^*1UIkiRq={)o_pM0iZhX%HU- zy@j8fUSp%0B?KjqzltVh?N~6^IiSQb`8QF67Frr?!bA99`BNlTAza*-&&-2)VaXcOS@u6AhA^ZS=d!jj+@b~D z8cH*guZ;zI+{C<3glE}jmp$gJUtA_SOw>_SH@W{*$cmqSWEdgiQA71ec*ZKJb6Cwy zv(wgce(Cz`^19@_l7`-jD&vx)PAXu1H723RXR;eQARAm%?@i7*>v1t0SN>H<6l7o7 z4yvIEyI*TM`lT;q_FeJLo0_>Chr)sKXiio>>#M&iRvIB3z2QH#I)5mzcAf=!CUpXF9$~c|k+lgZn_Z^EWc_v* znYG{3o-fEdVh)*UZrmefKwut%+#J$FZno1Ey1)2p$AXX#49p4+ejR!FqCaE{5*5$@ zkg^fNm=cp_pu@@Mjmm1J_aVJ;iG9v)%+BNi4@kBJ#AA%hS8jjw9gW$kE@vevG3P`HjIKb*E+>EGyqCx zr^iePMueXy2NU0IrBw~?+2w9;l#<0Dj%Ci=;Sr*DU9R^U&J1*XI@T^mbtYWvbhT1B zYmj}&41^sNidC}6*oEX-4OeD8qYlaqkrs5VDD9uVHKIey6>lvXBBXRd5LUm^qTLuS zOsw3@AqN3RG=a{L4;S9%%-1Mr^taDw*{`nUsCR8@BITP=MW`ox{Y%Mwg!NAz6nUpn zE;;HJYloPL%!DBmW5bWNc3Sg{mn}dgXN8IWkCWec=Q~fLBYcerNI)B@x^9Fn?m9m? zx(mE~;UkW>#gkvG{n@5+VMw4Y+I>0ApBgy6tn&;BoJ4vU3=-1Rz_{Oi?)Cze9*_Q=3-CB*^_U@MA!1PSw`|Jgt_GAt%Bc=#k7;O_isW zqvaAqPm9qqhbno>{yJy16><)BH`k?3=*?S2``=J3y z*H)lQsRFi&PY_oH3K&liQ#q%?H~+bv%KI(7z0a~!z4iJ zF22JW&f=Gs+K^EX;JtSstSPX59R780B{5)RQ-#2LLL5p_PmGI0nRS<$!^C|Ozbn8` z{<9f)J*DoOmc{z_^t5o7{N?prtIu>BeO6yppRfuj`lNuH6vPHK&T5D7q`ER^eGy2l zfDc(hCElgB48QF+{o_A~IfRy@Niv))9TL&8(M~T8htKwuT z#HjDS-S(}eZK06+$nFo&=HA`C(o46vf5qYKvV&`$qIJIFo*2}E_&@E2P<}z6;S7WFMO{o+Ye33c?b#_{ z*`PtI2PEZ`%e*@#tDAJy}g!-=;zVX;R<6%VK3eIl4W?V~1S%k4QuVp}`}4szMOJ%Ez1&5Hjn z5JDbexsGxAxz7MGueD~gBnYuqG)K*MPS{G&JLsra7fx3Ma>nb&b#lv1lQ0IUZmw)I zBMr_gFCLSR11AWq0jY{>*ktN9+xea+7IJbpXjOeMm1#45!NEiG$xJpFGgaB(^#re< zI!Wk#ePOMOzBq57ps~Ke^hP7U&e2H z^I|{KA<{}ic7==?7H~r@XY>q)GV)m9N$XmEv??Bv6MGFum0XWsSbL*Q_;QxK9oNeH zk#q$vn+}n~UEZ{tU-C)a3uW2}1kr3kEM3HvKoJbJ9bXOwy{S0LP-g zET4WdZ`xPIB~Qg*GJW3{H7IxiZ9(2uN`JykD&&X8@_K%#Pn!dyOQr*FlZ8x7guYbZ z{g@jL4dJ;bJxlU9B^wM65C-@yEiT7Tgjjv@xwvn*h-s7u8YC62SSQ8`uUGw=eeh7Id&RW!{~A)b_3 zXk&?@WH*<#R8pF(WcYZMNl#{P3v;E7FyHpRWt$53ve;>|qFP|dKnFUQQhGfHYWijq zs5lK?!f<+5i6ujvzFkBbW!K%2Up+jzO9RytBEVT5}Yge8i_b!!7)58^}q?7R<85Fi4+5@+KM z-73MuNM3qsmc&e-ougRwC3=;ehs50^VCn|HA?oZ9t-<{ycjOGIfX?&eshnnoz#hYR4|3O_(Z^#vSc&fR0M3QenbC1>n!Wet7FI2*N<{3<;6v)%2Zy*$Dm~EqSI-CEI~A-Em&@oY2VcnUT{zs@3W~(ob{ev?M2d3&z8Jw?gzf+7QT^ zl1(5g#<5h~=8!UF*Np!Nwlp8>iM2w@egSP1=VZ(KO%9t}IRWZY(H6TWa6pB+6QCqM z+3@h!a!{?&o90d>L>v0k>%m~CuebUc@+L0IFox_A_0tOEef6I~jT|TEDb~y%zMZa? z+KFM>tb7hsM8;p@ggTLG_I+I*eLz7)T>r?p=j%7+GL5c)xYu(DxC35V_q-JIi@(=3 zg#bk!_HHCJfjcz=?CD_M{=FFvF(82t!&yt;#*kpV`S!%2+EC*TcuMB=XD+F-%B^po zVh!FHFtec%qChA}v(2vcJvAWCcTw|?hd;aq-a$=Oa%?1XNr``}Q?Z%<(}{5;A^j|h zxwWhsOsZaHBIe+((2236aw6FnUchHzK@?7!ww>}WYe{B0=;>sYO6SQ|Vhs%DlZ^`4 zurZ$wP||x@BM$MMLREYDzV*=Xb_FY$DA}@#Vd6I)e94Qp*)E_ci}H_qKm2a`?yU6A zj7GPn6!w%QaxQ$+BCU_tmoS(qFTK>nLpoR|+P*8_rq-i7J-&oAjjwvSORp#*C>@;v zdFrcv;!tKaez;uR;{jMcKtAL@P5*(`>St1!OIwR-JJ&zTjwiDpHcyPC?r@ZMGn$0T zth}kDcNa~`?7Qi*>!pW0ooN~Sh7t+KOR|48^(}hV&!C}p9WLrV;8mP-Yv#4@LAa{S z4pU30v6@xCN1S^NcRdqF@GV^&0Am06?s@Y!mIMd~Zvw)tLeWjSt8z&Ykkn;H z+%v1x!-Wuu6c?-=_d$LeVR3mQOEJDzv8qK29)U@Vm(YK~Ih+nSfof~m6i(RTdHHiuYFr6y(m1`=UhDzNaZmVnUfwsvnfy175xJZ++&xdf`^{F zVGpl#;Ovh20oA*`g3gwv2Onv1t5TXCe|TmWrL$zDPX^}$0@=Q7 zizT%Fk!AcWPA~a^V6Q;9Q-plD9a(?hpr_jIRkJN?r46+Q7mcf* z_B68P$4XhrEfh!1#?!=1H!rIa*S~hnas65hj*8a8J#%mLLSVh5_1T#gv!i$qnaE`lhb+dp(nr zqd}m;PYvW<2GzM4I=)4BRbY>&ef6V*$uOLLb7wD1&GU*nDy!1V$LUv3QfE+Lr`B`i zBj~`(b|>o>2?-(5x~10oBBx9ved5IlBC;t#EV+B|z)zq2my3@%MN4wXPt5wd8^cn_ z9GrDW*Q<;6?RnmL#xd!d-htC!8CyUp```-pYW7}Mv}SeZx@4wWuHqF8^B2`7$1g6=iN+Q=K-w{ zv?y=f`-GV+Oi}0tjam=#y^2l&Re8d*-H(I$HJyc)t_^sQKUxK?KZp_fu_bD&*6o#{gs_z9%0T01KHNSk@A)M(dN9XE0Y|icD_Zdf$9`` zeV{GphLg7$uku}ebBGgkyep|cyG;^J%Y{mfCEO!WgIob^=+(w4tthVE9a$8Zu6l&? ztn^tF-i-7&p@U8j?-Ciq18kJvS^<5rAfPV_IBLTx=qC`L+2(AJWEb3MVjWy1+>EnD zL=fW}mW^u78!2k8%N)n49fG+MO>PjiP3;U1gt-OjL}$xK5v_-}^UjThqExNMUI?XB zlN;DQcC>$-=c&C-^2GrsPO3?{$y!>j?p)OGwE$nd`bOvjJ0eba6#7Jp&AsSPA-mCB z?n}Xz^QMN0>8zid$!f3nZ~e ztE(>@Ni~<~BegY5C{9~-MN2>>GDIgVO3#2Yzc8hdQrUrA2PMuCie5oXdBS#s&fe09 zq%l@CY_MQct0>6}okFwe8T(0Inf~hm-*|0tHa1q;oPtSQU>z|Wg!Dnza0+)%_-*w} zJMLTM1R{Y7CHF+CFQ_giQgriNT{XLuk?wzQl&2I=6&)sz8UaA~wD@J@>ESm5%#2)l)af=h8XXqH5(c<1%ewvN^g z@7BSqB+Gy>2TxzcHKNNmo9;^;SsZtp?dA=B8!@I3+``op3>hmMDuQ-bXkiI>$gXN- zE!}k6Rs(A2PFjW!yWu;pT?3abQS%C@^^5Ln9PWLP8Y3)tXxm}+qZKkm$dwA(WwLLY zhh#P?DIB%jI4kV5_jIOvFPo-lc2L)Y;a4Ab|jSQfS>O@8L5u6l4QJWS{0^!nIb!<0#7*A=S zAzy$9R?2wCTrFB*4fyn&a=tWk`Au;-U@#E&A11696e0FejMDAH#u31mEjJ`dI(c@z zNk%-ZkF8F+IJ|MJbzvt{Noin*YhVX+;6S0>^5I04pHiq1W-L(a&vfGpnd4HGjuzKS z5hrwsZmjsNu_y~%h;F0`o?r&ydb9w`?E$%|dcyjEq}odbW#!rU##WK+v*XL~;aHby zlY~e^lPu)?Q}P)gYlc1Lmitb71Ds$vaLOO14xb%aJdo^N;O@DZ>%Cgns*75d!lb9o z+^Hk_R2LXl;WooIaHeCcCy$VJ6$D`n8c-fg)_pOy??X3h0npjlYiAMW4d*12SdBG8 z-Iu-;kze^Cs5R=&ERqY~$JsHOP*&~DejV-LA@^AaV=Wtjil@M6;G83DxREuBQ!}cq zTNWsyEj&vaHn0x;;HMg{`02WI@^^ae6S5=R5Ix%o8jJ{adIsy3}il+ydV9EOrnFP0KK@H%+cDhyX>`S#zN9 ziTA?1M)C{l2Z5O1Ta#z_gRVK%4VAqX6k)fEhef?~z89O+O9(hBU*5}qEV&u*X{<;N zsJGemKVxM9~q; zTOhvJq4q_#%>LryfwPxDpc}O_1I-N<)#VBy%~aVfhb~-U%;_wvYqfQZO{Rw81Xv3K z8og6yZS)0(f@$LxbJ`lV`Qo_#{KK&*qJblrXkJdKO`(TT?U{0t-ceJ9sYkj`ClX3N zlytUD0Ur&m{U4;(G~UwrtSitIRmGBa98+_u2i;+XQm7m|u$5##)H@M_?$ja= z)eJA)mFFF{qZXyZ9xrO@r|6M#GbSLol;${N52=#pFbsLl{?Xsh zq`Ks0Kax0a$#@cH;DlEIdAD%0%s;(3H0K)p>#%%kB37QW*#}F5n>_buLsT>Qp*ok2 zoC>V+z1Q)iuLof4s$_g5vy~w*;O{z~bC`k~rdIO$2pS#X%Xc#kWH>*M*Xm5a2{=RN zNFD|B?QXpb+vBJ>)m5D7N`7oO^dX-}Pw?@~d&GU(EkQhPLbX+K7KEX#n(1VDpi%~M z`XE%XQ>@LqzoP8J$H1Zr_M4V1#-s&;KYbAZGqxaRxQqk=h`j~)o zl(C=*(&QaCoKh-oeCVI_VT*P;R-*idXi4Q!yEQe90PWT75cxFoDVbZZTg3g1Woz`y;g;>m^_R9mBi{7L@3%vw zS!MCz{RPVqBifpKL8hZNC)ZlnQ>?WtR97YJl=!RkbRRG``FmvhnMUP3wc&YzxlU!G zuvN6wmfEMm^_7XPrhUS}UYw^U4An~PYKg$!c4o36j z3@+fV6Dpm=ct|wa4jX4$>&T49_*OWsXieO;CtRf)ZaV;rCRGEiaYeN4Gg68hrgQQ} zUH&MU>;1|+Y9e_-j6ml9&ZI0v?OU#XUW%7Y-TD$JN?~qp#=g%t!j7lJ*_y|HJihVT z=_9f7QN%lKbfDlRI>^Wl6sbt2#X3BN?P#~V1(5f%*y6*I0 zWXW&EC(Giok6)6T$Yr*Mfuf}*34v<-^@>LU$uu^S3%fnU(2|hV@%F<{GC|VOC3qc9 zhQY*Y5O~@CE1U3xI~BA@iVZ&?<{DKO6qvi_I(>JoEyAkZYU6zlS%tO9vr#g}ppmnH zYv=$YT0`fD@RMO(nTmDF&8T5-1rC%+$@5W>lqaajfA&bUcWt7(E1iKH zl{l%Hk~qB5+ddbN%+X_EF^j?Id1FO~Y3>$i*l%pGL#|+^`~rnS?$OerSA4Pp--*X? z@5u-dQHTw;S-uWhdEd}W%c_t+&fkkGfVy4t!v1+4tr1#8fyj^qxeBS&a>0yQ?4uaN<10qIknJlv0(%ot>^W4+!U zt9$2`y*AAD>Zuu7WRD9S4cwPtdMmn`IghA`O+Dm`x;SU2T)Y( z+SpsX`-O?^+f6CI@YPW4al*1_2%+1rDqdAEDaaz%;JyLb){KrKdF8GfI~ zhsPS6p+dSmQ3u&ksDvj5dF6~5R9d}$L8SIxLc zijEP>F-$@E(WKg3;Rn~@d`SKXs)W0Ghge8^*ooo5QqMHxdYqR5$NjDAs*HM{_+!lX ziZDq5*Tm~ewfp5MGmWU1N!B_I*G|F|t#1VjT#CAXwLNXK*)YKsp>CtoNoo|=iTz0^ zfcSUgLIH%zR2jZ!5%zAk&_)-k^iDB5vZMZeQC54v#UN?u;CuNMD7la#$D)5d#a+30 zB$1~~JUl(zOrW&jIItD_8m8+VWH@NupKEtn+^*BIX9uZYNL z7k7&fpm<^Z%lDmR1=3ii=HCYCdnA+5R_0|7K4CkcY7cA1+d!cbZzn^BJpK|vZt%x1zH(PzOvPj3Fls=90N@K z#O-Foq|cir|%uON{Rcz@L zq9!*E8Umh4_1pl$22rU&brRlVtyKs9BJjk&%?Z)i2U zo{jQqD2FPS!7~vy)C1cVpEsyLTm%OG=Sx`O1`qYS8G8beOYAF0HqC8eX79 z)Fi03p#0N>`uRZzcrCq-PVFucaf9OZk@suL4d<}I&ArU=5?3E~O|*AKNh4S+-^AP4 z57l->y_ea_0!}C=mEuM+-Y5pMxzM%4qv82^(X7{A`%1sRWwvw^$-J`U&BB^HfVtpH zz_}=wyzOnN%bt}PSssutfCekm_ zizb@^{(M}T6u0m;dzak=e*%7aHr7gRtombe-aSU%hvS6oL>0Y6fuf$|@sRGNF0Gs* zPzmP)ZEcF!`6I^>JSmykMjDglkvp0YAz>>?E1N6hX`Ei~IYF$td~zSL{6R7f(5OyH zw=8RI!#I}fV=^5p4i^CwxDde;WR>`Fv`Jc6?UVZAqk5C()bgqPoTX9KA)uztAu*gu z!j+Ye+pOf29kiKMTRw!~7o68aR{Fi5ep?lf2Lw))sH9}F$Lj^7AEa7qbz~S7>T)WL z=u8LTceziPDG=}VUzc;S=Uw2TCV7w(wkD{c0N(NziiyKSB8Zlbh~UHWlRIH>3okw` zYDv2Yj{D5CT)RkA8_JMR=PVv7e$g-7_*$@5 z)~MaAb8?=ZAwdGmaK(L^ygOIt2eDCgII!Ev651>Lc;tJ9Je25UqQvVg(&vwiVM-qYBk#S1om9 z%mce_zK`>r_E9U0j@BxhtmiwmdrMKb!5_fPdnNy%?G(k`q#)2ex_QZG3 z4S~y-izApg7m{g2t7;GMEcfSFoLuKK+}hNu0HkFM2#L+f)2L%8HLgCDhJ|(A;Bh}W zYu(W5?WDQ3-=w{eDG-f4c6)liKZLtT68>H!aS4ZKr8%lAj$4R$PDQaP174e1k04C z)){BXA=So?xkF~dGs`-?gK#X^jkIJlz@F85Qzy0Ju0@2kmX0cU zM1HvwJ`hux+nu&^VH$DqJJI8BZFY;m&kvE8(1t}Kx$+v16#;k3hn$HI?7^dX zQ2gP-25l3ChEjJ1t=(va)}r}n;;$zr9Q|c^{WWLa!A?)}#gt;Ng}b~XiJJGj?an+N zVyGTd;ajQy%lE>Nxv-yahFAxU_JbuN!*14{> zziMY%CQ0^IqB&t@B%9RDg#olJTH>i5{t^h)u2N8gb1pP}Xq(?6NL2B@T~snBsBl_S zi9B%trVs9G;xsXFjV`mg$^A0D4N{7aX_G+T{XE7VS%#e6Jbm4OOr5Y>RjFA=bFq!w;_i(D zsPECsaxd{KJ;&ngi`1aOU)HY9TcMsOX9CBV;g_mh$Q#=iNPxXz~`pa^^M9NS1RTlQ*fTzWBt#1yj zI4o|nrSaXq>@+$iSF@Cr7o8j0MDhvIrJi3l{4#jRhx6c#J*@sNY+TrVtw(Z|>r5l; z)nf969S9GnKW{ElkQLI`sKlZWTG0~tOlmvM{V<8*uzqFMgnR-xgGHabhih}|M1rnn za~Z?di>5Nyu2V2*3KU^QJkQLc8!}p8{=MP~q!!_fD`2BMSs|w->MOt6>h0d`!k2*) z9JM=cgaWBPHQ)9KUxy)A!tptkLD|a zSuEsW*WjM@4!rZIDNv%J4+CwQGRgA_3zgm|YZ#jAa2GO`G(-TMublzFVI>20IP>pz z=ifO33G#UiM}Sy(w>K|&t}GWhY{!zu&i-I%GXlPT%3^v|Z}$QW%qi@xHn z_2aI7#a$-2YUZIIITv#Iu+Wlrt^9-A+rp01gNU_e2j^gu0R4k`Lj4Oc`r0e)FTNTP z5Xa7ydKkfLj!Xf?3Y)=#eK!-$!G(XQuXWhy%^NC^-}m9%FT)WX01Tz6;v;i^NekAD z1yJpvlNHYzc=j!=%RYQmq$TriLpRz<1HP66{Ll_t;?%uvtMI!8iIWio-!uZhGuZyApWKM|4WPi@CZLH{2>0N`~TA7Z)atCEj(y8 zzB()ezXOS{1D_SIL&K;(n!P`%0`v#6&#(OgHH7{^_W8VDpqA0dd_M0NC`Yt@IG^_m zlo0wmBZpSaM`R8{0&G3Ja|KFtfvw}|gg$uVi9*aLv{`bf@J@EGYGlBlUU;A6! z{{eIUB0~PZ2Vedo4F6Lw{y!Sf|0gp1&*@ENv@7~kHU28~Z&RWF|8x9r)9@!?|D^sD zru;b(|93I`7wqnz2H{WYZwdcL!1=2H$=~MSKXXCb(Z*%aU vdYyk2zw&Q$@SjEx|CEUTKeA3N!dOO4q5kGbOp(BkyB}WbIDcYMe-<}rUaj{F~zlj`2f zuP?S33qE}Kp{%6XRfDsJg0nuJtJsyRwsy_`HxzbtTl;QH@N z|4HJ%GX1YfU0cF`J?g)Ja)Su}#nb=0;Y5mxk08BxYL4LYRBXcaj@#Y>poS#S|35wj zF=RK4PQqI!n=7u8F(nCmv5=qg$mwT9du8>`7&qfQC5;*&re_TOi*Y7xbns$7KEnrY z_r<@p2KR(bq`TRE*n0J(P)3MEM}Ue$N@THYekaO=7nYDqxTvjJEQN5 z&mi>tp`ykhP(Zu%O{5NjY=fS^ebDyxx0i$Lu8bqUMX#jd{eXE6Cngz{8T8%@%~d$5 z_{v?t^`z9K{?8+ok({fXMH8B%nyYEK5uS&Cu&kXE&BmQKco~~>HmT*We=+ISjf5T* z-M^0MqqqO(#5ZZd_NSYWkH>M71h~HZ_hRzv2LkFI-Q)qXrNi|ATdQmNDegEUf~7Xtr@ z`bLLQt-|eZ{In;IhKGl_^r|@x>Rj3*sKY6^vakY`=hOe=H*Z1Z%F|i*MxVnfD_v%) z9eNUYFoz>b3!WRPCaqt{DJZTkk^ac(Dg>d>?6<_k#H1uq$5~-J@N>5NN#2nEJ;td3 z^q#2Fch`r)ABxlkG7?C`;NV@DA4r1NSy^EpscYyq`axu&}T& zGq-nioHrYKECmbAerT0v@LgTt=OPF~;WFQ-9Q#`3i-r05lVxTdM9By}i9PH8rQFr$IqMadB~@qoaq1hY=AGoN8`vZo0Zjn4`RO zKd(#lk%X;epfc0{+SBaT6K8k!uyXH{J#h1-TX!7W=R3sxU0t51OCjL8tz6*6KY#uV z3c}&oQvfbS#p>n$q6`H!xo<~WqV9Va?X=*ygoN|gl7U}p8n3+wv>k9Q6`|5Em3A-X zFNaz_-_a^D6u0V6iD8m=L(Vtq!5t@z{4ZrG4b;iqb#qcRGZI~YW|I!Ek29Q|d;lb* zQ}|G)<5v|(+P{_T#I2RK9bq|DeRAwls~zY)mp> zBLa5gy=mh0{+KJw#fBuf;ct6?su-Z3jy-Xt>3U!>Wv{~;>^hFL1p4PN-Ngp=>jUYMfad)% z=L=c}t{QT3a^Km+#V_+|1_(A>b|!hbxcZuB<{P~M0nf-Uu?$)d+`a)D(d(0Cgo;9I zR40!5l7;;DTkf>AwE+&%)!VD^>?sS2*88XyFHmY0_okj( zoDFCcYM%A7#*fVh%K0k%=X+%PzAIsb#N2j%2s%vT^E7<8Jepv6`t&I?b1q zt;jk=G2pBF(~9 z4X1#_#p(MVjfLjQah??=`sL>2oHettvI1Zca&1mq63YMase@2z-*^ZFumR-tp*OR_ zNl8gn)zn~*H>e}~-b(T`oi4){{Paf5>9P+Q%MI z^7d}WG9cX(`976h%}C#ds7uwJCkMZvmfQ9rKL3v6NiE{xIP_j zW=A^$I<%@FI{Z4D>F1J|9HjE%Z@5X=7?l?nY3Y8Sh3x`f^DNQQJf0W5sK2Y0knK?` zPDaNTdmXk#n@ko6R6}z8A^pBM#B%B9C&+Z+kIN45InAnem60O!3rE~-NkDrwGXQv= zBb!ggc(BC@K1tiS5bft-_}jO`cU(tvH53AW^vFbP5NP%$ zV8}~+){;*rV^#nHrJa+L6X45g+VhPM0e}JQw77OXNlEf@)O}S{vH3wa)!0zWz@0-^ zN$c=jD1SZ2%2f_Qo#9q0m)Fm*??hRfJ}MqjotVf@$ya_{!g>$VSi-m;JpG%cRX3a$ z%Xcbg@!Nlt*vl551yR_<>xO*(e7CbR`>q0;HJxksmolro;2Xr+7^ERH?$=dfB;ve(h+nyPKrbkXpaPbpC(l|G5*c&mO zh$jD%CZ8C=6LO24?6=K5vL`Ys`(jHD)b@c;IpMz9DEpv>@p7}n*DARB*@`}@sgkNj zjeizmpsl}hr|{(IAz3tHaO)lkElKKPg+3KIiHyT$)x&;L@nM;0^C9t<)o-F74Dr9( znp2_nfbpS8Ty@jXTh`Q9ds8O)@@_{f%$YbD@)X`QA;h$_T7^af$_vPX2v6-T_h6sV z2k?YwN(`a4FY);7Mag-+KJD55RvIgV*ej&+LYE3<1Y{uP(mOh0F|ieZt9>~jY6e^$ zzVcJ%=HW>fakhjz&H=y?8ylP4iP}4gPfgvGi~-`X5BhMcX?oy}?djpAcjZ$gM{JrF zt`U#dpU?(3#*OERKUd|yeu~d3g|OOl-JALPn^on((~4xq16quKH>FRH;JB4Up8X_iFgrxu8rFqPwx{9uUPdn7u$hRqalzMBoV<7TX zNRkV!Iy?G{#db<&_t!gZ?^0!kJb#b8^|#ri(cm%Lwm9kuP( zvE>Bo>xlAv+%SYnA=Ks-aulBH_3ee z`Ga=4T6)@~(bJJ_55{f+W=2^@{v{jkuzoc|1k~>^tjQBbr^(PjO6aqMy_*3=L)*IJ zr2h`LF~X}93{i~cP>b8#EHCsgDO7#+IhtyFKv33t zT!zyW#S{^GU0~b1g!St4zD(!a0q88tHyN3k$*7`vc6+X#`WIZX(Za6F{zn?&*cwh( zt%I*5<;MJ*#_L(bs&}qSQQ4)bbvF5jDi)RqpJ?~xV24$mjcN*CF7BzB7LZ!y1+InRQ${;)FDFd z+nf~t=V$3nHW1N9IHs=CbYOPG++c%buBx~U3?z!G>(QPLkO{{LO8-YzU#ifxuI0^8 z&}eCKxo0Es!$FG1!Un&D6#d`+h&9>H6Lz<48)t=*gLK)KKNX}8X4pzxhA0{==qBA| z7=TWJ$#tz8AnHq6l1Avf)(v?Wy^$5p9Tpz`?%g|Qc|dXqDIlR586J_OlAOkr8I^>+ zE^@mccD#i%#PNRhN2_9Z@BNNMoc$+d#_Gl?9!p5b-GNP7P0c$`GaHV_3lIoD<@t+* zl!;+ysLnRkuJ(=-s)9S>`^RV&>G+?0G^RTXl)}(25tvU;J<#h_+j=~mZ{ArrSYqp+ zK(*O*DYU$j!oTCV>Jpo6j3>#Ded99TnSPu-u=l2gio3fDRLuU0)1J#&1FUB;+S=mh z`0!T=3kbHow6=!+UC_OlEaO;dPgdA1yb3pT$zZK7g>dflMQY+2=5cvVu$EW{)dPvh zfcrwAKPJAuFqTfy?LEgAtXzMTn~($CoP`XlBV0 zBsj3U@r|0&v`Vo1b zykU=*aDqsa=|L66yykLFc$HEI?b=#q-JyJ0-Ajw$vlGH z`HpuX(0+yuvbSS|n<&up!8HOMyM`S#k=6ixepqnPNu2x3SI2cf7K6V+?tJtA!q<@8 zHNCfiM3wn{lFRun9FRp$Zmy+;g+L}v9_vT*%xhpcJm z``>28mTIG=F$+V<8hF%?QU2LYYrMxh`JO3{w=Xpdwr8QU-9H=HrVP}2T5$q1D8KQLc&$#;Oj4UAKsNRa^GY}B<4!*?&G#-212a6?LYMj=zgPZNj&>yN zn;+q!-b}Jcm)*j|mKVQ6pASMki;C2(nz_Sx;u5vq%(O=vL+@dSn+CyysXoA}FAjd` zgqTVdkNtq=`X0w`CNjPwfj!-!Z6+yt$H2tno31#$eA4GyMzCS^S>Tq2-?aO|pLYpe z7q1sE7kR+E75a? zwPb;X(!3&#oFL>5=%#?#w;1yS67K675REXxcrEyz82J2co6vWDKT&J|=AH97=mQG* zxvE@_;+p01jCb!7^qsoeUZ&ceW^V!5VB5WAC2hODn~>|^wWpB%^S$iLXA_-vkMH%9 zpAD5CSG-vzY3VMycpc*(FAACVM-xd1u{6fX(xb^`4 z5Cpm@rd8q~5Dj&8`-P@PyNP18T!p`w4WL2?dKa|KVfDTtP&k80{kE%;$1nv#ASzw+#B^rmqib8rgPbH zNz3`lB0I$llKEeJ`!pto$A3WMyCL`&?fZL1)za|&vrB>$S1}PXix%+MiP15e?wGLy z%dnC&0V?paJ2^TL@ndj?9F)(h@Wuk*9=}%ItrQpMJ@q$5f&YNQ{f!|RjHNvPpc+p%vsa& zX7@_Tz2WCfq1w)o8P(G)W-vR=W)7}qdxH`Jba?Hkk^-5;0(9;7%-7lR?bR3ASy@*s ze)dc|Q#l0n^6|9-mvZ06VpJG~RDpQEvVqfIg#7#CSexyUwDqot z<5prx^+r=Gu=H1!bf5A!w=)vQyOCRoC6`CUUMiKU9?4CjlyF@K+rOhKkFS;e2CTfx7en{LaJg&?;9#lN~*G0wKy0@87vHn|ZV zlc%1|FuDAs6X$uV7+MakCR-;HecHtODb8dEQLOy2H8-%40qz_BnP{ zdRv(Zh3pw^%ZNVxC3t1fgf`MRH~pPu`0t8jbM%(XW4DpJQZQ~fI2tu=unwj-eKoEx z?+`T+n3nB(W_amM|36+5ij&b3&sD#X<}GMHx%e6cg>Lf?ycm(WHP{;w0kkInRQ5iE z|ADM^*qS8yX|9o^S$3c15onY+JT%F9mU9O(fh4OXiL4usY$WZR72H0@Uh+5v2m=4O z02bdg(ywe_Ug`xA-fuk^ljgt6SM^IdGeNpMzhsTEM3ys4&NV0=Zn4H5W@(c&2}zF- zOTo^IixjAjlrS33l|6}SClosTxRvn$5 zDQ7@q|GH_Ey?aq#iu$H<2Px(9x`Rq1O>X@0on(Si`q z-Ab_K7<)u1caCj->xM4{MB^H6N9 zEgTX!!SNZaihC)$b;2U@+18N5vtlESIoyXnacz9z=luF|PERDgUZ)h+Kf8&*9vqOw zTttcOO;%V%GhyW$`T6;U5Yf{Jf%>|8U%wgH{E;ZKyob+$Z#J5xJaF!*fL5dWB;a;Y zeq*)&q^t;_U9}WPhx8AJpP1(7R_Ad4A=T)G4Nx zn{P6QcO_0)NgBMdz0e0Udtec7Ik3ayq$etQW|IMz553T2`Zq)pboyJ@G<=vLz)a(z>890**rcZjcR+mN@B z*xpCGk~Wfl#lFI?sgJd&zo3=I7fg2G4I17OsK-XNuXKoT=?PIsHhU_^J2%FFcQ7ml3=jDRNyw+$FVi;kJbG zT+dpWI}&J4ko-Jy=T6f+GREV#IPIFq=T`cdLJ42aTM@N!@evnv_G)7I!|DBGdFW<1U@=9+G=j z;^!B%|D5tHFZ^L>76!7NA2J%MRH*i1dvyco{)GA^gf8Qo?`Nk+r5)KhQwc?1bBERw74`Eyk0)QyzKWiIXPii4?dPFWN0*; zO9SRn*V+62J*kb}MCTqZINb}6!2(dFI}pug;NUpWa}Ev;aen^CT<7x~s+5w)Vn%OR zwG89CwBmZ1o%A{_s_Hw!{U}2N6GE{PLK8$ov+#piI|k@sz*KHjeyjNA;22 zWIXpCP@#OZslD=wXq<%)_?!nmX*!`=^f9$?l3D=MbywSeEc|%oa_OKt$@~LbbaIi` zi7UgV5!QeH?slmq6KfLRy3y|uPW8w|2gmUj)kK2QaZ`_A<`w6(nHjEMXdxYj@N%t8q-1yXX-F?WYO+qkHLX!YhH;SG{Q^9 zBiq4hp$v7x+V&AWox?)l57^jsr|`W9C{^6sErHvBjzH=T5#6MA_@k#!m@V^|Pip?2 zh&fN6z0G>1cbZ7ahBAe`^jEPu9%)W?us5{ZnKPpkwx&Csnyl!V+|NGl^WKhQ973ul ze(gGXV@gMR$Kc|QZ=XAh0%Ot38t3_MXX-H(fnZwdGf%xx!>;cA^HF%?c7sr5aBNjc zo{f>Bh9qr?-!my{%ul{eW)+v}eVHW0t}vBHVr(FVK}HF*?K`I?6K4`LYFb1TTdJtn zt&yZ0T4t5Pcj)Mf!Uq~0)0AKvqxU0CNm;&vFE2lo0tNFLWJcyM(n5Ie!?qPsQNLKW zrdo?GKgj2A6oFMZU9W$(`S;0_=oh)4R{%hUmkl}`*8_72$ZJj$NWti%sQHRE8TDGef%b@`@dZFZ>{I$vdd5LQg8Jlw@N-3RG z4nnLoe|EL7wN3B5VI`f=ab0Ss*yCOM>;}}=L6%Y*fu;$&pl0tek&>R(Hrg%i+gT~@ zD3>EdBFj6IBHf1QFWshNSyUa{+>KnT&lAFPX+nCUCh+8|U+wEs-8n8yk0Rr_QW2Ck zsWdBG_Q(i) zB=J2t$*BHcn~~pEr243_ZOIk1hoUk5LM7yv#id$78fFiCqM!I8>axx7><+JhIejE>E7!iW;TFKfkDJ(ukFeI~;xZVBvt>aj`5cTmy z5$M7ZLHu<|KE(0uv6&6@OHI3ePwHTbda`eZK920}3<-uurpWz@k=sw#ZRR-i^;R6m z3n60r4F3MkX$p)ZvQf}1e`$E`B=-ziX!JhIlV@j!X~VM5VQq55D7rxGvw&S&Qu{Iw& zv%;CMHWQ5eQRn=iG_$;4!=eKk}biwuESe zFsIkU0p|3h@enO;?b5~L8SnxeoIcQG@u`15`?12CH(R3xBLI_Q|8yl7*r!H z3+MBL?7IDf$!~4@1uN;_@hL>UVYPLutHev}mRQ}lv?!OneDqdyvd{eT&WcU3f)D$B z+tGY)jg4pszJnOwNIo2b(u`87n*VJ$Y(nviCZs!V>14_vQuG^H6^X1B!mdeNH2AK% zL_fvZ?rKpgQBcHn>jmA-LHE_Ws7F1M)hzuv3yZ61YRUzF6>^;pPIAa)CmSszVwZ<4 z5K01!86x@Q6EM|8rypwhmXV6R$y1$J`NwTCIx}|s6Y*VsKY<=EcIxhv=!{gowVnG% zX#}G?#LHuPO2T&l+K~1A8!3uH_ztc|#&ZA%rQRKRJOva)#FIvf69+SAb?{@?=;F?3 zgUds(rMS!dFR^J!XWwP|gdF|&)HFy;Vp4qKk0k2!?@xs=LK=E+HBD_b-|AY*d9AnU zP`l50Zd43N2m$1Tvx5!rTwT@rl7`ZW=kVvDro^YHfe*&emx&^B`N*Sc-D1N?GtI`k z?>$!}>ah>Pr|%6EbnhqozAfb(vb`s(_Ql=Vc(hrh?I+*jKznHJk0Rt2B6*@qAZGPN zsGFTJhj`3(L{kS{n$DT<(%mJI_YXQmpRK%1xA#ThZqT$eygc3`Q$ubm^H(Bnyrk|^uSy}x z!q74;-ATE$9a870A<_4)Xngwq6g<}}?HEdg)H9ZzK}X)Vb_5_e-*~EC-&irzE|DB} zSaGjiq2KnQvQZ&Pd@t$k=8EK=p4Y{}9%Zp*-rlZE+Vt-a*j66G>AQ5O?eJaYN|a>{ zH0^xE^d6)lewk+wG6d)nC+;F-OP<6mbnlJD@hdh^Ky!=F)Mw%H4L9S?ft~2l{8WD$St9*a!g%Hk5+=jLr|;*2NHsiP*@aqS)0dNvf-I-+&wbBS|m#3{B#%PNlbJqjPp8Rr@2nnEF^VO=Y2vL?rL) za=36@Bmo1mWR zXS~rPDfG&1hOLxEHC31NyPPm8cTfmMI=A955IOS;E8k>SKk+nT?ojh;{IPVZE}i{1 zWx25N5)(lfg*d4_q@6OQ*dO!J`WzQvdH|sV1hP$k(HT9JEClugNGJ(hdh5^U&(C+D~28x^Z>9Iyc2|%87-?NWScvR>i!B2znG>%{@ zr|dbDYT+-p{mAyrSC8#+WQ8U$W#Y6&C+cfe+)b#(d$NHx6ozGDebSjC=T<|v(Mpn& zjf8eXj931UF2i~RMBoF+)}RCXyzN)v4h-XXHJ-Wo!gp;V6TH1mV=g=XNT>v(`Z{gB zd-V4gVPjxLrUFG z9-H5^7Vf{te`{v_{M_X0do*M#VQ~>#-TFs6W=4VfN-JBnaJ%lYH>r+BA->GKj?>i? zdLfUHE+8oFWcW|-O+(A?aH+02g+Tx;8!6iEORod=oA9*E3 z+Xld15hCLj_y9X_7%0&lR6YDUAyiyGa|vY4>ov%^8QFCEsdYEa&2m0O&N>*s*SJU6 zMZ3Z2^BnoN)ub0(Ra2P?fzkGaI&VdO%{%Q!k_6a>=i!4RV6u%DA-f_PzCz7t>sMU& z=lpoW24Ki11ePd6prD@{{<8TP;CNEqs9M798$&hFlIjO&QY>j6S?l3P^Em^F0E5|M zW*cEoj8{b(mUAGx1g6K6lBC=0l=pol5GRCjDDGJ`2SJ-==Js$h+8nMY8$lhP68L1W z@-=Wd;xge=VvAHF9Tt8?$7AP~Og|8z1GG<_W+vZd_nsMsEZC`sL9+>EIXZcqV8B9 zizXH!-E*h9Sy9;r4`6nX3@b>OqX!!gqL>Em8ZE|=m|PhpH?kF@HgY@^?R=c zne1ydHN-4BtGYMqAu8_d*;mt2GhfAIqw%+!2@-T_pb8GZero`ED)xmIfO*GJGG__?%U~ySHU+RKqEgm*j1o$$@Jbqky~1X~ zC>2#$BrW#T6CO__6XOkFrVIjlXklDu&sHOi=dIDhN-|BmXVeWOzznl%`K6up!LZKn zk?B2iJg2~d^Hqt@C$3-9<;QzV!FXU_s~r19(5ROpv<}tHaEeFG#jgf~{l=NH4UNXe=F4FZ8UCJ8zuMT4FzU=R9w$0d|J@QiUgNTuW% zc6a1Gp+d=m533d?o46fgH^7Q?Z1DPCF{>Oav!+M!{ zcQ=YTXkFCR3V0DVIDbq33U>=)yR$%#V!4h3xHqCUy`2gWaNjE`_V@Qkg@@BVGY%-Z z+lTcQq#FWK2cW%oNOyAD$}os(xUF|cnm!=u9cXuw6RrP5>5n34+aZ^raZFf$k6&v@ z1=rBbjyzS`nL0m#oBtT;@I&s|TjH<;o_H?s!SAC1RC-gD*-`AoE^daC;3P(EgV60~ z>%^5NVIgQ#AN-cv4D!?n&Jgfr!SekB@9L(jkS_=pU`Fxvx}~aHc54tIeMA5kNI;7+hM&pK+-{hLQnaFuh_mUl3*?HB^P|u;P>K^sA7zx8}j%lgPN7>oe zw+pyoM-+YR_wRMC2)EOHlXMuP@~uH#I(61tgH;RR-|_8l^RDZPZcla;@@Ff%Nu-N_ z3#gnbV4wOJD~v0^EM`c>+E#j6*=Y5|Ta@k7uLl)XS?G?%@vJePzadLFE ze9%qAih(${7ljECAr2Ul!rJ_^L65iY=*h2r=PtlEmI1ncQe4Bhv6$qP zloTR*(d!L_YciAH-{6QB_PscO=Y)U0Ckv|ErmZ0Da|4Oyl)n5#zz-saqNaBhaWZV$ zxhrnDAZS!(=lwv?2=B_5*n@WmMAfnC#-|HJ8}rDpHbv0ox1(H6rx&0mQ~`btxET(9 zZCKVpeA_1JSpuETKp0oQUOULpEQ+fD2(tivdTMHlnwr|i#s;AArvZ>dhdn4j)Q2Uy zb++Bh8f23|9T2a@UgA;)kb;x2E0wCtw2Coi_C`E)EQ!tm(|A(ON-FIajW0ufHJ|+; za}H=n%m`|WX;?K`gULOdi3UF{Y%TOT|8v*Y$NTSkyAehXxAU7@fHvCPW^)4Vsvi~z zG%X%N$bJ*O@X`uA5vqYF@}0iTK2+XBQUZ|@=O$9Ny}c&* z0i5u(n3xy0-7YLa<4Lvhg666X58r-+1l)iKK_maOB!QpQ`Q!n6^N$T16xJcZ z#{ln7FXC0m8qo=o47<3xzR1UrpZ7HP3!cj@i_$gIUr&G2nh1e*6D)Inp>QwkD;w_( zTC31;I4O=u`1QpQ8J+71q})QwuY zP3Oe`&H?Jw1Wh;l`x`}4OCw0kPVuDt|7J+v51{dOW547k@#NZBx5h3JB6^7D8E>+u zzi^t(Y6G@AEhYDetQ)w${_UtW1Ts;FhqS3i8@_xu#L+t02s5E+nXG!>@WY0ALQphM zNSfLy_2cQcDzn{W8^*j~7-)1MKm=3R&szPEobd09dm|v16Tu;tcTJ8$ph)sIhgL9$ zh=IgcTz%7>Df<6Bb~_KMbvue)%(3Zg9oQGy+1dH?=Z}Oh8aOl{U2&J!o@$6%ZT zq5J6W5}Bo`V+uz;>_HM@TIn)JDc?2e7>t;Tc}c6clA4?(-4Fb#$7%8=lmSTyb9#1i z6eV$t8}{IZW_cXnjvyv<<05)9)^cb1;eVW3R9WNbZwG^tfctyOV6#kYJ968R@}|Xk28!UEgoRH3p*vTNcdNLF8G3KZ)BV}))n_0n*Ln? zq^nq)J0^@1h8hJ`RHNqLO>FvuZ$X=tK%Bk#y8xDn7Y)0G%wl=ys{p9nvtuMBj}bcy zf0Z*a8kvygd^ENYRLxK4SqMFl!v`bw@ub$Udc--%Fm@+~{gKM;5^IIZz7WVd^KXa3 zN>N}$V*UCiDT*f#;MOVs>AcYofD|wxF)T^A&We;BT7;ePd?H|p49fe@SRI#FAO(;A5B|h3EL?UAeY)8_q*cHe|P?RgiHmtNQ4Lw9Vz#%Q{ z#+VDu$7l<={04UJT7q;7*qIngwTSH3edouwXJeuc&vXU9iXK?R%nY}?Kp(Xc}{C{gg~Id!5bj+U4JB518jMSU+lMrhK6=^bpaSg8?aqS z5qja~bgu_JAiD`p*UWlixX>UPRF>eXB9X3cZA+bd0 zYWAxWHn7B#7lPxZwhQ=u_OUFh@&*Qc zhuMCSzA<7WB2O_Oj!|B(V`dN))i?v&LkWgnHv0N>T z#7Q07E_3M+>dVt$*3(oNhbcWYFHtmGDKgyDt@+Ksw5=Y;c~A5MU(v1l>fllm!Quzv zWEP#)&f~WRY`XO@Fi~HG^%0kyOxKxH7^t3$u0RpF@*0j=J9lZpiLrAQ&&MT_>XWyy zDd0QB)k8cw!HdB|8v2O;5r{Ak7}wA* z6}|jz#-og1%=y#rSkribs9Y41#b$P8qNqh0I81JjyZr zV4!=Ewr_Y&yFPYOaF+3POToK^o6U zR$^en=5@G9LhuxTWERj7!*@@Tqp@(=B^{@G?~+~pJxNS|3A6`dYifPqmgXgP>XOe| zRJhYEd5{!-l|XxbtjX|Gc&m8W=k{ver`uZ47@MQNwf<_QwFOek< z;vNf4a~Biz;y@cG24W6i+g7Na`MK@@JM&+*CwOMTEC3_x?qQvjJE7)}s2ZbH!3u#E zYmH+ewvLqBqnYZRNjs>06W$$e7Vg+)JwY|OtKH59p2=P81AJLf$k;<;08zvTBG*Hz?K4O{{ z1m^0|HaPqcF_+f_P2=OUabw}{Wm%c79OJY!Q$MK<&|@flTi*`l#TLP<7B~RzPSr8^ zbo4GpfZyGljOY|xw?}^{upm0Ipg6hHKEFF1kuXXvKDH%(Yo@*pSahguRLf{ewQ@8( zg3;NjF^lIZ`iwWTk)>(2OR~W~DzUCS1lqmOevct76+_=-Y#>d(-qMy5mmujOF6PiI zqT;uVD7ji$0KR^eXudMgFw2Exc{dbIb3~L$GHW$V>MWSHi@PynL$K}pUQRj7;ejLO zT97S&k=@^tBT*=*p}R~?g;gG=(?ZrTW>*M>{3-wTQLIxINoDYe%oTWt!cvoP80nsf zF^`TF*CCYf&M%cLo=wVBrC=e#tE|3E;i%DVZ1Su1*iyX{WLQJapIqbB(#?K@ z50RQY=?ZiPg#OCp0jLknFhmyJ=QdRH;&Qi9?vL-B>d$cq-{v;Q&Mrx z%AI>0-i_+s2|~KL8{_s$P0|z`HV;qMu%EigUDhw3q<`JJyWWi~BZ~9)VjQLRg({x? zu!QHndhhm#Fu{M$f2n_nq8ZuAb$^qTqluKq(A0e?yB(N6dCjzT7Yd1~fN58nx8nW| zP?0a6YK=R#>aC@F|M`Vj<^Nd&^Xb^;s^-?yo8s{Lb6&4AmIiEmf4%|Wd4@>B_Z1=# zS}bcWB6b(7{HkC5C|Q87&5|W&_sunk$|v^WS4;%-OwNwH3P-MqcDln%wne1ebSUr@ z-#fK)gDm8n@5N-BZP0rTS>n7bIgznkk1bN)F(HBe!sAF|SiG5axaHSnBF2RnTY3Hn z1jMWN!%j9>ZVk2(w4q)7?DAI0qB-6)CGzX{<8{#^-u|EIk%Bl9 zrzvMH4V?~V=Ptc@Mvm`XZQcDjL{Ps(wuLWGvPF62SLH;N8Fp=o8z5?Pogh#K)-_%a ze#Mir`>6c52t=q@C9SN(I4goj0yD^gZTqMPTDaL(N0(T?X`fmRRgFFE9V@Hr zKuB^quNL3|(f+36AO~!50@dc$eGiUf-J>ejy1_)oL8-$L>DAQYh_i%h(-;*t+Y!Qu zOH6a47*=&*G1-fG4FhS4&STQDdh!Hmhl!6i)buks9Z766BvszfIomqR6gN)#4ny0w zGYwpxk7>WNGPAZsX5cXjW)Ct>n|{ua`aDS*!5SoM&Krbt>&t2)Y0Sn z&hPTfBkZlI6H)}@-Jf&1?tf*a9yXDT$uJH9>xcaSZTCoaK%>t8Yj|G0UVKA`9ys&tadx zCCCV$GkLbPD+W(o6dmLxP&z;vX2pDdG<&|?Ii;D07BU#A+Iy*``TbA|%}Fgv=ckgA zZ?@$Y<2d4!Sj_`R`rYAX9k}}7i@9tqk=!B>6}=*sP`_#oEogp)*gx*&888wM{0;hb zNGgS8jC(hOY_gz$Fynm~6t~COdlIoYNcUjB)?{|H2NIGRbJ#X zzjn2~k0OnIJ6Uz1oUR{r zXDIWfHG|@b3d|q9gM*uSw*_whjzyv*_OXY>xq`NS%JK1d^Of_tF^kKv*5|P(+HPlw z@03Quv zt*JJSkUp-jzCjH;$ii5}1*v;-p}X?0RXo$E|eXA%-g1WAZzcdcj5e0|q?zq-Hf z{o%g%`d`=ocU}9w_clt{I6{o~VOu^it<)y7UPWAw9J^3a*qEvF{#W|LN}q@`;0?n1 zfq5akphtf4CqW;M%EicEFfWyhd1miMriCxwPJ^H|S2)lpm@?+RU;dbufX~C@N{_SBK(A+&NmRBTp$ANUD^1gX9n-$$QV>GOl=*$&joE?V!0-A|+LBOz6hqjd7_27K1_es~UrM#>S zxutM@QT)l#8y||jF@-SOTZ0LL6Yj3PSEigSUnN*JMHxX%kUh>e_6zP{VRm-t{A;5} zwTA*9?(5AdKUV4-(XB(x&8;as)i^2am&|0;$;y!8(ZMVZN6IB_=zZ;UGoe!TnIu`t zN#H&Yrn!=5M>|8M9eP|3jFpFxjobf{HSHVYgC}DH6_vrGtXAxgUja|5Itpr0aBxIlN z7T+#TH<%z4uzV9kToZpEc&)ZJy1svu*+R8x8vPMR4gK~%E}bX4wv>Bwctu25@euVa zZXu>N*}{%;!xo&I(A>|SNzXJkwrFYCTq7PPCOW=aGG`e0%KL<+Q*`? z@w1To^z>#cQ>vkQ*&*WaSS;F}wqGvE?pTuiYvr#l8oYEJICRmz))P6NxfEE#UA$2; z(ELSADWQomr0Ntm*xB}Vs)XP_Xa5Qn`+YA$C$$uvK8L{N5Sz@FY)5b<=V!2KYI1Pt z$*wyfE0Zyj9_BmIj;+yM9U2E0yz(2PDYe0v%?v6YoeJ|yoWCX=PScGx>s{J_^?hiS z$vpL=734w1`v1=5$VGcu%`IsjV#P6<{`Ixk^Uwq*AErC2Fun;$ zHXq#@Kt-3-ok+^UINfw7(DiE|g}mQ*R-uXwhBeb;EzhX|Gw+3XpsDi+{ci^Cl8cGa zt`>V(@x^KF%k*k07v3{L7N<(OgT?{}HLceoBj_JoYMeNJ1j)PwCplI}A*J`ixv