commit
						e6ca385312
					
				| @ -174,6 +174,6 @@ | |||||||
|             </p> |             </p> | ||||||
|         </div> |         </div> | ||||||
|         <core-send-message-form *ngIf="footerType == 'message'" (onSubmit)="sendMessage($event)" [showKeyboard]="showKeyboard" |         <core-send-message-form *ngIf="footerType == 'message'" (onSubmit)="sendMessage($event)" [showKeyboard]="showKeyboard" | ||||||
|             [placeholder]="'addon.messages.newmessage' | translate" (onResize)="resizeContent()"></core-send-message-form> |             [placeholder]="'addon.messages.newmessage' | translate"></core-send-message-form> | ||||||
|     </ion-toolbar> |     </ion-toolbar> | ||||||
| </ion-footer> | </ion-footer> | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ | |||||||
| // See the License for the specific language governing permissions and
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; | import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; | ||||||
| import { IonContent } from '@ionic/angular'; | import { IonContent } from '@ionic/angular'; | ||||||
| import { AlertOptions } from '@ionic/core'; | import { AlertOptions } from '@ionic/core'; | ||||||
| import { CoreEventObserver, CoreEvents } from '@singletons/events'; | import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||||
| @ -76,6 +76,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|     protected viewDestroyed = false; |     protected viewDestroyed = false; | ||||||
|     protected memberInfoObserver: CoreEventObserver; |     protected memberInfoObserver: CoreEventObserver; | ||||||
|     protected showLoadingModal = false; // Whether to show a loading modal while fetching data.
 |     protected showLoadingModal = false; // Whether to show a loading modal while fetching data.
 | ||||||
|  |     protected hostElement: HTMLElement; | ||||||
| 
 | 
 | ||||||
|     conversationId?: number; // Conversation ID. Undefined if it's a new individual conversation.
 |     conversationId?: number; // Conversation ID. Undefined if it's a new individual conversation.
 | ||||||
|     conversation?: AddonMessagesConversationFormatted; // The conversation object (if it exists).
 |     conversation?: AddonMessagesConversationFormatted; // The conversation object (if it exists).
 | ||||||
