MOBILE-2557 core: Recalculate format-text when core-loading changes

main
Dani Palou 2018-08-27 12:50:56 +02:00
parent 9f7e5087c6
commit e000151ab1
5 changed files with 68 additions and 13 deletions

View File

@ -4,7 +4,7 @@
<p class="core-loading-message" *ngIf="message">{{message}}</p> <p class="core-loading-message" *ngIf="message">{{message}}</p>
</span> </span>
</div> </div>
<div #content class="core-loading-content"> <div #content class="core-loading-content" [id]="uniqueId">
<ng-content [@coreShowHideAnimation] *ngIf="hideUntil"> <ng-content [@coreShowHideAnimation] *ngIf="hideUntil">
</ng-content> </ng-content>
</div> </div>

View File

@ -15,6 +15,8 @@
import { Component, Input, OnInit, OnChanges, SimpleChange, ViewChild, ElementRef } from '@angular/core'; import { Component, Input, OnInit, OnChanges, SimpleChange, ViewChild, ElementRef } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { coreShowHideAnimation } from '@classes/animations'; import { coreShowHideAnimation } from '@classes/animations';
import { CoreEventsProvider } from '@providers/events';
import { CoreUtilsProvider } from '@providers/utils/utils';
/** /**
* Component to show a loading spinner and message while data is being loaded. * Component to show a loading spinner and message while data is being loaded.
@ -45,10 +47,16 @@ export class CoreLoadingComponent implements OnInit, OnChanges {
@Input() hideUntil: boolean; // Determine when should the contents be shown. @Input() hideUntil: boolean; // Determine when should the contents be shown.
@Input() message?: string; // Message to show while loading. @Input() message?: string; // Message to show while loading.
@ViewChild('content') content: ElementRef; @ViewChild('content') content: ElementRef;
protected uniqueId: string;
protected element: HTMLElement; // Current element. protected element: HTMLElement; // Current element.
constructor(private translate: TranslateService, element: ElementRef) { constructor(private translate: TranslateService, element: ElementRef, private eventsProvider: CoreEventsProvider,
utils: CoreUtilsProvider) {
this.element = element.nativeElement; this.element = element.nativeElement;
// Calculate the unique ID.
this.uniqueId = 'core-loading-content-' + utils.getUniqueId('CoreLoadingComponent');
} }
/** /**
@ -62,14 +70,27 @@ export class CoreLoadingComponent implements OnInit, OnChanges {
} }
ngOnChanges(changes: { [name: string]: SimpleChange }): void { ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if (changes.hideUntil.currentValue === true) { if (changes.hideUntil) {
setTimeout(() => { if (changes.hideUntil.currentValue === true) {
// Content is loaded so, center the spinner on the content itself.
this.element.classList.add('core-loading-loaded');
setTimeout(() => { setTimeout(() => {
// Change CSS to force calculate height. // Content is loaded so, center the spinner on the content itself.
this.content.nativeElement.classList.add('core-loading-content'); this.element.classList.add('core-loading-loaded');
}, 500); setTimeout(() => {
// Change CSS to force calculate height.
this.content.nativeElement.classList.add('core-loading-content');
}, 500);
});
} else {
this.element.classList.remove('core-loading-loaded');
this.content.nativeElement.classList.remove('core-loading-content');
}
// Trigger the event after a timeout since the elements inside ngIf haven't been added to DOM yet.
setTimeout(() => {
this.eventsProvider.trigger(CoreEventsProvider.CORE_LOADING_CHANGED, {
loaded: changes.hideUntil.currentValue,
uniqueId: this.uniqueId
});
}); });
} }
} }

View File

@ -16,6 +16,7 @@ import { Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleCh
import { Platform, NavController, Content } from 'ionic-angular'; import { Platform, NavController, Content } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { CoreAppProvider } from '@providers/app'; import { CoreAppProvider } from '@providers/app';
import { CoreEventsProvider } from '@providers/events';
import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreFilepoolProvider } from '@providers/filepool';
import { CoreLoggerProvider } from '@providers/logger'; import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
@ -58,6 +59,7 @@ export class CoreFormatTextDirective implements OnChanges {
protected element: HTMLElement; protected element: HTMLElement;
protected showMoreDisplayed: boolean; protected showMoreDisplayed: boolean;
protected loadingChangedListener;
constructor(element: ElementRef, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, constructor(element: ElementRef, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider,
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform, private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
@ -65,7 +67,7 @@ export class CoreFormatTextDirective implements OnChanges {
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider, private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController, private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController,
@Optional() private content: Content, @Optional() private svComponent: CoreSplitViewComponent, @Optional() private content: Content, @Optional() private svComponent: CoreSplitViewComponent,
private iframeUtils: CoreIframeUtilsProvider) { private iframeUtils: CoreIframeUtilsProvider, private eventsProvider: CoreEventsProvider) {
this.element = element.nativeElement; this.element = element.nativeElement;
this.element.classList.add('opacity-hide'); // Hide contents until they're treated. this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
this.afterRender = new EventEmitter(); this.afterRender = new EventEmitter();
@ -174,10 +176,16 @@ export class CoreFormatTextDirective implements OnChanges {
* Calculate the height and check if we need to display show more or not. * Calculate the height and check if we need to display show more or not.
*/ */
protected calculateHeight(): void { protected calculateHeight(): void {
// Height cannot be calculated if the element is not shown while calculating.
// Force shorten if it was previously shortened.
// @todo: Work on calculate this height better. // @todo: Work on calculate this height better.
const height = this.element.style.maxHeight ? 0 : this.getElementHeight(this.element);
// Remove max-height (if any) to calculate the real height.
const initialMaxHeight = this.element.style.maxHeight;
this.element.style.maxHeight = null;
const height = this.getElementHeight(this.element);
// Restore the max height now.
this.element.style.maxHeight = initialMaxHeight;
// If cannot calculate height, shorten always. // If cannot calculate height, shorten always.
if (!height || height > this.maxHeight) { if (!height || height > this.maxHeight) {
@ -290,6 +298,16 @@ export class CoreFormatTextDirective implements OnChanges {
this.calculateHeight(); this.calculateHeight();
} }
}); });
if (!this.loadingChangedListener) {
// Recalculate the height if a parent core-loading displays the content.
this.loadingChangedListener = this.eventsProvider.on(CoreEventsProvider.CORE_LOADING_CHANGED, (data) => {
if (data.loaded && this.domUtils.closest(this.element.parentElement, '#' + data.uniqueId)) {
// The format-text is inside the loading, re-calculate the height.
this.calculateHeight();
}
});
}
} else { } else {
this.domUtils.moveChildren(div, this.element); this.domUtils.moveChildren(div, this.element);
} }

