forked from EVOgeek/Vmeda.Online
		
	MOBILE-3814 format-text: Use a general loader solution on format-text
This commit is contained in:
		
							parent
							
								
									fb3a01a55c
								
							
						
					
					
						commit
						e03ef0d26e
					
				| @ -90,8 +90,8 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
| 
 | ||||
|     protected element: HTMLElement; | ||||
|     protected emptyText = ''; | ||||
|     protected contentSpan: HTMLElement; | ||||
|     protected domPromise?: CoreCancellablePromise<void>; | ||||
|     protected domPromises: CoreCancellablePromise<void>[] = []; | ||||
|     protected domElementPromise?: CoreCancellablePromise<void>; | ||||
| 
 | ||||
|     constructor( | ||||
|         element: ElementRef, | ||||
| @ -101,18 +101,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|         CoreComponentsRegistry.register(element.nativeElement, this); | ||||
| 
 | ||||
|         this.element = element.nativeElement; | ||||
|         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.element.classList.add('core-loading'); // Hide contents until they're treated.
 | ||||
| 
 | ||||
|         this.emptyText = this.hideIfEmpty ? '' : ' '; | ||||
|         this.contentSpan.innerHTML = this.emptyText; | ||||
|         this.element.innerHTML = this.emptyText; | ||||
| 
 | ||||
|         this.afterRender = new EventEmitter<void>(); | ||||
| 
 | ||||
| @ -134,14 +126,15 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     ngOnDestroy(): void { | ||||
|         this.domPromise?.cancel(); | ||||
|         this.domElementPromise?.cancel(); | ||||
|         this.domPromises.forEach((promise) => { promise.cancel();}); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async ready(): Promise<void> { | ||||
|         if (!this.element.classList.contains('core-format-text-loading')) { | ||||
|         if (!this.element.classList.contains('core-loading')) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| @ -229,7 +222,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|      * Add magnifying glass icons to view adapted images at full size. | ||||
|      */ | ||||
|     async addMagnifyingGlasses(): Promise<void> { | ||||
|         const imgs = Array.from(this.contentSpan.querySelectorAll('.core-adapted-img-container > img')); | ||||
|         const imgs = Array.from(this.element.querySelectorAll('.core-adapted-img-container > img')); | ||||
|         if (!imgs.length) { | ||||
|             return; | ||||
|         } | ||||
| @ -311,7 +304,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|      */ | ||||
|     protected async finishRender(): Promise<void> { | ||||
|         // Show the element again.
 | ||||
|         this.element.classList.remove('core-format-text-loading'); | ||||
|         this.element.classList.remove('core-loading'); | ||||
| 
 | ||||
|         await CoreUtils.nextTick(); | ||||
| 
 | ||||
| @ -324,7 +317,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|      */ | ||||
|     protected async formatAndRenderContents(): Promise<void> { | ||||
|         if (!this.text) { | ||||
|             this.contentSpan.innerHTML = this.emptyText; // Remove current contents.
 | ||||
|             this.element.innerHTML = this.emptyText; // Remove current contents.
 | ||||
| 
 | ||||
|             await this.finishRender(); | ||||
| 
 | ||||
| @ -342,10 +335,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|         // Disable media adapt to correctly calculate the height.
 | ||||
|         this.element.classList.add('core-disable-media-adapt'); | ||||
| 
 | ||||
|         this.contentSpan.innerHTML = ''; // Remove current contents.
 | ||||
|         this.element.innerHTML = ''; // Remove current contents.
 | ||||
| 
 | ||||
|         // Move the children to the current element to be able to calculate the height.
 | ||||
|         CoreDomUtils.moveChildren(result.div, this.contentSpan); | ||||
|         CoreDomUtils.moveChildren(result.div, this.element); | ||||
| 
 | ||||
|         await CoreUtils.nextTick(); | ||||
| 
 | ||||
| @ -362,7 +355,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|         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.contentSpan, | ||||
|                 this.element, | ||||
|                 result.filters, | ||||
|                 this.viewContainerRef, | ||||
|                 result.options, | ||||
| @ -557,9 +550,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|      * @return The width of the element in pixels. | ||||
|      */ | ||||
|     protected async getElementWidth(): Promise<number> { | ||||
|         this.domPromise = CoreDomUtils.waitToBeInDOM(this.element); | ||||
| 
 | ||||
|         await this.domPromise; | ||||
|         if (!this.domElementPromise) { | ||||
|             this.domElementPromise = CoreDomUtils.waitToBeInDOM(this.element); | ||||
|         } | ||||
|         await this.domElementPromise; | ||||
| 
 | ||||
|         let width = this.element.getBoundingClientRect().width; | ||||
|         if (!width) { | ||||
| @ -709,12 +703,15 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | ||||
|                     newUrl += `&h=${privacyHash}`; | ||||
|                 } | ||||
| 
 | ||||
|                 const domPromise = CoreDomUtils.waitToBeInDOM(iframe); | ||||
|                 this.domPromises.push(domPromise); | ||||
| 
 | ||||
|                 await domPromise; | ||||
| 
 | ||||
|                 // Width and height are mandatory, we need to calculate them.
 | ||||
|                 let width: string | number; | ||||
|                 let height: string | number; | ||||
| 
 | ||||
|                 await CoreDomUtils.waitToBeInDOM(iframe, 5000); | ||||
| 
 | ||||
|                 if (iframe.width) { | ||||
|                     width = iframe.width; | ||||
|                 } else { | ||||
|  | ||||
| @ -58,7 +58,7 @@ describe('CoreFormatTextDirective', () => { | ||||
|         ); | ||||
| 
 | ||||
|         // Assert
 | ||||
|         const text = fixture.nativeElement.querySelector('core-format-text .core-format-text-content'); | ||||
|         const text = fixture.nativeElement.querySelector('core-format-text'); | ||||
|         expect(text).not.toBeNull(); | ||||
|         expect(text.innerHTML).toEqual(sentence); | ||||
|     }); | ||||
|  | ||||
| @ -5,59 +5,25 @@ | ||||
| core-format-text { | ||||
|     --core-format-text-background: var(--background, var(--ion-item-background)); | ||||
|     --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); | ||||
|     --core-format-text-loader-shine: 251,251,251; | ||||
| } | ||||
| 
 | ||||
| body.dark core-format-text { | ||||
|     --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); | ||||
|     --core-format-text-loader-shine: 90,90,90; | ||||
| } | ||||
| 
 | ||||
| core-format-text { | ||||
|     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; | ||||
|         display: block; | ||||
|         border-radius: var(--small-radius); | ||||
| 
 | ||||
|         .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-format-text-content { | ||||
|         opacity: 1; | ||||
|         @include core-transition(opacity, 200ms); | ||||
| 
 | ||||
|     display: contents; | ||||
|     user-select: text; | ||||
|     word-break: break-word; | ||||
|     word-wrap: break-word; | ||||
| 
 | ||||
|     @include core-transition(background-color color, 200ms); | ||||
|     &.core-loading { | ||||
|         width: 100%; | ||||
|         &:empty:before { | ||||
|             content: 'E'; // Set a minimum empty text to have a minimum height of one line. | ||||
|             opacity: 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     &.collapsible-item { | ||||
| @ -66,16 +32,11 @@ core-format-text { | ||||
|         cursor: pointer; | ||||
|         pointer-events: auto; | ||||
| 
 | ||||
|         .core-format-text-content { | ||||
|             display: block; | ||||
|         } | ||||
| 
 | ||||
|         &.collapsible-enabled { | ||||
|             .core-format-text-content { | ||||
|             display: block; | ||||
|             max-height: none; | ||||
|             } | ||||
|             &.collapsible-collapsed .core-format-text-content { | ||||
| 
 | ||||
|             &.collapsible-collapsed { | ||||
|                 overflow: hidden; | ||||
|             } | ||||
|         } | ||||
| @ -97,7 +58,7 @@ core-format-text { | ||||
|     } | ||||
|     &.collapsible-item.inline { | ||||
|         display: inline-block; | ||||
|         &.collapsible-enabled .core-format-text-content { | ||||
|         &.collapsible-enabled { | ||||
|            display: inline-block; | ||||
|         } | ||||
|     } | ||||
| @ -141,7 +102,7 @@ core-format-text { | ||||
|     } | ||||
| 
 | ||||
|     // Disable clicks in links inside MathJax equations. | ||||
|     .core-format-text-content .filter_mathjaxloader_equation .MathJax_Preview a { | ||||
|     .filter_mathjaxloader_equation .MathJax_Preview a { | ||||
|         pointer-events: none; | ||||
|     } | ||||
| 
 | ||||
| @ -243,7 +204,7 @@ core-format-text { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| core-format-text .core-format-text-content, | ||||
| core-format-text, | ||||
| core-rich-text-editor .core-rte-editor { | ||||
|     @include core-headings(); | ||||
| 
 | ||||
| @ -657,14 +618,10 @@ core-rich-text-editor .core-rte-editor { | ||||
| 
 | ||||
| // h1 is too big and ugly, reduce size when loading. | ||||
| ion-header.ios h1 core-format-text { | ||||
|     &.core-format-text-loading { | ||||
|     &.core-loading { | ||||
|         max-height: 30px; | ||||
|         margin-top: 10px; | ||||
|     } | ||||
|     &.core-format-text-content { | ||||
|         display: block; | ||||
|         margin-top: -10px; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| body.dark core-format-text select, | ||||
|  | ||||
| @ -120,15 +120,15 @@ body { | ||||
| } | ||||
| 
 | ||||
| // Correctly inherit ion-text-wrap onto labels. | ||||
| .item ion-label core-format-text .core-format-text-content > *, | ||||
| .fake-ion-item core-format-text .core-format-text-content > * { | ||||
| .item ion-label core-format-text > *, | ||||
| .fake-ion-item core-format-text > * { | ||||
|     white-space: nowrap; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
| } | ||||
| 
 | ||||
| .item.ion-text-wrap > ion-label core-format-text .core-format-text-content > *, | ||||
| .fake-ion-item.ion-text-wrap core-format-text .core-format-text-content > * { | ||||
| .item.ion-text-wrap > ion-label core-format-text > *, | ||||
| .fake-ion-item.ion-text-wrap core-format-text > * { | ||||
|     white-space: normal; | ||||
|     overflow: inherit; | ||||
| } | ||||
| @ -334,7 +334,7 @@ ion-button.button-solid { | ||||
|     --box-shadow: none; | ||||
| } | ||||
| 
 | ||||
| ion-button core-format-text .core-format-text-content { | ||||
| ion-button core-format-text { | ||||
|     white-space: nowrap; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
| @ -350,7 +350,7 @@ ion-button > * { | ||||
| 
 | ||||
| ion-button.ion-text-wrap { | ||||
|     white-space: normal; | ||||
|     core-format-text .core-format-text-content { | ||||
|     core-format-text { | ||||
|         white-space: normal; | ||||
|         display: contents; | ||||
|     } | ||||
| @ -1516,3 +1516,36 @@ ion-header.no-title { | ||||
|         flex-grow: 1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Loader animation. | ||||
| .core-loading { | ||||
|     position: relative; | ||||
|     background-color: var(--loader-background-color); | ||||
|     color: transparent; // Hide contents. | ||||
|     overflow: hidden; | ||||
|     display: var(--loader-display); | ||||
|     border-radius: var(--loader-radius); | ||||
|     @include core-transition(all, 200ms); | ||||
|     min-height: 8px; | ||||
|     min-width: 50px; | ||||
| 
 | ||||
|     // Hide contents. | ||||
|     > * { | ||||
|         opacity: 0; | ||||
|         @include core-transition(opacity, 200ms); | ||||
|     } | ||||
| 
 | ||||
|     &::after { | ||||
|         content: ''; | ||||
|         position: absolute; | ||||
|         left: -45%; | ||||
|         height: 100%; | ||||
|         width: 45%; | ||||
|         background-image: linear-gradient(to left, rgba(var(--loader-shine), .05), rgba(var(--loader-shine), .3), rgba(var(--loader-shine), .6), rgba(var(--loader-shine), .3), rgba(var(--loader-shine), .05)); | ||||
|         animation: loading 1s infinite; | ||||
|         display: block; | ||||
|         top: 0; | ||||
|         bottom: 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -41,6 +41,8 @@ | ||||
| 
 | ||||
|     --contrast-background: var(--gray-900); | ||||
| 
 | ||||
|     --loader-shine: 90, 90, 90; | ||||
| 
 | ||||
|     --drop-shadow-color: 0, 0, 0, 1; | ||||
|     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); | ||||
|     --drop-shadow-bottom: 0px -2px 5px rgba(var(--drop-shadow-color)); | ||||
|  | ||||
| @ -85,6 +85,11 @@ | ||||
| 
 | ||||
|     --contrast-background: white; | ||||
| 
 | ||||
|     --loader-background-color: rgba(0, 0, 0, .1); | ||||
|     --loader-shine: 251, 251, 251; | ||||
|     --loader-radius: var(--small-radius); | ||||
|     --loader-display: block; | ||||
| 
 | ||||
|     --drop-shadow-color: 0, 0, 0, 0.5; | ||||
|     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); | ||||
|     --drop-shadow-bottom: 0px -2px 5px rgba(var(--drop-shadow-color)); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user