| @ -109,10 +110,13 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|     newMessages = 0; |     newMessages = 0; | ||||||
|     scrollElement?: HTMLElement; |     scrollElement?: HTMLElement; | ||||||
|     unreadMessageFrom = 0; |     unreadMessageFrom = 0; | ||||||
|  |     initialized = false; | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         protected route: ActivatedRoute, |         protected route: ActivatedRoute, | ||||||
|  |         protected elementRef: ElementRef<HTMLElement>, | ||||||
|     ) { |     ) { | ||||||
|  |         this.hostElement = elementRef.nativeElement; | ||||||
|         this.siteId = CoreSites.getCurrentSiteId(); |         this.siteId = CoreSites.getCurrentSiteId(); | ||||||
|         this.currentUserId = CoreSites.getCurrentSiteUserId(); |         this.currentUserId = CoreSites.getCurrentSiteUserId(); | ||||||
|         this.groupMessagingEnabled = AddonMessages.isGroupMessagingEnabled(); |         this.groupMessagingEnabled = AddonMessages.isGroupMessagingEnabled(); | ||||||
| @ -162,6 +166,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|         this.route.queryParams.subscribe(async (params) => { |         this.route.queryParams.subscribe(async (params) => { | ||||||
|             const oldConversationId = this.conversationId; |             const oldConversationId = this.conversationId; | ||||||
|             const oldUserId = this.userId; |             const oldUserId = this.userId; | ||||||
|  |             let forceScrollToBottom = false; | ||||||
|             this.conversationId = CoreNavigator.getRouteNumberParam('conversationId', { params }) || undefined; |             this.conversationId = CoreNavigator.getRouteNumberParam('conversationId', { params }) || undefined; | ||||||
|             this.userId = CoreNavigator.getRouteNumberParam('userId', { params }) || undefined; |             this.userId = CoreNavigator.getRouteNumberParam('userId', { params }) || undefined; | ||||||
|             this.showInfo = !params.hideInfo; |             this.showInfo = !params.hideInfo; | ||||||
| @ -169,13 +174,15 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|             if (oldConversationId != this.conversationId || oldUserId != this.userId) { |             if (oldConversationId != this.conversationId || oldUserId != this.userId) { | ||||||
|                 // Showing reload again can break animations.
 |                 // Showing reload again can break animations.
 | ||||||
|                 this.loaded = false; |                 this.loaded = false; | ||||||
|  |                 this.initialized = false; | ||||||
|  |                 forceScrollToBottom = true; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             this.showKeyboard = CoreNavigator.getRouteBooleanParam('showKeyboard', { params }) || false; |             this.showKeyboard = CoreNavigator.getRouteBooleanParam('showKeyboard', { params }) || false; | ||||||
| 
 | 
 | ||||||
|             await this.fetchData(); |             await this.fetchData(); | ||||||
| 
 | 
 | ||||||
|             this.scrollToBottom(); |             this.scrollToBottom(forceScrollToBottom); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -353,7 +360,6 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|             CoreDomUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingmessages', true); |             CoreDomUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingmessages', true); | ||||||
|         } finally { |         } finally { | ||||||
|             this.checkCanDelete(); |             this.checkCanDelete(); | ||||||
|             this.resizeContent(); |  | ||||||
|             this.loaded = true; |             this.loaded = true; | ||||||
|             this.setPolling(); // Make sure we're polling messages.
 |             this.setPolling(); // Make sure we're polling messages.
 | ||||||
|             this.setContactRequestInfo(); |             this.setContactRequestInfo(); | ||||||
| @ -481,10 +487,6 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|             message.showTail = this.showTail(message, this.messages[index + 1]); |             message.showTail = this.showTail(message, this.messages[index + 1]); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // Call resize to recalculate the dimensions.
 |  | ||||||
|         // @todo probably not needed.
 |  | ||||||
|         // this.content!.resize();
 |  | ||||||
| 
 |  | ||||||
|         // If we received a new message while using group messaging, force mark messages as read.
 |         // If we received a new message while using group messaging, force mark messages as read.
 | ||||||
|         const last = this.messages[this.messages.length - 1]; |         const last = this.messages[this.messages.length - 1]; | ||||||
|         const forceMark = this.groupMessagingEnabled && last && last.useridfrom != this.currentUserId && this.lastMessage.text != '' |         const forceMark = this.groupMessagingEnabled && last && last.useridfrom != this.currentUserId && this.lastMessage.text != '' | ||||||
| @ -537,7 +539,9 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const messages = Array.from(document.querySelectorAll('.addon-message-not-mine')).slice(-this.newMessages).reverse(); |             const messages = Array.from(this.hostElement.querySelectorAll('.addon-message-not-mine')) | ||||||
|  |                 .slice(-this.newMessages) | ||||||
|  |                 .reverse(); | ||||||
| 
 | 
 | ||||||
|             const newMessagesUnread = messages.findIndex((message) => { |             const newMessagesUnread = messages.findIndex((message) => { | ||||||
|                 const elementRect = message.getBoundingClientRect(); |                 const elementRect = message.getBoundingClientRect(); | ||||||
| @ -1036,7 +1040,16 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|      * @return Resolved when done. |      * @return Resolved when done. | ||||||
|      */ |      */ | ||||||
|     async loadPrevious(infiniteComplete?: () => void): Promise<void> { |     async loadPrevious(infiniteComplete?: () => void): Promise<void> { | ||||||
|         let infiniteHeight = this.infinite?.infiniteEl?.nativeElement.getBoundingClientRect().height || 0; |         if (!this.initialized) { | ||||||
|  |             // Don't load previous if the view isn't fully initialized.
 | ||||||
|  |             // Don't put the initialized condition in the "enabled" input because then the load more is hidden and
 | ||||||
|  |             // the scroll height changes when it appears.
 | ||||||
|  |             infiniteComplete && infiniteComplete(); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let infiniteHeight = this.infinite?.hostElement.getBoundingClientRect().height || 0; | ||||||
|         const scrollHeight = (this.scrollElement?.scrollHeight || 0); |         const scrollHeight = (this.scrollElement?.scrollHeight || 0); | ||||||
| 
 | 
 | ||||||
|         // If there is an ongoing fetch, wait for it to finish.
 |         // If there is an ongoing fetch, wait for it to finish.
 | ||||||
| @ -1051,7 +1064,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|                 // Try to keep the scroll position.
 |                 // Try to keep the scroll position.
 | ||||||
|                 const scrollBottom = scrollHeight - (this.scrollElement?.scrollTop || 0); |                 const scrollBottom = scrollHeight - (this.scrollElement?.scrollTop || 0); | ||||||
| 
 | 
 | ||||||
|                 const height = this.infinite?.infiniteEl?.nativeElement.getBoundingClientRect().height || 0; |                 const height = this.infinite?.hostElement.getBoundingClientRect().height || 0; | ||||||
|                 if (this.canLoadMore && infiniteHeight && this.infinite) { |                 if (this.canLoadMore && infiniteHeight && this.infinite) { | ||||||
|                     // The height of the infinite is different while spinner is shown. Add that difference.
 |                     // The height of the infinite is different while spinner is shown. Add that difference.
 | ||||||
|                     infiniteHeight = infiniteHeight - height; |                     infiniteHeight = infiniteHeight - height; | ||||||
| @ -1073,10 +1086,8 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Keep scroll position after loading previous messages. |      * Keep scroll position after loading previous messages. | ||||||
|      * We don't use resizeContent because the approach used is different and it isn't easy to calculate these positions. |  | ||||||
|      */ |      */ | ||||||
|     protected keepScroll(oldScrollHeight: number, oldScrollBottom: number, infiniteHeight: number, retries = 0): void { |     protected keepScroll(oldScrollHeight: number, oldScrollBottom: number, infiniteHeight: number, retries = 0): void { | ||||||
| 
 |  | ||||||
|         setTimeout(() => { |         setTimeout(() => { | ||||||
|             const newScrollHeight = (this.scrollElement?.scrollHeight || 0); |             const newScrollHeight = (this.scrollElement?.scrollHeight || 0); | ||||||
| 
 | 
 | ||||||
| @ -1089,53 +1100,39 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             // Scroll has changed, but maybe it hasn't reached the full height yet.
 | ||||||
|  |             setTimeout(() => { | ||||||
|  |                 const newScrollHeight = (this.scrollElement?.scrollHeight || 0); | ||||||
|                 const scrollTo = newScrollHeight - oldScrollBottom + infiniteHeight; |                 const scrollTo = newScrollHeight - oldScrollBottom + infiniteHeight; | ||||||
| 
 | 
 | ||||||
|                 this.content!.scrollToPoint(0, scrollTo, 0); |                 this.content!.scrollToPoint(0, scrollTo, 0); | ||||||
|             }, 30); |             }, 30); | ||||||
|     } |         }, 30); | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Content or scroll has been resized. For content, only call it if it's been added on top. |  | ||||||
|      */ |  | ||||||
|     resizeContent(): void { |  | ||||||
|         /* @todo probably not needed. |  | ||||||
|         let top = this.content!.getContentDimensions().scrollTop; |  | ||||||
|         // @todo this.content.resize();
 |  | ||||||
| 
 |  | ||||||
|         // Wait for new content height to be calculated.
 |  | ||||||
|         setTimeout(() => { |  | ||||||
|             // Visible content size changed, maintain the bottom position.
 |  | ||||||
|             if (!this.viewDestroyed && (this.scrollElement?.clientHeight || 0) != this.oldContentHeight) { |  | ||||||
|                 if (!top) { |  | ||||||
|                     top = this.content!.getContentDimensions().scrollTop; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 top += this.oldContentHeight - (this.scrollElement?.clientHeight || 0); |  | ||||||
|                 this.oldContentHeight = (this.scrollElement?.clientHeight || 0); |  | ||||||
| 
 |  | ||||||
|                 this.content!.scrollToPoint(0, top, 0); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         */ |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Scroll bottom when render has finished. |      * Scroll bottom when render has finished. | ||||||
|  |      * | ||||||
|  |      * @param force Whether to force scroll to bottom. | ||||||
|      */ |      */ | ||||||
|     scrollToBottom(): void { |     async scrollToBottom(force = false): Promise<void> { | ||||||
|         // Check if scroll is at bottom. If so, scroll bottom after rendering since there might be something new.
 |         // Check if scroll is at bottom. If so, scroll bottom after rendering since there might be something new.
 | ||||||
|         if (this.scrollBottom) { |         if (this.scrollBottom || force) { | ||||||
|             // Need a timeout to leave time to the view to be rendered.
 |  | ||||||
|             setTimeout(() => { |  | ||||||
|                 if (!this.viewDestroyed) { |  | ||||||
|                     this.content!.scrollToBottom(0); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             this.scrollBottom = false; |             this.scrollBottom = false; | ||||||
| 
 | 
 | ||||||
|             // Reset the badge.
 |             // Reset the badge.
 | ||||||
|             this.setNewMessagesBadge(0); |             this.setNewMessagesBadge(0); | ||||||
|  | 
 | ||||||
|  |             // Leave time for the view to be rendered.
 | ||||||
|  |             await CoreUtils.nextTicks(5); | ||||||
|  | 
 | ||||||
|  |             if (!this.viewDestroyed) { | ||||||
|  |                 this.content!.scrollToBottom(0); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (force) { | ||||||
|  |                 this.initialized = true; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -1144,7 +1141,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView | |||||||
|      */ |      */ | ||||||
|     scrollToFirstUnreadMessage(): void { |     scrollToFirstUnreadMessage(): void { | ||||||
|         if (this.newMessages > 0) { |         if (this.newMessages > 0) { | ||||||
|             const messages = Array.from(document.querySelectorAll('.addon-message-not-mine')); |             const messages = Array.from(this.hostElement.querySelectorAll('.addon-message-not-mine')); | ||||||
| 
 | 
 | ||||||
|             CoreDomUtils.scrollToElement(this.content!, <HTMLElement> messages[messages.length - this.newMessages]); |             CoreDomUtils.scrollToElement(this.content!, <HTMLElement> messages[messages.length - this.newMessages]); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -360,7 +360,7 @@ export class AddonQtypeDdImageOrTextQuestion { | |||||||
|             this.pollForImageLoad(); |             this.pollForImageLoad(); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         this.resizeFunction = this.repositionDragsForQuestion.bind(this); |         this.resizeFunction = this.windowResized.bind(this); | ||||||
|         window.addEventListener('resize', this.resizeFunction!); |         window.addEventListener('resize', this.resizeFunction!); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -679,6 +679,15 @@ export class AddonQtypeDdImageOrTextQuestion { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Window resized. | ||||||
|  |      */ | ||||||
|  |     async windowResized(): Promise<void> { | ||||||
|  |         await CoreDomUtils.waitForResizeDone(); | ||||||
|  | 
 | ||||||
|  |         this.repositionDragsForQuestion(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -601,7 +601,7 @@ export class AddonQtypeDdMarkerQuestion { | |||||||
|             this.pollForImageLoad(); |             this.pollForImageLoad(); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         this.resizeFunction = this.redrawDragsAndDrops.bind(this); |         this.resizeFunction = this.windowResized.bind(this); | ||||||
|         window.addEventListener('resize', this.resizeFunction!); |         window.addEventListener('resize', this.resizeFunction!); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -869,6 +869,15 @@ export class AddonQtypeDdMarkerQuestion { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Window resized. | ||||||
|  |      */ | ||||||
|  |     async windowResized(): Promise<void> { | ||||||
|  |         await CoreDomUtils.waitForResizeDone(); | ||||||
|  | 
 | ||||||
|  |         this.redrawDragsAndDrops(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -214,7 +214,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
| 
 | 
 | ||||||
|         this.positionDragItems(); |         this.positionDragItems(); | ||||||
| 
 | 
 | ||||||
|         this.resizeFunction = this.positionDragItems.bind(this); |         this.resizeFunction = this.windowResized.bind(this); | ||||||
|         window.addEventListener('resize', this.resizeFunction!); |         window.addEventListener('resize', this.resizeFunction!); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -515,6 +515,15 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Window resized. | ||||||
|  |      */ | ||||||
|  |     async windowResized(): Promise<void> { | ||||||
|  |         await CoreDomUtils.waitForResizeDone(); | ||||||
|  | 
 | ||||||
|  |         this.positionDragItems(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Component, Input, Output, EventEmitter, OnChanges, SimpleChange, ViewChild, ElementRef } from '@angular/core'; | import { Component, Input, Output, EventEmitter, OnChanges, SimpleChange, ViewChild, ElementRef } from '@angular/core'; | ||||||
| import { IonContent, IonInfiniteScroll } from '@ionic/angular'; | import { IonInfiniteScroll } from '@ionic/angular'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
| 
 | 
 | ||||||
| @ -37,15 +37,16 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | |||||||
|     @Output() action: EventEmitter<() => void>; // Will emit an event when triggered.
 |     @Output() action: EventEmitter<() => void>; // Will emit an event when triggered.
 | ||||||
| 
 | 
 | ||||||
|     @ViewChild('topbutton') topButton?: ElementRef; |     @ViewChild('topbutton') topButton?: ElementRef; | ||||||
|     @ViewChild('infinitescroll') infiniteEl?: ElementRef; |  | ||||||
|     @ViewChild('bottombutton') bottomButton?: ElementRef; |     @ViewChild('bottombutton') bottomButton?: ElementRef; | ||||||
|     @ViewChild('spinnercontainer') spinnerContainer?: ElementRef; |     @ViewChild('spinnercontainer') spinnerContainer?: ElementRef; | ||||||
|     @ViewChild(IonInfiniteScroll) infiniteScroll?: IonInfiniteScroll; |     @ViewChild(IonInfiniteScroll) infiniteScroll?: IonInfiniteScroll; | ||||||
| 
 | 
 | ||||||
|     loadingMore = false; // Hide button and avoid loading more.
 |     loadingMore = false; // Hide button and avoid loading more.
 | ||||||
|  |     hostElement: HTMLElement; | ||||||
| 
 | 
 | ||||||
|     constructor(protected element: ElementRef) { |     constructor(protected element: ElementRef<HTMLElement>) { | ||||||
|         this.action = new EventEmitter(); |         this.action = new EventEmitter(); | ||||||
|  |         this.hostElement = element.nativeElement; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -76,14 +77,14 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | |||||||
|         await CoreUtils.nextTick(); |         await CoreUtils.nextTick(); | ||||||
| 
 | 
 | ||||||
|         // Calculate distance from edge.
 |         // Calculate distance from edge.
 | ||||||
|         const content = this.element.nativeElement.closest('ion-content') as IonContent; |         const content = this.hostElement.closest('ion-content'); | ||||||
|         if (!content) { |         if (!content) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const scrollElement = await content.getScrollElement(); |         const scrollElement = await content.getScrollElement(); | ||||||
| 
 | 
 | ||||||
|         const infiniteHeight = this.element.nativeElement.getBoundingClientRect().height; |         const infiniteHeight = this.hostElement.getBoundingClientRect().height; | ||||||
|         const scrollTop = scrollElement.scrollTop; |         const scrollTop = scrollElement.scrollTop; | ||||||
|         const height = scrollElement.offsetHeight; |         const height = scrollElement.offsetHeight; | ||||||
|         const threshold = height * THRESHOLD; |         const threshold = height * THRESHOLD; | ||||||
| @ -141,11 +142,20 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | |||||||
|      * @deprecated since 3.9.5 |      * @deprecated since 3.9.5 | ||||||
|      */ |      */ | ||||||
|     getHeight(): number { |     getHeight(): number { | ||||||
|         // return this.element.nativeElement.getBoundingClientRect().height;
 |         return (this.position == 'top' ? | ||||||
|  |             this.getElementHeight(this.topButton?.nativeElement) : | ||||||
|  |             this.getElementHeight(this.bottomButton?.nativeElement)) + | ||||||
|  |             this.getElementHeight(this.infiniteScrollElement) + | ||||||
|  |             this.getElementHeight(this.spinnerContainer?.nativeElement); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         return (this.position == 'top' ? this.getElementHeight(this.topButton): this.getElementHeight(this.bottomButton)) + |     /** | ||||||
|             this.getElementHeight(this.infiniteEl) + |      * Get the infinite scroll element. | ||||||
|             this.getElementHeight(this.spinnerContainer); |      * | ||||||
|  |      * @return Element or null. | ||||||
|  |      */ | ||||||
|  |     get infiniteScrollElement(): HTMLIonInfiniteScrollElement | null { | ||||||
|  |         return this.hostElement.querySelector('ion-infinite-scroll'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -154,9 +164,9 @@ export class CoreInfiniteLoadingComponent implements OnChanges { | |||||||
|      * @param element Element ref. |      * @param element Element ref. | ||||||
|      * @return Height. |      * @return Height. | ||||||
|      */ |      */ | ||||||
|     protected getElementHeight(element?: ElementRef): number { |     protected getElementHeight(element?: HTMLElement | null): number { | ||||||
|         if (element && element.nativeElement) { |         if (element) { | ||||||
|             return CoreDomUtils.getElementHeight(element.nativeElement, true, true, true); |             return CoreDomUtils.getElementHeight(element, true, true, true); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return 0; |         return 0; | ||||||
|  | |||||||
| @ -1861,6 +1861,32 @@ export class CoreDomUtilsProvider { | |||||||
|         CoreForms.triggerFormSubmittedEvent(formRef, online, siteId); |         CoreForms.triggerFormSubmittedEvent(formRef, online, siteId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * In iOS the resize event is triggered before the window size changes. Wait for the size to change. | ||||||
|  |      * | ||||||
|  |      * @param windowWidth Initial window width. | ||||||
|  |      * @param windowHeight Initial window height. | ||||||
|  |      * @param retries Number of retries done. | ||||||
|  |      */ | ||||||
|  |     async waitForResizeDone(windowWidth?: number, windowHeight?: number, retries = 0): Promise<void> { | ||||||
|  |         if (!CoreApp.isIOS()) { | ||||||
|  |             return; // Only wait in iOS.
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         windowWidth = windowWidth || window.innerWidth; | ||||||
|  |         windowHeight = windowHeight || window.innerHeight; | ||||||
|  | 
 | ||||||
|  |         if (windowWidth != window.innerWidth || windowHeight != window.innerHeight || retries >= 10) { | ||||||
|  |             // Window size changed or max number of retries reached, stop.
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Wait a bit and try again.
 | ||||||
|  |         await CoreUtils.wait(50); | ||||||
|  | 
 | ||||||
|  |         return this.waitForResizeDone(windowWidth, windowHeight, retries+1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -1666,6 +1666,15 @@ export class CoreUtilsProvider { | |||||||
|         return this.wait(0); |         return this.wait(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Wait until several next ticks. | ||||||
|  |      */ | ||||||
|  |     async nextTicks(numTicks = 0): Promise<void> { | ||||||
|  |         for (let i = 0; i < numTicks; i++) { | ||||||
|  |             await this.wait(0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Given some options, check if a file should be opened with showOpenWithDialog. |      * Given some options, check if a file should be opened with showOpenWithDialog. | ||||||
|      * |      * | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user