View File

@ -55,6 +55,7 @@ export class CoreEventsProvider {
static APP_LAUNCHED_URL = 'app_launched_url'; // App opened with a certain URL (custom URL scheme). static APP_LAUNCHED_URL = 'app_launched_url'; // App opened with a certain URL (custom URL scheme).
static FILE_SHARED = 'file_shared'; static FILE_SHARED = 'file_shared';
static KEYBOARD_CHANGE = 'keyboard_change'; static KEYBOARD_CHANGE = 'keyboard_change';
static CORE_LOADING_CHANGED = 'core_loading_changed';
protected logger; protected logger;
protected observables: { [s: string]: Subject<any> } = {}; protected observables: { [s: string]: Subject<any> } = {};

View File

@ -59,6 +59,7 @@ export interface PromiseDefer {
export class CoreUtilsProvider { export class CoreUtilsProvider {
protected logger; protected logger;
protected iabInstance: InAppBrowserObject; protected iabInstance: InAppBrowserObject;
protected uniqueIds: {[name: string]: number} = {};
constructor(private iab: InAppBrowser, private appProvider: CoreAppProvider, private clipboard: Clipboard, constructor(private iab: InAppBrowser, private appProvider: CoreAppProvider, private clipboard: Clipboard,
private domUtils: CoreDomUtilsProvider, logger: CoreLoggerProvider, private translate: TranslateService, private domUtils: CoreDomUtilsProvider, logger: CoreLoggerProvider, private translate: TranslateService,
@ -571,6 +572,20 @@ export class CoreUtilsProvider {
}); });
} }
/**
* Get a unique ID for a certain name.
*
* @param {string} name The name to get the ID for.
* @return {number} Unique ID.
*/
getUniqueId(name: string): number {
if (!this.uniqueIds[name]) {
this.uniqueIds[name] = 0;
}
return ++this.uniqueIds[name];
}
/** /**
* Given a list of files, check if there are repeated names. * Given a list of files, check if there are repeated names.
* *