From 604e866943fa1124469edc0154f65a16c8966c43 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 24 Mar 2022 15:11:13 +0100 Subject: [PATCH 1/8] MOBILE-3833 data: Fix unable to change group for new entries --- src/addons/mod/bigbluebuttonbn/components/index/index.html | 4 ++-- src/addons/mod/data/pages/edit/edit.html | 4 ++-- src/addons/mod/data/pages/edit/edit.ts | 6 ++++-- .../feedback/components/index/addon-mod-feedback-index.html | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/addons/mod/bigbluebuttonbn/components/index/index.html b/src/addons/mod/bigbluebuttonbn/components/index/index.html index 8003d0166..98308626b 100644 --- a/src/addons/mod/bigbluebuttonbn/components/index/index.html +++ b/src/addons/mod/bigbluebuttonbn/components/index/index.html @@ -23,8 +23,8 @@ - {{'core.groupsseparate' | translate }} - {{'core.groupsvisible' | translate }} + {{ 'core.groupsseparate' | translate }} + {{ 'core.groupsvisible' | translate }} diff --git a/src/addons/mod/data/pages/edit/edit.html b/src/addons/mod/data/pages/edit/edit.html index 4b04f9b68..875d160f0 100644 --- a/src/addons/mod/data/pages/edit/edit.html +++ b/src/addons/mod/data/pages/edit/edit.html @@ -20,8 +20,8 @@ - {{ 'core.groupsvisible' | translate }} - {{ 'core.groupsseparate' | translate }} + {{ 'core.groupsseparate' | translate }} + {{ 'core.groupsvisible' | translate }} diff --git a/src/addons/mod/data/pages/edit/edit.ts b/src/addons/mod/data/pages/edit/edit.ts index 53a73c691..208d9de72 100644 --- a/src/addons/mod/data/pages/edit/edit.ts +++ b/src/addons/mod/data/pages/edit/edit.ts @@ -163,8 +163,10 @@ export class AddonModDataEditPage implements OnInit { const entry = await AddonModDataHelper.fetchEntry(this.database, this.fieldsArray, this.entryId || 0); this.entry = entry.entry; - // Load correct group. - this.selectedGroup = this.entry.groupid; + if (this.entryId) { + // Load correct group. + this.selectedGroup = this.entry.groupid; + } // Check permissions when adding a new entry or offline entry. if (!this.isEditing) { diff --git a/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html b/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html index 8a72abe19..eb378ee03 100644 --- a/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html +++ b/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html @@ -61,8 +61,8 @@ - {{'core.groupsseparate' | translate }} - {{'core.groupsvisible' | translate }} + {{ 'core.groupsseparate' | translate }} + {{ 'core.groupsvisible' | translate }} From 9c2116c33b2d9a5f0b004482ce32c9437f9f37dd Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 24 Mar 2022 16:08:16 +0100 Subject: [PATCH 2/8] MOBILE-3833 data: Hide All participants with visible groups --- src/addons/mod/data/components/index/index.ts | 6 ++++++ src/addons/mod/data/pages/edit/edit.ts | 6 ++++++ src/addons/mod/data/pages/entry/entry.ts | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/addons/mod/data/components/index/index.ts b/src/addons/mod/data/components/index/index.ts index 4708f24c7..bb4b1b8dc 100644 --- a/src/addons/mod/data/components/index/index.ts +++ b/src/addons/mod/data/components/index/index.ts @@ -218,6 +218,12 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp } this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); + if (this.groupInfo.visibleGroups && this.groupInfo.groups?.length) { + // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. + this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0); + this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id; + } + this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo); this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { diff --git a/src/addons/mod/data/pages/edit/edit.ts b/src/addons/mod/data/pages/edit/edit.ts index 208d9de72..52abfab1e 100644 --- a/src/addons/mod/data/pages/edit/edit.ts +++ b/src/addons/mod/data/pages/edit/edit.ts @@ -174,6 +174,12 @@ export class AddonModDataEditPage implements OnInit { if (refresh) { this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); + if (this.groupInfo.visibleGroups && this.groupInfo.groups?.length) { + // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. + this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0); + this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id; + } + this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo); this.initialSelectedGroup = this.selectedGroup; } diff --git a/src/addons/mod/data/pages/entry/entry.ts b/src/addons/mod/data/pages/entry/entry.ts index 648726a62..6bc442857 100644 --- a/src/addons/mod/data/pages/entry/entry.ts +++ b/src/addons/mod/data/pages/entry/entry.ts @@ -174,6 +174,12 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { this.access = await AddonModData.getDatabaseAccessInformation(this.database.id, { cmId: this.moduleId }); this.groupInfo = await CoreGroups.getActivityGroupInfo(this.database.coursemodule); + if (this.groupInfo.visibleGroups && this.groupInfo.groups?.length) { + // There is a bug in Moodle with All participants and visible groups (MOBILE-3597). Remove it. + this.groupInfo.groups = this.groupInfo.groups.filter(group => group.id !== 0); + this.groupInfo.defaultGroupId = this.groupInfo.groups[0].id; + } + this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo); const actions = AddonModDataHelper.getActions(this.database, this.access, this.entry!); From 1a0733139679f16421a1f64ae9b3898077db52ed Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 24 Mar 2022 17:29:58 +0100 Subject: [PATCH 3/8] MOBILE-3833 course: Display data ASAP in course downloads --- scripts/langindex.json | 3 +- .../pages/course-storage/course-storage.html | 31 ++++++++----- .../pages/course-storage/course-storage.ts | 43 +++++++++++-------- src/core/lang.json | 1 + 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index ec7f4e8eb..8221281fa 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1453,6 +1453,7 @@ "core.block.tour_navigation_dashboard_content": "tool_usertours", "core.block.tour_navigation_dashboard_title": "tool_usertours", "core.browser": "local_moodlemobileapp", + "core.calculating": "local_moodlemobileapp", "core.cancel": "moodle", "core.cannotconnect": "local_moodlemobileapp", "core.cannotconnecttrouble": "local_moodlemobileapp", @@ -1673,6 +1674,7 @@ "core.editor.underline": "atto_underline/pluginname", "core.editor.unorderedlist": "atto_unorderedlist/pluginname", "core.emptysplit": "local_moodlemobileapp", + "core.endonesteptour": "tool_usertours", "core.error": "moodle", "core.errorchangecompletion": "local_moodlemobileapp", "core.errordeletefile": "local_moodlemobileapp", @@ -2342,7 +2344,6 @@ "core.usernotfullysetup": "error", "core.users": "moodle", "core.usersuspended": "tool_reportbuilder", - "core.endonesteptour": "tool_usertours", "core.view": "moodle", "core.viewcode": "local_moodlemobileapp", "core.vieweditor": "local_moodlemobileapp", diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.html b/src/addons/storagemanager/pages/course-storage/course-storage.html index b6353dd6c..b36d1e85d 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.html +++ b/src/addons/storagemanager/pages/course-storage/course-storage.html @@ -24,15 +24,18 @@

{{ 'addon.storagemanager.totaldownloads' | translate }}

- {{ totalSize | coreBytesToSize }} + + {{ totalSize | coreBytesToSize }} + {{ 'core.calculating' | translate }}
- + {{ prefetchCourseData.statusTranslatable | translate }} - @@ -52,18 +55,21 @@

+ *ngIf="section.sizeLoaded && section.totalSize > 0"> {{ section.totalSize | coreBytesToSize }} + + {{ 'core.calculating' | translate }} +

-
+
- + @@ -87,7 +94,8 @@ - + @@ -98,11 +106,14 @@ + *ngIf="module.sizeLoaded && module.totalSize > 0"> {{ module.totalSize | coreBytesToSize }} + + {{ 'core.calculating' | translate }} +
@@ -111,8 +122,8 @@ [canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner" (action)="prefetchModule(module, section)"> - + diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index aa14b5269..5c3f371cb 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -48,6 +48,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { loaded = false; sections: AddonStorageManagerCourseSection[] = []; totalSize = 0; + sizeLoaded = false; downloadEnabled = false; downloadCourseEnabled = false; @@ -107,13 +108,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { this.sections = (await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId)).sections .map((section) => ({ ...section, totalSize: 0 })); + this.loaded = true; + await Promise.all([ this.loadSizes(), this.initCoursePrefetch(), this.initModulePrefetch(), ]); - - this.loaded = true; } /** @@ -241,12 +242,15 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { */ protected async loadSizes(): Promise { this.totalSize = 0; + this.sizeLoaded = false; - const promises: Promise[] = []; - this.sections.forEach((section) => { + await Promise.all(this.sections.map(async (section) => { section.totalSize = 0; - section.modules.forEach((module) => { + section.sizeLoaded = false; + + await Promise.all(section.modules.map(async (module) => { module.totalSize = 0; + module.sizeLoaded = false; // Note: This function only gets the size for modules which are downloadable. // For other modules it always returns 0, even if they have downloaded some files. @@ -255,21 +259,22 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { // But these aren't necessarily consistent, for example mod_frog vs mmaModFrog. // There is nothing enforcing correct values. // Most modules which have large files are downloadable, so I think this is sufficient. - const promise = CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId).then((size) => { - // There are some cases where the return from this is not a valid number. - if (!isNaN(size)) { - module.totalSize = Number(size); - section.totalSize += size; - this.totalSize += size; - } + const size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId); - return; - }); - promises.push(promise); - }); - }); + // There are some cases where the return from this is not a valid number. + if (!isNaN(size)) { + module.totalSize = Number(size); + section.totalSize += size; + this.totalSize += size; + } - await Promise.all(promises); + module.sizeLoaded = true; + })); + + section.sizeLoaded = true; + })); + + this.sizeLoaded = true; // Mark course as not downloaded if course size is 0. if (this.totalSize == 0) { @@ -608,11 +613,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { type AddonStorageManagerCourseSection = Omit & { totalSize: number; + sizeLoaded?: boolean; modules: AddonStorageManagerModule[]; }; type AddonStorageManagerModule = CoreCourseModuleData & { totalSize?: number; + sizeLoaded?: boolean; prefetchHandler?: CoreCourseModulePrefetchHandler; spinner?: boolean; downloadStatus?: string; diff --git a/src/core/lang.json b/src/core/lang.json index 8dd623b4e..a66c1a6a3 100644 --- a/src/core/lang.json +++ b/src/core/lang.json @@ -13,6 +13,7 @@ "areyousure": "Are you sure?", "back": "Back", "browser": "Browser", + "calculating": "Calculating", "cancel": "Cancel", "cannotconnect": "Cannot connect", "cannotconnecttrouble": "We're having trouble connecting to your site.", From 37af8e3c69b4338a874fe39fe8bb5fd85c5e39a2 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 28 Mar 2022 12:54:14 +0200 Subject: [PATCH 4/8] MOBILE-3833 course: Improve performance after download or delete --- .../pages/course-storage/course-storage.html | 23 ++--- .../pages/course-storage/course-storage.ts | 91 ++++++++++++++----- 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.html b/src/addons/storagemanager/pages/course-storage/course-storage.html index b36d1e85d..57b45f33c 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.html +++ b/src/addons/storagemanager/pages/course-storage/course-storage.html @@ -25,8 +25,8 @@

{{ 'addon.storagemanager.totaldownloads' | translate }}

- {{ totalSize | coreBytesToSize }} - {{ 'core.calculating' | translate }} + {{ totalSize | coreBytesToSize }} + {{ 'core.calculating' | translate }} {{ prefetchCourseData.statusTranslatable | translate }} - @@ -55,12 +55,12 @@

+ *ngIf="!section.calculatingSize && section.totalSize > 0"> {{ section.totalSize | coreBytesToSize }} - + {{ 'core.calculating' | translate }} @@ -69,7 +69,8 @@

-
+
- @@ -95,7 +96,7 @@ + *ngIf="downloadEnabled || (!module.calculatingSize && module.totalSize > 0)"> @@ -106,12 +107,12 @@ + *ngIf="!module.calculatingSize && module.totalSize > 0"> {{ module.totalSize | coreBytesToSize }} - + {{ 'core.calculating' | translate }} @@ -123,7 +124,7 @@ (action)="prefetchModule(module, section)"> + *ngIf="!module.calculatingSize && module.totalSize > 0" color="danger"> diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index 5c3f371cb..39c3d42d0 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -48,7 +48,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { loaded = false; sections: AddonStorageManagerCourseSection[] = []; totalSize = 0; - sizeLoaded = false; + calculatingSize = true; downloadEnabled = false; downloadCourseEnabled = false; @@ -106,12 +106,20 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { const sections = await CoreCourse.getSections(this.courseId, false, true); this.sections = (await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId)).sections - .map((section) => ({ ...section, totalSize: 0 })); + .map(section => ({ + ...section, + totalSize: 0, + calculatingSize: true, + modules: section.modules.map(module => ({ + ...module, + calculatingSize: true, + })), + })); this.loaded = true; await Promise.all([ - this.loadSizes(), + this.initSizes(), this.initCoursePrefetch(), this.initModulePrefetch(), ]); @@ -240,18 +248,9 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { /** * Init section, course and modules sizes. */ - protected async loadSizes(): Promise { - this.totalSize = 0; - this.sizeLoaded = false; - + protected async initSizes(): Promise { await Promise.all(this.sections.map(async (section) => { - section.totalSize = 0; - section.sizeLoaded = false; - await Promise.all(section.modules.map(async (module) => { - module.totalSize = 0; - module.sizeLoaded = false; - // Note: This function only gets the size for modules which are downloadable. // For other modules it always returns 0, even if they have downloaded some files. // However there is no 100% reliable way to actually track the files in this case. @@ -268,13 +267,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { this.totalSize += size; } - module.sizeLoaded = true; + module.calculatingSize = false; })); - section.sizeLoaded = true; + section.calculatingSize = false; })); - this.sizeLoaded = true; + this.calculatingSize = false; // Mark course as not downloaded if course size is 0. if (this.totalSize == 0) { @@ -282,6 +281,56 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { } } + /** + * Update the sizes of some modules. + * + * @param modules Modules. + * @param section Section the modules belong to. + * @return Promise resolved when done. + */ + protected async updateModulesSizes( + modules: AddonStorageManagerModule[], + section?: AddonStorageManagerCourseSection, + ): Promise { + this.calculatingSize = true; + + await Promise.all(modules.map(async (module) => { + if (module.calculatingSize) { + return; + } + + module.calculatingSize = true; + + if (!section) { + section = this.sections.find((section) => section.modules.some((mod) => mod.id === module.id)); + if (section) { + section.calculatingSize = true; + } + } + + try { + const size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId); + + const diff = (isNaN(size) ? 0 : size) - (module.totalSize ?? 0); + + module.totalSize = Number(size); + this.totalSize += diff; + if (section) { + section.totalSize += diff; + } + } catch { + // Ignore errors, it shouldn't happen. + } finally { + module.calculatingSize = false; + } + })); + + this.calculatingSize = false; + if (section) { + section.calculatingSize = false; + } + } + /** * The user has requested a delete for the whole course data. * @@ -406,7 +455,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { } finally { modal.dismiss(); - await this.loadSizes(); + await this.updateModulesSizes(modules, section); CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, false, false); } } @@ -455,7 +504,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingsection', true); } } finally { - await this.loadSizes(); + await this.updateModulesSizes(section.modules, section); } } catch (error) { // User cancelled or there was an error calculating the size. @@ -501,7 +550,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { } finally { module.spinner = false; - await this.loadSizes(); + await this.updateModulesSizes([module]); } } @@ -613,13 +662,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { type AddonStorageManagerCourseSection = Omit & { totalSize: number; - sizeLoaded?: boolean; + calculatingSize: boolean; modules: AddonStorageManagerModule[]; }; type AddonStorageManagerModule = CoreCourseModuleData & { totalSize?: number; - sizeLoaded?: boolean; + calculatingSize: boolean; prefetchHandler?: CoreCourseModulePrefetchHandler; spinner?: boolean; downloadStatus?: string; From 0298273fc4c62b88b8473790d64cbaf976d6d246 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 29 Mar 2022 12:39:18 +0200 Subject: [PATCH 5/8] MOBILE-3833 course: Collapse sections in downloads page --- .../pages/course-storage/course-storage.html | 84 ++++++++++--------- .../pages/course-storage/course-storage.ts | 30 ++++++- .../course-format/course-format.html | 5 ++ .../components/course-format/course-format.ts | 64 +++++++++----- .../components/course-index/course-index.html | 56 +++++++------ .../course/pages/contents/contents.html | 5 -- .../course/pages/contents/contents.ts | 8 -- 7 files changed, 152 insertions(+), 100 deletions(-) diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.html b/src/addons/storagemanager/pages/course-storage/course-storage.html index 57b45f33c..2df7b3282 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.html +++ b/src/addons/storagemanager/pages/course-storage/course-storage.html @@ -47,7 +47,13 @@ - + + +

- - - - - - -

- - -

- - - {{ module.totalSize | coreBytesToSize }} - - - {{ 'core.calculating' | translate }} - -
+ + + + + + + +

+ + +

+ + + {{ module.totalSize | coreBytesToSize }} + + + {{ 'core.calculating' | translate }} + +
-
- - - - - - -
-
+
+ + + + + + +
+
+
diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.ts b/src/addons/storagemanager/pages/course-storage/course-storage.ts index 39c3d42d0..6aa817913 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.ts +++ b/src/addons/storagemanager/pages/course-storage/course-storage.ts @@ -13,7 +13,7 @@ // limitations under the License. import { CoreConstants } from '@/core/constants'; -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, ElementRef, OnDestroy, OnInit } from '@angular/core'; import { CoreCourse, CoreCourseProvider } from '@features/course/services/course'; import { CoreCourseHelper, @@ -30,6 +30,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; +import { CoreDom } from '@singletons/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; /** @@ -62,6 +63,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { statusDownloaded = CoreConstants.DOWNLOADED; + protected initialSectionId?: number; protected siteUpdatedObserver?: CoreEventObserver; protected courseStatusObserver?: CoreEventObserver; protected sectionStatusObserver?: CoreEventObserver; @@ -69,7 +71,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { protected isDestroyed = false; protected isGuest = false; - constructor() { + constructor(protected elementRef: ElementRef) { // Refresh the enabled flags if site is updated. this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite(); @@ -100,16 +102,19 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { } this.isGuest = !!CoreNavigator.getRouteBooleanParam('isGuest'); + this.initialSectionId = CoreNavigator.getRouteNumberParam('sectionId'); this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite(); this.downloadEnabled = !CoreSites.getRequiredCurrentSite().isOfflineDisabled(); - const sections = await CoreCourse.getSections(this.courseId, false, true); + const sections = (await CoreCourse.getSections(this.courseId, false, true)) + .filter((section) => !CoreCourseHelper.isSectionStealth(section)); this.sections = (await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId)).sections .map(section => ({ ...section, totalSize: 0, calculatingSize: true, + expanded: section.id === this.initialSectionId, modules: section.modules.map(module => ({ ...module, calculatingSize: true, @@ -118,6 +123,12 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { this.loaded = true; + CoreDom.scrollToElement( + this.elementRef.nativeElement, + '.core-course-storage-section-expanded', + { addYAxis: -10 }, + ); + await Promise.all([ this.initSizes(), this.initCoursePrefetch(), @@ -641,6 +652,18 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { } } + /** + * Toggle expand status. + * + * @param event Event object. + * @param section Section to expand / collapse. + */ + toggleExpand(event: Event, section: AddonStorageManagerCourseSection): void { + section.expanded = !section.expanded; + event.stopPropagation(); + event.preventDefault(); + } + /** * @inheritdoc */ @@ -663,6 +686,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { type AddonStorageManagerCourseSection = Omit & { totalSize: number; calculatingSize: boolean; + expanded: boolean; modules: AddonStorageManagerModule[]; }; diff --git a/src/core/features/course/components/course-format/course-format.html b/src/core/features/course/components/course-format/course-format.html index 2d8cd3391..4031d1654 100644 --- a/src/core/features/course/components/course-format/course-format.html +++ b/src/core/features/course/components/course-format/course-format.html @@ -1,3 +1,8 @@ + + + + + diff --git a/src/core/features/course/components/course-format/course-format.ts b/src/core/features/course/components/course-format/course-format.ts index dca3d5443..c1bee68f6 100644 --- a/src/core/features/course/components/course-format/course-format.ts +++ b/src/core/features/course/components/course-format/course-format.ts @@ -391,29 +391,38 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { ); } + /** + * Get selected section ID. If viewing all sections, use current scrolled section. + * + * @return Section ID, undefined if not found. + */ + protected async getSelectedSectionId(): Promise { + if (this.selectedSection?.id !== this.allSectionsId) { + return this.selectedSection?.id; + } + + // Check current scrolled section. + const allSectionElements: NodeListOf = + this.elementRef.nativeElement.querySelectorAll('section.core-course-module-list-wrapper'); + + const scroll = await this.content.getScrollElement(); + const containerTop = scroll.getBoundingClientRect().top; + + const element = Array.from(allSectionElements).find((element) => { + const position = element.getBoundingClientRect(); + + // The bottom is inside the container or lower. + return position.bottom >= containerTop; + }); + + return Number(element?.getAttribute('id')) || undefined; + } + /** * Display the course index modal. */ async openCourseIndex(): Promise { - let selectedId = this.selectedSection?.id; - - if (selectedId == this.allSectionsId) { - // Check current scrolled section. - const allSectionElements: NodeListOf = - this.elementRef.nativeElement.querySelectorAll('section.section-wrapper'); - - const scroll = await this.content.getScrollElement(); - const containerTop = scroll.getBoundingClientRect().top; - - const element = Array.from(allSectionElements).find((element) => { - const position = element.getBoundingClientRect(); - - // The bottom is inside the container or lower. - return position.bottom >= containerTop; - }); - - selectedId = Number(element?.getAttribute('id')) || undefined; - } + const selectedId = await this.getSelectedSectionId(); const data = await CoreDomUtils.openModal({ component: CoreCourseCourseIndexComponent, @@ -453,6 +462,23 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.moduleId = data.moduleId; } + /** + * Open course downloads page. + */ + async gotoCourseDownloads(): Promise { + const selectedId = await this.getSelectedSectionId(); + + CoreNavigator.navigateToSitePath( + `storage/${this.course.id}`, + { + params: { + title: this.course.fullname, + sectionId: selectedId, + }, + }, + ); + } + /** * Function called when selected section changes. * diff --git a/src/core/features/course/components/course-index/course-index.html b/src/core/features/course/components/course-index/course-index.html index 892a63767..8de92a89b 100644 --- a/src/core/features/course/components/course-index/course-index.html +++ b/src/core/features/course/components/course-index/course-index.html @@ -48,34 +48,36 @@ - - - - - - - - - - - -

- - -

-
- -
+
+ + + + + + + + + + + +

+ + +

+
+ +
+
- +
diff --git a/src/core/features/course/pages/contents/contents.html b/src/core/features/course/pages/contents/contents.html index bc3f404f8..2d0eeb1db 100644 --- a/src/core/features/course/pages/contents/contents.html +++ b/src/core/features/course/pages/contents/contents.html @@ -1,8 +1,3 @@ - - - - - diff --git a/src/core/features/course/pages/contents/contents.ts b/src/core/features/course/pages/contents/contents.ts index 81953a209..7413a0444 100644 --- a/src/core/features/course/pages/contents/contents.ts +++ b/src/core/features/course/pages/contents/contents.ts @@ -366,14 +366,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy { } } - gotoCourseDownloads(): void { - CoreNavigator.navigateToSitePath( - `storage/${this.course.id}`, - { params: { title: this.course.fullname } }, - ); - - } - /** * @inheritdoc */ From ca25ad0420e8bd1281f7ac9b9d727f1b8369578b Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 29 Mar 2022 13:22:52 +0200 Subject: [PATCH 6/8] MOBILE-3833 config: Remove unused globalization plugin --- config.xml | 5 ----- package-lock.json | 18 ------------------ package.json | 4 +--- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/config.xml b/config.xml index bfcacc07b..da7166bf5 100644 --- a/config.xml +++ b/config.xml @@ -130,11 +130,6 @@ - - - - - diff --git a/package-lock.json b/package-lock.json index 40f640b46..a73545b60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,7 +71,6 @@ "cordova-plugin-file": "6.0.2", "cordova-plugin-file-opener2": "3.0.5", "cordova-plugin-geolocation": "4.1.0", - "cordova-plugin-globalization": "1.11.0", "cordova-plugin-ionic-keyboard": "2.2.0", "cordova-plugin-media": "5.0.4", "cordova-plugin-media-capture": "3.0.3", @@ -11389,18 +11388,6 @@ } } }, - "node_modules/cordova-plugin-globalization": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/cordova-plugin-globalization/-/cordova-plugin-globalization-1.11.0.tgz", - "integrity": "sha1-6sMVgQAphJOvowvolA5pj2HvvP4=", - "engines": { - "cordovaDependencies": { - "2.0.0": { - "cordova": ">100" - } - } - } - }, "node_modules/cordova-plugin-ionic-keyboard": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-keyboard/-/cordova-plugin-ionic-keyboard-2.2.0.tgz", @@ -40148,11 +40135,6 @@ "resolved": "https://registry.npmjs.org/cordova-plugin-geolocation/-/cordova-plugin-geolocation-4.1.0.tgz", "integrity": "sha512-y5io/P10xGMxSn2KEqfv/fExK47eA1pmSonJdmDqDsaSADV9JpgdPx0mUSA08+5pzma/OS9R0LoODeDPx7Jvjg==" }, - "cordova-plugin-globalization": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/cordova-plugin-globalization/-/cordova-plugin-globalization-1.11.0.tgz", - "integrity": "sha1-6sMVgQAphJOvowvolA5pj2HvvP4=" - }, "cordova-plugin-ionic-keyboard": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-keyboard/-/cordova-plugin-ionic-keyboard-2.2.0.tgz", diff --git a/package.json b/package.json index 295ce081c..767ed5d13 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,6 @@ "cordova-plugin-file": "6.0.2", "cordova-plugin-file-opener2": "3.0.5", "cordova-plugin-geolocation": "4.1.0", - "cordova-plugin-globalization": "1.11.0", "cordova-plugin-ionic-keyboard": "2.2.0", "cordova-plugin-media": "5.0.4", "cordova-plugin-media-capture": "3.0.3", @@ -236,7 +235,6 @@ "ANDROIDX_VERSION": "1.0.0", "ANDROIDX_APPCOMPAT_VERSION": "1.3.1" }, - "cordova-plugin-globalization": {}, "@moodlehq/cordova-plugin-file-transfer": {}, "cordova-plugin-prevent-override": {}, "cordova-plugin-androidx-adapter": {} @@ -245,4 +243,4 @@ "optionalDependencies": { "keytar": "7.2.0" } -} +} \ No newline at end of file From 6dadd7b9a64697ad7e63841a520164facd477317 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 30 Mar 2022 09:38:33 +0200 Subject: [PATCH 7/8] MOBILE-3833 core: Fix handle links with URL scheme --- .../features/contentlinks/services/contentlinks-helper.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/features/contentlinks/services/contentlinks-helper.ts b/src/core/features/contentlinks/services/contentlinks-helper.ts index 8c5ccd06c..e4d6379dd 100644 --- a/src/core/features/contentlinks/services/contentlinks-helper.ts +++ b/src/core/features/contentlinks/services/contentlinks-helper.ts @@ -21,6 +21,7 @@ import { makeSingleton, Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; import { Params } from '@angular/router'; import { CoreContentLinksChooseSiteModalComponent } from '../components/choose-site-modal/choose-site-modal'; +import { CoreCustomURLSchemes } from '@services/urlschemes'; /** * Service that provides some features regarding content links. @@ -138,6 +139,12 @@ export class CoreContentLinksHelperProvider { openBrowserRoot?: boolean, ): Promise { try { + if (CoreCustomURLSchemes.isCustomURL(url)) { + await CoreCustomURLSchemes.handleCustomURL(url); + + return true; + } + if (checkRoot) { const data = await CoreSites.isStoredRootURL(url, username); From 9884ceb6b34164c770ba5d3e59332b5cfda8522f Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 30 Mar 2022 09:38:55 +0200 Subject: [PATCH 8/8] MOBILE-3833 ios: Fix handle iframe links in iOS --- src/core/initializers/inject-ios-scripts.ts | 3 ++- src/core/services/utils/iframe.ts | 19 +++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/core/initializers/inject-ios-scripts.ts b/src/core/initializers/inject-ios-scripts.ts index 64b26993d..cfd717666 100644 --- a/src/core/initializers/inject-ios-scripts.ts +++ b/src/core/initializers/inject-ios-scripts.ts @@ -17,10 +17,11 @@ import { CoreIframeUtils } from '@services/utils/iframe'; import { Platform } from '@singletons'; export default async function(): Promise { + await Platform.ready(); + if (!CoreApp.isIOS() || !('WKUserScript' in window)) { return; } - await Platform.ready(); CoreIframeUtils.injectiOSScripts(window); } diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index 1faf9308e..08745cb44 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -446,26 +446,13 @@ export class CoreIframeUtilsProvider { } else { element.setAttribute('src', url); } - } else if (CoreUrlUtils.isLocalFileUrl(url)) { - // It's a local file. - const filename = url.substring(url.lastIndexOf('/') + 1); - - if (!CoreFileHelper.isOpenableInApp({ filename })) { - try { - await CoreFileHelper.showConfirmOpenUnsupportedFile(); - } catch (error) { - return; // Cancelled, stop. - } - } - + } else { try { - await CoreUtils.openFile(url); + // It's an external link or a local file, check if it can be opened in the app. + await CoreWindow.open(url, name); } catch (error) { CoreDomUtils.showErrorModal(error); } - } else { - // It's an external link, check if it can be opened in the app. - await CoreWindow.open(url, name); } }