From 64dd36a5e2b754221bc3a53929413db11c9b01b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 4 Jun 2021 12:25:30 +0200 Subject: [PATCH 1/6] MOBILE-3320 core: Add format text placeholder when loading --- src/core/directives/format-text.ts | 32 +++++-- src/core/directives/tests/format-text.test.ts | 2 +- .../components/format/core-course-format.html | 5 +- src/theme/bootstrap.scss | 1 + src/theme/components/format-text.scss | 94 +++++++++++++++---- 5 files changed, 104 insertions(+), 30 deletions(-) diff --git a/src/core/directives/format-text.ts b/src/core/directives/format-text.ts index 16ee00021..adb0641a3 100644 --- a/src/core/directives/format-text.ts +++ b/src/core/directives/format-text.ts @@ -72,6 +72,7 @@ export class CoreFormatTextDirective implements OnChanges { @Input() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the text for some reason. @Input() captureLinks?: boolean; // Whether links should tried to be opened inside the app. Defaults to true. @Input() openLinksInApp?: boolean; // Whether links should be opened in InAppBrowser. + @Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty. /** * Max height in pixels to render the content box. It should be 50 at least to make sense. @@ -86,6 +87,8 @@ export class CoreFormatTextDirective implements OnChanges { protected element: HTMLElement; protected showMoreDisplayed = false; protected loadingChangedListener?: CoreEventObserver; + protected emptyText = ''; + protected contentSpan: HTMLElement; constructor( element: ElementRef, @@ -93,9 +96,20 @@ export class CoreFormatTextDirective implements OnChanges { protected viewContainerRef: ViewContainerRef, protected sanitizer: DomSanitizer, ) { - this.element = element.nativeElement; - this.element.classList.add('opacity-hide'); // Hide contents until they're treated. + this.element.classList.add('core-format-text-loading'); // Hide contents until they're treated. + + const placeholder = document.createElement('span'); + placeholder.classList.add('core-format-text-loader'); + this.element.appendChild(placeholder); + + this.contentSpan = document.createElement('span'); + this.contentSpan.classList.add('core-format-text-content'); + this.element.appendChild(this.contentSpan); + + this.emptyText = this.hideIfEmpty ? '' : ' '; + this.contentSpan.innerHTML = this.emptyText; + this.afterRender = new EventEmitter(); this.element.addEventListener('click', this.elementClicked.bind(this)); @@ -183,7 +197,7 @@ export class CoreFormatTextDirective implements OnChanges { * Add magnifying glass icons to view adapted images at full size. */ addMagnifyingGlasses(): void { - const imgs = Array.from(this.element.querySelectorAll('.core-adapted-img-container > img')); + const imgs = Array.from(this.contentSpan.querySelectorAll('.core-adapted-img-container > img')); if (!imgs.length) { return; } @@ -339,7 +353,7 @@ export class CoreFormatTextDirective implements OnChanges { */ protected finishRender(): void { // Show the element again. - this.element.classList.remove('opacity-hide'); + this.element.classList.remove('core-format-text-loading'); // Emit the afterRender output. this.afterRender.emit(); } @@ -349,7 +363,7 @@ export class CoreFormatTextDirective implements OnChanges { */ protected async formatAndRenderContents(): Promise { if (!this.text) { - this.element.innerHTML = ''; // Remove current contents. + this.contentSpan.innerHTML = this.emptyText; // Remove current contents. this.finishRender(); return; @@ -370,12 +384,12 @@ export class CoreFormatTextDirective implements OnChanges { // Disable media adapt to correctly calculate the height. this.element.classList.add('core-disable-media-adapt'); - this.element.innerHTML = ''; // Remove current contents. + this.contentSpan.innerHTML = ''; // Remove current contents. if (this.maxHeight && result.div.innerHTML != '' && (this.fullOnClick || (window.innerWidth < 576 || window.innerHeight < 576))) { // Don't collapse in big screens. // Move the children to the current element to be able to calculate the height. - CoreDomUtils.moveChildren(result.div, this.element); + CoreDomUtils.moveChildren(result.div, this.contentSpan); // Calculate the height now. this.calculateHeight(); @@ -396,7 +410,7 @@ export class CoreFormatTextDirective implements OnChanges { }); } } else { - CoreDomUtils.moveChildren(result.div, this.element); + CoreDomUtils.moveChildren(result.div, this.contentSpan); // Add magnifying glasses to images. this.addMagnifyingGlasses(); @@ -405,7 +419,7 @@ export class CoreFormatTextDirective implements OnChanges { if (result.options.filter) { // Let filters handle HTML. We do it here because we don't want them to block the render of the text. CoreFilterDelegate.handleHtml( - this.element, + this.contentSpan, result.filters, this.viewContainerRef, result.options, diff --git a/src/core/directives/tests/format-text.test.ts b/src/core/directives/tests/format-text.test.ts index d9b2da208..f0fc1d7d0 100644 --- a/src/core/directives/tests/format-text.test.ts +++ b/src/core/directives/tests/format-text.test.ts @@ -66,7 +66,7 @@ describe('CoreFormatTextDirective', () => { ); // Assert - const text = fixture.nativeElement.querySelector('core-format-text'); + const text = fixture.nativeElement.querySelector('core-format-text .core-format-text-content'); expect(text).not.toBeNull(); expect(text.innerHTML).toEqual(sentence); }); diff --git a/src/core/features/course/components/format/core-course-format.html b/src/core/features/course/components/format/core-course-format.html index 785725e7b..3995c6be0 100644 --- a/src/core/features/course/components/format/core-course-format.html +++ b/src/core/features/course/components/format/core-course-format.html @@ -142,7 +142,10 @@ - + + + + diff --git a/src/theme/bootstrap.scss b/src/theme/bootstrap.scss index 9c819d497..0be89e900 100644 --- a/src/theme/bootstrap.scss +++ b/src/theme/bootstrap.scss @@ -9,6 +9,7 @@ clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; + display: block !important; } .sr-only-focusable:active, .sr-only-focusable:focus { diff --git a/src/theme/components/format-text.scss b/src/theme/components/format-text.scss index c1f41259c..4c0daaee8 100644 --- a/src/theme/components/format-text.scss +++ b/src/theme/components/format-text.scss @@ -2,22 +2,70 @@ /** Styles of elements inside the directive should be placed in format-text.scss */ @import "~theme/globals"; -:root { - --background: var(--background, #{$ion-item-background}); - --background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background)}); - --viewer-icon-background: rgba(255, 255, 255, .5); +core-format-text { + --core-format-text-background: var(--background, #{$ion-item-background}); + --core-format-text-background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background)}); + --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); + --core-format-text-loader-shine: 251,251,251; } -:root body.dark { - --background: var(--background, #{$ion-item-background-dark}); - --background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background-dark)}); - --viewer-icon-background: rgba(0, 0, 0, .5); +body.dark core-format-text { + --core-format-text-background: var(--background, #{$ion-item-background-dark}); + --core-format-text-background-gradient-rgb: var(--background-rgb, #{color-to-rgb-list($ion-item-background-dark)}); + --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); + --core-format-text-loader-shine: 90,90,90; } core-format-text { - user-select: text; - word-break: break-word; - word-wrap: break-word; + display: contents; + + .core-format-text-loader { + opacity: 0; + @include core-transition(opacity, 200ms); + display: contents; + } + + &.core-format-text-loading { + position: relative; + width: 100%; + height: 100%; + opacity: 1; + background-color: rgba(0,0,0,.1); + overflow: hidden; + border-radius: 5px; + display: block; + + .core-format-text-loader { + position: absolute; + left: -45%; + height: 100%; + width: 45%; + background-image: -webkit-linear-gradient(to left, rgba(var(--core-format-text-loader-shine), .05), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .6), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .05)); + background-image: linear-gradient(to left, rgba(var(--core-format-text-loader-shine), .05), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .6), rgba(var(--core-format-text-loader-shine), .3), rgba(var(--core-format-text-loader-shine), .05)); + animation: loading 1s infinite; + opacity: 1; + display: inline; + } + + .core-format-text-content { + opacity: 0; + display: inline; + } + + .core-show-more { + display: none !important; + } + } + + .core-format-text-content { + opacity: 1; + @include core-transition(opacity, 200ms); + + display: contents; + user-select: text; + word-break: break-word; + word-wrap: break-word; + } &[maxHeight], &[ng-reflect-max-height] { @@ -57,7 +105,7 @@ core-format-text { position: absolute; @include position(null, 0, 0, null); z-index: 7; - background-color: var(--background); + background-color: var(--core-format-text-background); color: var(--text-color); @include padding(null, null, null, 10px); margin: 0; @@ -68,10 +116,8 @@ core-format-text { height: 100%; position: absolute; @include position(null, 0, 0, 0); - background: -moz-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); - background: -webkit-gradient(left top, left bottom, color-stop(calc(100% - 50px), rgba(var(--background-gradient-rgb), 0)), color-stop(calc(100% - 15px), rgba(var(--background-gradient-rgb), 1))); - background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); - background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--background-gradient-rgb), 1) calc(100% - 15px)); + background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 15px)); + background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 50px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 15px)); z-index: 6; } } @@ -115,15 +161,15 @@ core-format-text { .core-adapted-img-container { position: relative; display: inline-block; - width: 100%; + max-width: 100%; } .core-image-viewer-icon { position: absolute; @include position(null, 10px, 10px, null); - color: var(--black); + color: var(--ion-text-color); border-radius: 5px; - background-color: var(--viewer-icon-background); + background-color: var(--core-format-text-viewer-icon-background); display: flex; width: var(--a11y-min-target-size); @@ -141,3 +187,13 @@ core-format-text { } } } + + +@keyframes loading { + 0% { + left: -45%; + } + 100% { + left: 100%; + } +} From 224a7baa7d702b3d00775b56e8d1b28636063ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 4 Jun 2021 12:44:48 +0200 Subject: [PATCH 2/6] MOBILE-3320 core: Improvements on loading component --- .../addon-block-recentlyaccesseditems.html | 2 +- .../recentlyaccesseditems.scss | 3 +++ src/core/components/loading/loading.scss | 22 ++++++++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html index f63f935a5..4990142ad 100644 --- a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html +++ b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html @@ -5,7 +5,7 @@ - +
Date: Fri, 4 Jun 2021 12:53:24 +0200 Subject: [PATCH 3/6] MOBILE-3320 glossary: Fix link handlers --- src/addons/mod/glossary/services/handlers/edit-link.ts | 6 +----- src/addons/mod/glossary/services/handlers/entry-link.ts | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/addons/mod/glossary/services/handlers/edit-link.ts b/src/addons/mod/glossary/services/handlers/edit-link.ts index 089bfaf36..503220fef 100644 --- a/src/addons/mod/glossary/services/handlers/edit-link.ts +++ b/src/addons/mod/glossary/services/handlers/edit-link.ts @@ -47,12 +47,8 @@ export class AddonModGlossaryEditLinkHandlerService extends CoreContentLinksHand const module = await CoreCourse.getModuleBasicInfo(cmId, siteId); await CoreNavigator.navigateToSitePath( - AddonModGlossaryModuleHandlerService.PAGE_NAME + '/edit/0', + AddonModGlossaryModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/edit/0`, { - params: { - cmId: module.id, - courseId: module.course, - }, siteId, }, ); diff --git a/src/addons/mod/glossary/services/handlers/entry-link.ts b/src/addons/mod/glossary/services/handlers/entry-link.ts index 7ae25bb04..85b427bfd 100644 --- a/src/addons/mod/glossary/services/handlers/entry-link.ts +++ b/src/addons/mod/glossary/services/handlers/entry-link.ts @@ -52,12 +52,8 @@ export class AddonModGlossaryEntryLinkHandlerService extends CoreContentLinksHan ); await CoreNavigator.navigateToSitePath( - AddonModGlossaryModuleHandlerService.PAGE_NAME + `/entry/${entryId}`, + AddonModGlossaryModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/entry/${entryId}`, { - params: { - cmId: module.id, - courseId: module.course, - }, siteId, }, ); From ceeddda90863695a7f62f70885cd750fa5c1ada1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 4 Jun 2021 13:50:17 +0200 Subject: [PATCH 4/6] MOBILE-3320 tabs: Fix tab bottom padding --- src/core/classes/tabs.ts | 56 ++++++++++++++++++------------ src/core/components/tabs/tabs.scss | 2 ++ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts index 7182606c4..ddacb08bb 100644 --- a/src/core/classes/tabs.ts +++ b/src/core/classes/tabs.ts @@ -144,15 +144,36 @@ export class CoreTabsBaseComponent implements OnInit, Aft this.tabBarHeight = this.tabBarElement.offsetHeight; - if (this.tabsShown) { - // Smooth translation. - this.tabBarElement.style.top = - this.lastScroll + 'px'; - this.tabBarElement.style.height = 'calc(100% + ' + scroll + 'px'; - } else { - this.tabBarElement.classList.add('tabs-hidden'); - this.tabBarElement.style.top = '0'; - this.tabBarElement.style.height = ''; + this.applyScroll(this.tabsShown, this.lastScroll); + } + + /** + * Apply scroll to hiding tabs. + * + * @param showTabs Show or completely hide tabs. + * @param scroll Scroll position. + */ + protected applyScroll(showTabs: boolean, scroll?: number): void { + if (!this.tabBarElement || !this.tabBarHeight) { + + return; } + + if (showTabs) { + // Smooth translation. + this.tabBarElement!.classList.remove('tabs-hidden'); + if (scroll === 0) { + this.tabBarElement!.style.height = ''; + this.lastScroll = 0; + } else if (scroll !== undefined) { + this.tabBarElement!.style.height = (this.tabBarHeight - scroll) + 'px'; + } + } else { + this.tabBarElement!.classList.add('tabs-hidden'); + this.tabBarElement!.style.height = ''; + } + + this.tabsShown = showTabs; } /** @@ -478,11 +499,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft if (scrollTop <= 0) { // Ensure tabbar is shown. - this.tabsElement.style.top = '0'; - this.tabsElement.style.height = ''; - this.tabBarElement.classList.remove('tabs-hidden'); - this.tabsShown = true; - this.lastScroll = 0; + this.applyScroll(true, 0); return; } @@ -493,22 +510,17 @@ export class CoreTabsBaseComponent implements OnInit, Aft } if (this.tabsShown && scrollTop > this.tabBarHeight) { - this.tabsShown = false; - // Hide tabs. - this.tabBarElement.classList.add('tabs-hidden'); - this.tabsElement.style.top = '0'; - this.tabsElement.style.height = ''; + this.applyScroll(false); } else if (!this.tabsShown && scrollTop <= this.tabBarHeight) { - this.tabsShown = true; - this.tabBarElement.classList.remove('tabs-hidden'); + this.applyScroll(true); } if (this.tabsShown && scrollElement.scrollHeight > scrollElement.clientHeight + (this.tabBarHeight - scrollTop)) { // Smooth translation. - this.tabsElement.style.top = - scrollTop + 'px'; - this.tabsElement.style.height = 'calc(100% + ' + scrollTop + 'px'; + this.applyScroll(true, scrollTop); } + // Use lastScroll after moving the tabs to avoid flickering. this.lastScroll = scrollTop; } diff --git a/src/core/components/tabs/tabs.scss b/src/core/components/tabs/tabs.scss index fa1562f1d..64368d56d 100644 --- a/src/core/components/tabs/tabs.scss +++ b/src/core/components/tabs/tabs.scss @@ -22,6 +22,8 @@ -webkit-filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); border: 0; + display: flex; + align-items: flex-end; ion-row { width: 100%; From 3de60760b09989d2b42e64bbb2a2fc821438682a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 4 Jun 2021 14:40:07 +0200 Subject: [PATCH 5/6] MOBILE-3320 core: Fix wraps on chat and assignment submission --- src/addons/calendar/pages/day/day.html | 2 +- .../messages/pages/discussion/discussion.html | 2 +- .../addon-mod-assign-submission.html | 19 ++++++++----------- .../index/addon-mod-chat-index.html | 4 ++-- .../mod/forum/components/index/index.html | 10 ++++++---- .../index/addon-mod-glossary-index.html | 2 +- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/addons/calendar/pages/day/day.html b/src/addons/calendar/pages/day/day.html index 4ca58a438..5177df833 100644 --- a/src/addons/calendar/pages/day/day.html +++ b/src/addons/calendar/pages/day/day.html @@ -53,7 +53,7 @@ - diff --git a/src/addons/messages/pages/discussion/discussion.html b/src/addons/messages/pages/discussion/discussion.html index 6ff35dea0..cf6b37e40 100644 --- a/src/addons/messages/pages/discussion/discussion.html +++ b/src/addons/messages/pages/discussion/discussion.html @@ -96,7 +96,7 @@ - {{ members[message.useridfrom].fullname }} +
{{ members[message.useridfrom].fullname }}
{{ message.useridfrom == currentUserId diff --git a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html index 09d1c6416..7f368c34a 100644 --- a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html +++ b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html @@ -8,7 +8,6 @@

{{ user!.fullname }}

- @@ -17,7 +16,6 @@

{{ 'addon.mod_assign.hiddenuser' | translate }} {{blindId}}

- @@ -26,7 +24,6 @@

{{ 'addon.mod_assign.submissionstatus' | translate }}

- @@ -385,12 +382,12 @@ {{ 'addon.mod_assign.defaultteam' | translate }}

- - - - {{ statusTranslated }} - - - {{ gradingStatusTranslationId | translate }} - +

+ + {{ statusTranslated }} + + + {{ gradingStatusTranslationId | translate }} + +

diff --git a/src/addons/mod/chat/components/index/addon-mod-chat-index.html b/src/addons/mod/chat/components/index/addon-mod-chat-index.html index 6a2c21ff3..2efee98b1 100644 --- a/src/addons/mod/chat/components/index/addon-mod-chat-index.html +++ b/src/addons/mod/chat/components/index/addon-mod-chat-index.html @@ -43,10 +43,10 @@ - + {{ 'addon.mod_chat.enterchat' | translate }} - + {{ 'addon.mod_chat.viewreport' | translate }} diff --git a/src/addons/mod/forum/components/index/index.html b/src/addons/mod/forum/components/index/index.html index 5e3d2bbf4..db45724cc 100644 --- a/src/addons/mod/forum/components/index/index.html +++ b/src/addons/mod/forum/components/index/index.html @@ -10,11 +10,13 @@ - - @@ -37,11 +39,11 @@ - + - + diff --git a/src/addons/mod/glossary/components/index/addon-mod-glossary-index.html b/src/addons/mod/glossary/components/index/addon-mod-glossary-index.html index 8e3bcab19..6906bf761 100644 --- a/src/addons/mod/glossary/components/index/addon-mod-glossary-index.html +++ b/src/addons/mod/glossary/components/index/addon-mod-glossary-index.html @@ -49,7 +49,7 @@ [autoFocus]="true" [lengthCheck]="2" (onClear)="toggleSearch()" searchArea="AddonModGlossary-{{module.id}}"> - + From 1106a8c4040bb2b030e5a703c4d4d44935a40253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 4 Jun 2021 15:56:57 +0200 Subject: [PATCH 6/6] MOBILE-3320 core: Fix border color on Android select and hovering styles --- src/core/components/combobox/combobox.scss | 7 +++---- src/theme/theme.base.scss | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/components/combobox/combobox.scss b/src/core/components/combobox/combobox.scss index 85f428f01..a36947dd4 100644 --- a/src/core/components/combobox/combobox.scss +++ b/src/core/components/combobox/combobox.scss @@ -13,7 +13,6 @@ --color: var(--core-combobox-color); --color-activated: var(--core-combobox-color); --border-color: var(--core-combobox-border-color); - --border-width: 0 0 var(--core-combobox-border-width) 0; --border-style: solid; --color-focused: currentcolor; --color-hover: currentcolor; @@ -53,9 +52,7 @@ ion-button { } ion-select { - border-color: var(--border-color); - border-width: var(--border-width); - border-style: var(--border-style); + border-bottom: var(--core-combobox-border-width) var(--border-style) var(--border-color); &::part(icon) { margin: var(--icon-margin); @@ -84,6 +81,8 @@ ion-select { ion-button { --border-radius: 0; + --border-width: 0 0 var(--core-combobox-border-width) 0; + flex: 1; min-height: 45px; diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index bdf7d264a..0defd7a37 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -685,7 +685,7 @@ audio.core-media-adapt-width { } // Make links clickable when inside radio or checkbox items. Style part. -@media (any-hover: hover) { +@media (hover: hover) { ion-item.item-multiple-inputs:hover::part(native) { color: var(--color-hover);