diff --git a/package-lock.json b/package-lock.json index ea2219902..db53b00b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "@ionic-native/status-bar": "^5.33.0", "@ionic-native/web-intent": "^5.33.0", "@ionic-native/zip": "^5.33.0", - "@ionic/angular": "^5.6.6", + "@ionic/angular": "^5.9.2", "@moodlehq/cordova-plugin-file-transfer": "1.7.1-moodle.2", "@moodlehq/cordova-plugin-inappbrowser": "5.0.0-moodle.3", "@moodlehq/cordova-plugin-ionic-webview": "5.0.0-moodle.1", @@ -3695,11 +3695,11 @@ "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ=" }, "node_modules/@ionic/angular": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.6.6.tgz", - "integrity": "sha512-0psh2n4Y/3sx0e2Yj4WmNcukz0nrETEiJE6Fl4CldoB8QHZcXGi0hKrPAcbGSAF0+lAJ58+Z5Gp/HQVm/MQOMA==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.9.2.tgz", + "integrity": "sha512-5GzKg+l4au3xFECky2v/USlRsmTAXgvNO5Zalt7NUXc//VJIL2lQvswojE6FBWuM/xR5W0CWbJdFth19TaZWVQ==", "dependencies": { - "@ionic/core": "5.6.6", + "@ionic/core": "5.9.2", "tslib": "^1.9.3" }, "peerDependencies": { @@ -4197,20 +4197,15 @@ } }, "node_modules/@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.2.tgz", + "integrity": "sha512-1ZqSBS8R6tGQsc+LsLxIRv0q3Ww6jwgJXLvdn6FmVWfpPbBvT+CjCuU9hqJ5qwM+atErblUMYSexvvpws8lGAA==", "dependencies": { "@stencil/core": "^2.4.0", - "ionicons": "^5.5.1", + "ionicons": "^5.5.3", "tslib": "^2.1.0" } }, - "node_modules/@ionic/core/node_modules/tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" - }, "node_modules/@ionic/utils-array": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@ionic/utils-array/-/utils-array-2.1.5.tgz", @@ -5129,7 +5124,6 @@ "version": "5.0.0-moodle.3", "resolved": "https://registry.npmjs.org/@moodlehq/cordova-plugin-inappbrowser/-/cordova-plugin-inappbrowser-5.0.0-moodle.3.tgz", "integrity": "sha512-BDW53W8BzHIJY6lqV3IyYIO9Rh3qi/nA3qkwZjvJiw7iohlQMeR67LV+bXjM4I8N1PTGoBSXiS5BmaS9NFi/1A==", - "dev": true, "engines": { "cordovaDependencies": { "0.2.3": { @@ -5657,9 +5651,9 @@ } }, "node_modules/@stencil/core": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.2.tgz", - "integrity": "sha512-bgjPXkSzzg1WnTgVUm6m5ZzpKt602WmA/QljODAW1xVN40OHJdbGblzF/F6MFzqv2c5Cy30CB41arc8qADIdcQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.11.0.tgz", + "integrity": "sha512-/IubCWhVXCguyMUp/3zGrg3c882+RJNg/zpiKfyfJL3kRCOwe+/MD8OoAXVGdd+xAohZKIi1Ik+EHFlsptsjLg==", "bin": { "stencil": "bin/stencil" }, @@ -17077,11 +17071,23 @@ } }, "node_modules/ionicons": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz", - "integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.4.tgz", + "integrity": "sha512-3ph8X9my3inhabWEZ7N0XRA0MnnNQ1v9a602mLNgWsIXnxE9G5BybIZ/pws/OZZ/hoNlvSjk801N03yL9/FNgQ==", "dependencies": { - "@stencil/core": "^2.5.0" + "@stencil/core": "~2.10.0" + } + }, + "node_modules/ionicons/node_modules/@stencil/core": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.10.0.tgz", + "integrity": "sha512-15rWMTPQ/sp0lSV82HVCXkIya3QLN+uBl7pqK4JnTrp4HiLrzLmNbWjbvgCs55gw0lULbCIGbRIEsFz+Pe/Q+A==", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=12.10.0", + "npm": ">=6.0.0" } }, "node_modules/ios-sim": { @@ -28592,9 +28598,9 @@ } }, "node_modules/tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "node_modules/tsutils": { "version": "3.17.1", @@ -34108,11 +34114,11 @@ } }, "@ionic/angular": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.6.6.tgz", - "integrity": "sha512-0psh2n4Y/3sx0e2Yj4WmNcukz0nrETEiJE6Fl4CldoB8QHZcXGi0hKrPAcbGSAF0+lAJ58+Z5Gp/HQVm/MQOMA==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.9.2.tgz", + "integrity": "sha512-5GzKg+l4au3xFECky2v/USlRsmTAXgvNO5Zalt7NUXc//VJIL2lQvswojE6FBWuM/xR5W0CWbJdFth19TaZWVQ==", "requires": { - "@ionic/core": "5.6.6", + "@ionic/core": "5.9.2", "tslib": "^1.9.3" }, "dependencies": { @@ -34475,20 +34481,13 @@ } }, "@ionic/core": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.6.tgz", - "integrity": "sha512-EbVIXOTVVPxBo7hsarBpRSFNsQ22wBFtWkKmrmliieknG5LUkf5WZBpj4EENQhzYA6c+//7/nfhcD9pWgtAofA==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.2.tgz", + "integrity": "sha512-1ZqSBS8R6tGQsc+LsLxIRv0q3Ww6jwgJXLvdn6FmVWfpPbBvT+CjCuU9hqJ5qwM+atErblUMYSexvvpws8lGAA==", "requires": { "@stencil/core": "^2.4.0", - "ionicons": "^5.5.1", + "ionicons": "^5.5.3", "tslib": "^2.1.0" - }, - "dependencies": { - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" - } } }, "@ionic/utils-array": { @@ -35199,8 +35198,7 @@ "@moodlehq/cordova-plugin-inappbrowser": { "version": "5.0.0-moodle.3", "resolved": "https://registry.npmjs.org/@moodlehq/cordova-plugin-inappbrowser/-/cordova-plugin-inappbrowser-5.0.0-moodle.3.tgz", - "integrity": "sha512-BDW53W8BzHIJY6lqV3IyYIO9Rh3qi/nA3qkwZjvJiw7iohlQMeR67LV+bXjM4I8N1PTGoBSXiS5BmaS9NFi/1A==", - "dev": true + "integrity": "sha512-BDW53W8BzHIJY6lqV3IyYIO9Rh3qi/nA3qkwZjvJiw7iohlQMeR67LV+bXjM4I8N1PTGoBSXiS5BmaS9NFi/1A==" }, "@moodlehq/cordova-plugin-ionic-webview": { "version": "5.0.0-moodle.1", @@ -35562,9 +35560,9 @@ } }, "@stencil/core": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.2.tgz", - "integrity": "sha512-bgjPXkSzzg1WnTgVUm6m5ZzpKt602WmA/QljODAW1xVN40OHJdbGblzF/F6MFzqv2c5Cy30CB41arc8qADIdcQ==" + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.11.0.tgz", + "integrity": "sha512-/IubCWhVXCguyMUp/3zGrg3c882+RJNg/zpiKfyfJL3kRCOwe+/MD8OoAXVGdd+xAohZKIi1Ik+EHFlsptsjLg==" }, "@szmarczak/http-timer": { "version": "1.1.2", @@ -44594,11 +44592,18 @@ "dev": true }, "ionicons": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz", - "integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.4.tgz", + "integrity": "sha512-3ph8X9my3inhabWEZ7N0XRA0MnnNQ1v9a602mLNgWsIXnxE9G5BybIZ/pws/OZZ/hoNlvSjk801N03yL9/FNgQ==", "requires": { - "@stencil/core": "^2.5.0" + "@stencil/core": "~2.10.0" + }, + "dependencies": { + "@stencil/core": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.10.0.tgz", + "integrity": "sha512-15rWMTPQ/sp0lSV82HVCXkIya3QLN+uBl7pqK4JnTrp4HiLrzLmNbWjbvgCs55gw0lULbCIGbRIEsFz+Pe/Q+A==" + } } }, "ios-sim": { @@ -53782,9 +53787,9 @@ } }, "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "tsutils": { "version": "3.17.1", diff --git a/package.json b/package.json index 6a006d22f..b093c50ae 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@ionic-native/status-bar": "^5.33.0", "@ionic-native/web-intent": "^5.33.0", "@ionic-native/zip": "^5.33.0", - "@ionic/angular": "^5.6.6", + "@ionic/angular": "^5.9.2", "@moodlehq/cordova-plugin-file-transfer": "1.7.1-moodle.2", "@moodlehq/cordova-plugin-inappbrowser": "5.0.0-moodle.3", "@moodlehq/cordova-plugin-ionic-webview": "5.0.0-moodle.1", @@ -124,7 +124,7 @@ "nl.kingsquare.cordova.background-audio": "^1.0.1", "rxjs": "~6.5.5", "ts-md5": "^1.2.7", - "tslib": "^2.0.1", + "tslib": "^2.3.1", "zone.js": "~0.10.3" }, "devDependencies": { diff --git a/src/addons/messages/pages/discussion/discussion.page.ts b/src/addons/messages/pages/discussion/discussion.page.ts index bdff8c4f9..ca9028029 100644 --- a/src/addons/messages/pages/discussion/discussion.page.ts +++ b/src/addons/messages/pages/discussion/discussion.page.ts @@ -495,7 +495,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView /** * Set the new message badge number and set scroll listener if needed. * - * @param addMessages NUmber of messages still to be read. + * @param addMessages Number of messages still to be read. */ protected setNewMessagesBadge(addMessages: number): void { if (this.newMessages == 0 && addMessages > 0) { diff --git a/src/core/components/swipe-navigation/swipe-navigation.scss b/src/core/components/swipe-navigation/swipe-navigation.scss index 05c7d60e5..046438a5a 100644 --- a/src/core/components/swipe-navigation/swipe-navigation.scss +++ b/src/core/components/swipe-navigation/swipe-navigation.scss @@ -9,6 +9,7 @@ ion-slide { ::ng-deep { core-loading .core-loading-content { + display: block; width: 100%; } diff --git a/src/core/directives/collapsible-header.ts b/src/core/directives/collapsible-header.ts index 626a5e7b6..656d5d15e 100644 --- a/src/core/directives/collapsible-header.ts +++ b/src/core/directives/collapsible-header.ts @@ -106,6 +106,12 @@ export class CoreCollapsibleHeaderDirective implements OnDestroy { return; } + // Wait animations to finish. + const animations = this.content.getAnimations(); + await Promise.all(animations.map(async (animation) => { + await animation.finished; + })); + const title = this.content.querySelector('.collapsible-title, h1'); const contentH1 = this.content.querySelector('h1'); const headerH1 = this.header.querySelector('h1'); @@ -133,11 +139,17 @@ export class CoreCollapsibleHeaderDirective implements OnDestroy { const contentH1Styles = getComputedStyle(contentH1); if (Platform.isRTL) { - this.h1StartDifference = contentH1.getBoundingClientRect().right - - (headerH1.getBoundingClientRect().right - parseFloat(headerH1Styles.paddingRight)); + // Checking position over parent because transition may not be finished. + const contentH1Position = contentH1.getBoundingClientRect().right - this.content.getBoundingClientRect().right; + const headerH1Position = headerH1.getBoundingClientRect().right - this.header.getBoundingClientRect().right; + + this.h1StartDifference = Math.round(contentH1Position - (headerH1Position - parseFloat(headerH1Styles.paddingRight))); } else { - this.h1StartDifference = contentH1.getBoundingClientRect().left - - (headerH1.getBoundingClientRect().left + parseFloat(headerH1Styles.paddingLeft)); + // Checking position over parent because transition may not be finished. + const contentH1Position = contentH1.getBoundingClientRect().left - this.content.getBoundingClientRect().left; + const headerH1Position = headerH1.getBoundingClientRect().left - this.header.getBoundingClientRect().left; + + this.h1StartDifference = Math.round(contentH1Position - (headerH1Position + parseFloat(headerH1Styles.paddingLeft))); } this.headerH1FontSize = parseFloat(headerH1Styles.fontSize); @@ -145,7 +157,9 @@ export class CoreCollapsibleHeaderDirective implements OnDestroy { // Transfer font styles. Array.from(headerH1Styles).forEach((styleName) => { - if (styleName != 'font-size' && (styleName.startsWith('font-') || styleName.startsWith('letter-'))) { + if (styleName != 'font-size' && + styleName != 'font-family' && + (styleName.startsWith('font-') || styleName.startsWith('letter-'))) { contentH1.style.setProperty(styleName, headerH1Styles.getPropertyValue(styleName)); } }); diff --git a/src/core/features/course/components/module-navigation/module-navigation.ts b/src/core/features/course/components/module-navigation/module-navigation.ts index dfb9602a4..c6cc18ae9 100644 --- a/src/core/features/course/components/module-navigation/module-navigation.ts +++ b/src/core/features/course/components/module-navigation/module-navigation.ts @@ -23,6 +23,7 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreMath } from '@singletons/math'; /** * Component to show a button to go to the next resource/activity. @@ -50,6 +51,8 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { protected initialHeight = 0; protected initialPaddingBottom = 0; protected previousTop = 0; + protected previousHeight = 0; + protected stickTimeout?: number; protected content?: HTMLIonContentElement | null; protected completionObserver: CoreEventObserver; @@ -102,6 +105,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { } // Set a minimum height value. this.initialHeight = this.initialHeight || 56; + this.previousHeight = this.initialHeight; this.content = this.element.closest('ion-content'); @@ -118,6 +122,8 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { return; } + this.content.classList.add('has-core-course-module-navigation'); + // Move element to the nearest ion-content if it's not the parent. if (this.element.parentElement?.nodeName != 'ION-CONTENT') { this.content.appendChild(this.element); @@ -135,7 +141,7 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { return; } - this.onScroll(e.detail.scrollTop, scroll.scrollHeight - scroll.offsetHeight); + this.onScroll(e.detail, scroll); }); } @@ -304,19 +310,21 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { /** * On scroll function. * - * @param top Scroll top measure. - * @param maxScroll Scroll height. + * @param scrollDetail Scroll detail object. + * @param scrollElement Scroll element to calculate maxScroll. */ - protected onScroll(top: number, maxScroll: number): void { - if (top == 0 || top == maxScroll) { + protected onScroll(scrollDetail: ScrollDetail, scrollElement: HTMLElement): void { + const maxScroll = scrollElement.scrollHeight - scrollElement.offsetHeight; + if (scrollDetail.scrollTop <= 0 || scrollDetail.scrollTop >= maxScroll) { // Reset. this.setBarHeight(this.initialHeight); } else { - const diffHeight = this.element.clientHeight - (top - this.previousTop); - this.setBarHeight(diffHeight); - } + let newHeight = this.previousHeight - (scrollDetail.scrollTop - this.previousTop); + newHeight = CoreMath.clamp(newHeight, 0, this.initialHeight); - this.previousTop = top; + this.setBarHeight(newHeight); + } + this.previousTop = scrollDetail.scrollTop; } /** @@ -325,14 +333,20 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy { * @param height The new bar height. */ protected setBarHeight(height: number): void { - if (height <= 0) { - height = 0; - } else if (height > this.initialHeight) { - height = this.initialHeight; + if (this.stickTimeout) { + clearTimeout(this.stickTimeout); } - this.element.style.opacity = height == 0 ? '0' : '1'; + this.element.style.opacity = height <= 0 ? '0' : '1'; this.content?.style.setProperty('--core-course-module-navigation-height', height + 'px'); + this.previousHeight = height; + + if (height > 0 && height < this.initialHeight) { + // Finish opening or closing the bar. + const newHeight = height < this.initialHeight / 2 ? 0 : this.initialHeight; + + this.stickTimeout = window.setTimeout(() => this.setBarHeight(newHeight), 500); + } } } diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index 51f3cb7f2..d13635f92 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -459,7 +459,7 @@ body.core-iframe-fullscreen ion-router-outlet { @supports (padding-left: constant(safe-area-inset-left)) { --ion-safe-area-left: constant(safe-area-inset-left); } - + @supports (padding-left: env(safe-area-inset-left)) { --ion-safe-area-left: env(safe-area-inset-left); } @@ -539,7 +539,7 @@ body.core-iframe-fullscreen ion-router-outlet { .core-modal-lateral-#{$breakpoint} { --ion-safe-area-left: 0px; --ion-safe-area-right: 0px; - + .modal-wrapper { position: absolute; @include position(0 !important, 0 !important, 0 !important, unset !important); @@ -554,7 +554,7 @@ body.core-iframe-fullscreen ion-router-outlet { } } } - + } // Hidden submit button. @@ -911,9 +911,9 @@ ion-fab[core-fab] { ion-fab-button::part(close-icon) { display: none; } -} +} -core-course-module-navigation + ion-fab { +ion-content.has-core-course-module-navigation ion-fab { bottom: calc(var(--core-course-module-navigation-height, 0px) + 10px); @include core-transition(all, 200ms); }