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 element: HTMLElement; | ||||||
|     protected emptyText = ''; |     protected emptyText = ''; | ||||||
|     protected contentSpan: HTMLElement; |     protected domPromises: CoreCancellablePromise<void>[] = []; | ||||||
|     protected domPromise?: CoreCancellablePromise<void>; |     protected domElementPromise?: CoreCancellablePromise<void>; | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         element: ElementRef, |         element: ElementRef, | ||||||
| @ -101,18 +101,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|         CoreComponentsRegistry.register(element.nativeElement, this); |         CoreComponentsRegistry.register(element.nativeElement, this); | ||||||
| 
 | 
 | ||||||
|         this.element = element.nativeElement; |         this.element = element.nativeElement; | ||||||
|         this.element.classList.add('core-format-text-loading'); // Hide contents until they're treated.
 |         this.element.classList.add('core-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.emptyText = this.hideIfEmpty ? '' : ' '; | ||||||
|         this.contentSpan.innerHTML = this.emptyText; |         this.element.innerHTML = this.emptyText; | ||||||
| 
 | 
 | ||||||
|         this.afterRender = new EventEmitter<void>(); |         this.afterRender = new EventEmitter<void>(); | ||||||
| 
 | 
 | ||||||
| @ -134,14 +126,15 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngOnDestroy(): void { |     ngOnDestroy(): void { | ||||||
|         this.domPromise?.cancel(); |         this.domElementPromise?.cancel(); | ||||||
|  |         this.domPromises.forEach((promise) => { promise.cancel();}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     async ready(): Promise<void> { |     async ready(): Promise<void> { | ||||||
|         if (!this.element.classList.contains('core-format-text-loading')) { |         if (!this.element.classList.contains('core-loading')) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -229,7 +222,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|      * Add magnifying glass icons to view adapted images at full size. |      * Add magnifying glass icons to view adapted images at full size. | ||||||
|      */ |      */ | ||||||
|     async addMagnifyingGlasses(): Promise<void> { |     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) { |         if (!imgs.length) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -311,7 +304,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|      */ |      */ | ||||||
|     protected async finishRender(): Promise<void> { |     protected async finishRender(): Promise<void> { | ||||||
|         // Show the element again.
 |         // Show the element again.
 | ||||||
|         this.element.classList.remove('core-format-text-loading'); |         this.element.classList.remove('core-loading'); | ||||||
| 
 | 
 | ||||||
|         await CoreUtils.nextTick(); |         await CoreUtils.nextTick(); | ||||||
| 
 | 
 | ||||||
| @ -324,7 +317,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|      */ |      */ | ||||||
|     protected async formatAndRenderContents(): Promise<void> { |     protected async formatAndRenderContents(): Promise<void> { | ||||||
|         if (!this.text) { |         if (!this.text) { | ||||||
|             this.contentSpan.innerHTML = this.emptyText; // Remove current contents.
 |             this.element.innerHTML = this.emptyText; // Remove current contents.
 | ||||||
| 
 | 
 | ||||||
|             await this.finishRender(); |             await this.finishRender(); | ||||||
| 
 | 
 | ||||||
| @ -342,10 +335,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|         // Disable media adapt to correctly calculate the height.
 |         // Disable media adapt to correctly calculate the height.
 | ||||||
|         this.element.classList.add('core-disable-media-adapt'); |         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.
 |         // 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(); |         await CoreUtils.nextTick(); | ||||||
| 
 | 
 | ||||||
| @ -362,7 +355,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|         if (result.options.filter) { |         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.
 |             // Let filters handle HTML. We do it here because we don't want them to block the render of the text.
 | ||||||
|             CoreFilterDelegate.handleHtml( |             CoreFilterDelegate.handleHtml( | ||||||
|                 this.contentSpan, |                 this.element, | ||||||
|                 result.filters, |                 result.filters, | ||||||
|                 this.viewContainerRef, |                 this.viewContainerRef, | ||||||
|                 result.options, |                 result.options, | ||||||
| @ -557,9 +550,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|      * @return The width of the element in pixels. |      * @return The width of the element in pixels. | ||||||
|      */ |      */ | ||||||
|     protected async getElementWidth(): Promise<number> { |     protected async getElementWidth(): Promise<number> { | ||||||
|         this.domPromise = CoreDomUtils.waitToBeInDOM(this.element); |         if (!this.domElementPromise) { | ||||||
| 
 |             this.domElementPromise = CoreDomUtils.waitToBeInDOM(this.element); | ||||||
|         await this.domPromise; |         } | ||||||
|  |         await this.domElementPromise; | ||||||
| 
 | 
 | ||||||
|         let width = this.element.getBoundingClientRect().width; |         let width = this.element.getBoundingClientRect().width; | ||||||
|         if (!width) { |         if (!width) { | ||||||
| @ -709,12 +703,15 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo | |||||||
|                     newUrl += `&h=${privacyHash}`; |                     newUrl += `&h=${privacyHash}`; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 const domPromise = CoreDomUtils.waitToBeInDOM(iframe); | ||||||
|  |                 this.domPromises.push(domPromise); | ||||||
|  | 
 | ||||||
|  |                 await domPromise; | ||||||
|  | 
 | ||||||
|                 // Width and height are mandatory, we need to calculate them.
 |                 // Width and height are mandatory, we need to calculate them.
 | ||||||
|                 let width: string | number; |                 let width: string | number; | ||||||
|                 let height: string | number; |                 let height: string | number; | ||||||
| 
 | 
 | ||||||
|                 await CoreDomUtils.waitToBeInDOM(iframe, 5000); |  | ||||||
| 
 |  | ||||||
|                 if (iframe.width) { |                 if (iframe.width) { | ||||||
|                     width = iframe.width; |                     width = iframe.width; | ||||||
|                 } else { |                 } else { | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ describe('CoreFormatTextDirective', () => { | |||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         // Assert
 |         // 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).not.toBeNull(); | ||||||
|         expect(text.innerHTML).toEqual(sentence); |         expect(text.innerHTML).toEqual(sentence); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -5,59 +5,25 @@ | |||||||
| core-format-text { | core-format-text { | ||||||
|     --core-format-text-background: var(--background, var(--ion-item-background)); |     --core-format-text-background: var(--background, var(--ion-item-background)); | ||||||
|     --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); |     --core-format-text-viewer-icon-background: rgba(255, 255, 255, .5); | ||||||
|     --core-format-text-loader-shine: 251,251,251; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| body.dark core-format-text { | body.dark core-format-text { | ||||||
|     --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); |     --core-format-text-viewer-icon-background: rgba(0, 0, 0, .5); | ||||||
|     --core-format-text-loader-shine: 90,90,90; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| core-format-text { | 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; |     display: contents; | ||||||
|     user-select: text; |     user-select: text; | ||||||
|     word-break: break-word; |     word-break: break-word; | ||||||
|     word-wrap: 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 { |     &.collapsible-item { | ||||||
| @ -66,16 +32,11 @@ core-format-text { | |||||||
|         cursor: pointer; |         cursor: pointer; | ||||||
|         pointer-events: auto; |         pointer-events: auto; | ||||||
| 
 | 
 | ||||||
|         .core-format-text-content { |  | ||||||
|             display: block; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         &.collapsible-enabled { |         &.collapsible-enabled { | ||||||
|             .core-format-text-content { |  | ||||||
|             display: block; |             display: block; | ||||||
|             max-height: none; |             max-height: none; | ||||||
|             } | 
 | ||||||
|             &.collapsible-collapsed .core-format-text-content { |             &.collapsible-collapsed { | ||||||
|                 overflow: hidden; |                 overflow: hidden; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -97,7 +58,7 @@ core-format-text { | |||||||
|     } |     } | ||||||
|     &.collapsible-item.inline { |     &.collapsible-item.inline { | ||||||
|         display: inline-block; |         display: inline-block; | ||||||
|         &.collapsible-enabled .core-format-text-content { |         &.collapsible-enabled { | ||||||
|            display: inline-block; |            display: inline-block; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -141,7 +102,7 @@ core-format-text { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Disable clicks in links inside MathJax equations. |     // 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; |         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 { | core-rich-text-editor .core-rte-editor { | ||||||
|     @include core-headings(); |     @include core-headings(); | ||||||
| 
 | 
 | ||||||
| @ -657,14 +618,10 @@ core-rich-text-editor .core-rte-editor { | |||||||
| 
 | 
 | ||||||
| // h1 is too big and ugly, reduce size when loading. | // h1 is too big and ugly, reduce size when loading. | ||||||
| ion-header.ios h1 core-format-text { | ion-header.ios h1 core-format-text { | ||||||
|     &.core-format-text-loading { |     &.core-loading { | ||||||
|         max-height: 30px; |         max-height: 30px; | ||||||
|         margin-top: 10px; |         margin-top: 10px; | ||||||
|     } |     } | ||||||
|     &.core-format-text-content { |  | ||||||
|         display: block; |  | ||||||
|         margin-top: -10px; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| body.dark core-format-text select, | body.dark core-format-text select, | ||||||
|  | |||||||
| @ -120,15 +120,15 @@ body { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Correctly inherit ion-text-wrap onto labels. | // Correctly inherit ion-text-wrap onto labels. | ||||||
| .item ion-label core-format-text .core-format-text-content > *, | .item ion-label core-format-text > *, | ||||||
| .fake-ion-item core-format-text .core-format-text-content > * { | .fake-ion-item core-format-text > * { | ||||||
|     white-space: nowrap; |     white-space: nowrap; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
|     text-overflow: ellipsis; |     text-overflow: ellipsis; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .item.ion-text-wrap > ion-label 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 .core-format-text-content > * { | .fake-ion-item.ion-text-wrap core-format-text > * { | ||||||
|     white-space: normal; |     white-space: normal; | ||||||
|     overflow: inherit; |     overflow: inherit; | ||||||
| } | } | ||||||
| @ -334,7 +334,7 @@ ion-button.button-solid { | |||||||
|     --box-shadow: none; |     --box-shadow: none; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-button core-format-text .core-format-text-content { | ion-button core-format-text { | ||||||
|     white-space: nowrap; |     white-space: nowrap; | ||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
|     text-overflow: ellipsis; |     text-overflow: ellipsis; | ||||||
| @ -350,7 +350,7 @@ ion-button > * { | |||||||
| 
 | 
 | ||||||
| ion-button.ion-text-wrap { | ion-button.ion-text-wrap { | ||||||
|     white-space: normal; |     white-space: normal; | ||||||
|     core-format-text .core-format-text-content { |     core-format-text { | ||||||
|         white-space: normal; |         white-space: normal; | ||||||
|         display: contents; |         display: contents; | ||||||
|     } |     } | ||||||
| @ -1516,3 +1516,36 @@ ion-header.no-title { | |||||||
|         flex-grow: 1; |         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); |     --contrast-background: var(--gray-900); | ||||||
| 
 | 
 | ||||||
|  |     --loader-shine: 90, 90, 90; | ||||||
|  | 
 | ||||||
|     --drop-shadow-color: 0, 0, 0, 1; |     --drop-shadow-color: 0, 0, 0, 1; | ||||||
|     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); |     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); | ||||||
|     --drop-shadow-bottom: 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; |     --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-color: 0, 0, 0, 0.5; | ||||||
|     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); |     --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color)); | ||||||
|     --drop-shadow-bottom: 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