MOBILE-3833 collapsible: Change collapsible visible strategy
parent
e3e54ec194
commit
50c3985822
|
@ -683,7 +683,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
|
|||
* Go to search courses.
|
||||
*/
|
||||
async openSearch(): Promise<void> {
|
||||
CoreNavigator.navigateToSitePath('/list', { params : { mode: 'search' } });
|
||||
CoreNavigator.navigateToSitePath('courses/list', { params : { mode: 'search' } });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,7 +50,8 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
protected endContentScrollListener?: EventListener;
|
||||
protected resizeListener?: CoreEventObserver;
|
||||
protected slotPromise?: CoreCancellablePromise<void>;
|
||||
protected calcPending = false;
|
||||
protected viewportPromise?: CoreCancellablePromise<void>;
|
||||
protected loadingHeight = false;
|
||||
protected pageDidEnterListener?: EventListener;
|
||||
protected page?: HTMLElement;
|
||||
|
||||
|
@ -85,13 +86,14 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
* Calculate the height of the footer.
|
||||
*/
|
||||
protected async calculateHeight(): Promise<void> {
|
||||
if (!CoreDom.isElementVisible(this.element)) {
|
||||
this.calcPending = true;
|
||||
|
||||
if (this.loadingHeight) {
|
||||
// Already calculating, return.
|
||||
return;
|
||||
}
|
||||
this.loadingHeight = true;
|
||||
|
||||
this.calcPending = false;
|
||||
this.viewportPromise = CoreDom.waitToBeInViewport(this.element);
|
||||
await this.viewportPromise;
|
||||
|
||||
this.element.classList.remove('is-active');
|
||||
await CoreUtils.nextTick();
|
||||
|
@ -110,6 +112,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
this.element.classList.add('is-active');
|
||||
|
||||
this.setBarHeight(this.initialHeight);
|
||||
this.loadingHeight = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,9 +178,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
this.page?.addEventListener(
|
||||
'ionViewDidEnter',
|
||||
this.pageDidEnterListener = () => {
|
||||
if (this.calcPending) {
|
||||
this.calculateHeight();
|
||||
}
|
||||
this.calculateHeight();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -255,6 +256,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
|
|||
|
||||
this.resizeListener?.off();
|
||||
this.slotPromise?.cancel();
|
||||
this.viewportPromise?.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChange } from '@angular/core';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||
import { CoreLoadingComponent } from '@components/loading/loading';
|
||||
import { CoreTabsOutletComponent } from '@components/tabs-outlet/tabs-outlet';
|
||||
import { CoreTabsComponent } from '@components/tabs/tabs';
|
||||
|
@ -69,17 +69,15 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
protected content?: HTMLIonContentElement;
|
||||
protected contentScrollListener?: EventListener;
|
||||
protected endContentScrollListener?: EventListener;
|
||||
protected pageDidEnterListener?: EventListener;
|
||||
protected resizeListener?: CoreEventObserver;
|
||||
protected floatingTitle?: HTMLHeadingElement;
|
||||
protected scrollingHeight?: number;
|
||||
protected subscriptions: Subscription[] = [];
|
||||
protected enabled = true;
|
||||
protected isWithinContent = false;
|
||||
protected enteredPromise = new CorePromisedValue<void>();
|
||||
protected mutationObserver?: MutationObserver;
|
||||
protected firstEnter = true;
|
||||
protected initPending = false;
|
||||
protected loadingFloatingTitle = false;
|
||||
protected visiblePromise?: CoreCancellablePromise<void>;
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
this.collapsedHeader = el.nativeElement;
|
||||
|
@ -106,10 +104,9 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
await Promise.all([
|
||||
this.initializeCollapsedHeader(),
|
||||
this.initializeExpandedHeader(),
|
||||
await this.enteredPromise,
|
||||
]);
|
||||
|
||||
this.initializeFloatingTitle();
|
||||
await this.initializeFloatingTitle();
|
||||
this.initializeContent();
|
||||
}
|
||||
|
||||
|
@ -117,7 +114,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
* @inheritdoc
|
||||
*/
|
||||
async ngOnChanges(changes: {[name: string]: SimpleChange}): Promise<void> {
|
||||
if (changes.collapsible) {
|
||||
if (changes.collapsible && !changes.collapsible.firstChange) {
|
||||
this.collapsible = !CoreUtils.isFalseOrZero(changes.collapsible.currentValue);
|
||||
this.enabled = this.collapsible;
|
||||
|
||||
|
@ -141,47 +138,16 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
if (this.content && this.endContentScrollListener) {
|
||||
this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
|
||||
}
|
||||
if (this.page && this.pageDidEnterListener) {
|
||||
this.page.removeEventListener('ionViewDidEnter', this.pageDidEnterListener);
|
||||
}
|
||||
|
||||
this.resizeListener?.off();
|
||||
this.mutationObserver?.disconnect();
|
||||
this.visiblePromise?.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the page element, initialize it, and wait until it's ready for the transition to trigger on scroll.
|
||||
* Listen to changing events.
|
||||
*/
|
||||
protected initializePage(): void {
|
||||
if (!this.collapsedHeader.parentElement) {
|
||||
throw new Error('[collapsible-header] Couldn\'t get page');
|
||||
}
|
||||
|
||||
// Find element and prepare classes.
|
||||
this.page = this.collapsedHeader.parentElement;
|
||||
this.page.classList.add('collapsible-header-page');
|
||||
|
||||
this.page.addEventListener(
|
||||
'ionViewDidEnter',
|
||||
this.pageDidEnterListener = () => {
|
||||
if (this.firstEnter) {
|
||||
this.firstEnter = false;
|
||||
clearTimeout(timeout);
|
||||
this.enteredPromise.resolve();
|
||||
} else if (this.initPending) {
|
||||
this.initializeFloatingTitle();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Timeout in case event is never fired.
|
||||
const timeout = window.setTimeout(() => {
|
||||
if (this.firstEnter) {
|
||||
this.firstEnter = false;
|
||||
this.enteredPromise.reject(new Error('[collapsible-header] Waiting for ionViewDidEnter timeout reached'));
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
protected listenEvents(): void {
|
||||
this.resizeListener = CoreDom.onWindowResize(() => {
|
||||
this.initializeFloatingTitle();
|
||||
}, 50);
|
||||
|
@ -216,6 +182,19 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the page element, initialize it, and wait until it's ready for the transition to trigger on scroll.
|
||||
*/
|
||||
protected initializePage(): void {
|
||||
if (!this.collapsedHeader.parentElement) {
|
||||
throw new Error('[collapsible-header] Couldn\'t get page');
|
||||
}
|
||||
|
||||
// Find element and prepare classes.
|
||||
this.page = this.collapsedHeader.parentElement;
|
||||
this.page.classList.add('collapsible-header-page');
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the collapsed header element, initialize it, and wait until it's ready for the transition to trigger on scroll.
|
||||
*/
|
||||
|
@ -253,6 +232,8 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
return;
|
||||
}
|
||||
|
||||
this.listenEvents();
|
||||
|
||||
// Initialize from tabs.
|
||||
const tabs = CoreComponentsRegistry.resolve(this.page.querySelector('core-tabs-outlet'), CoreTabsOutletComponent);
|
||||
|
||||
|
@ -284,21 +265,22 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
/**
|
||||
* Initialize a floating title to mimic transitioning the title from one state to the other.
|
||||
*/
|
||||
protected initializeFloatingTitle(): void {
|
||||
protected async initializeFloatingTitle(): Promise<void> {
|
||||
if (!this.page || !this.expandedHeader) {
|
||||
throw new Error('[collapsible-header] Couldn\'t create floating title');
|
||||
}
|
||||
|
||||
if (!CoreDom.isElementVisible(this.expandedHeader)) {
|
||||
this.initPending = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.initPending = false;
|
||||
if (this.loadingFloatingTitle) {
|
||||
// Already calculating, return.
|
||||
return;
|
||||
}
|
||||
this.loadingFloatingTitle = true;
|
||||
|
||||
this.visiblePromise = CoreDom.waitToBeVisible(this.expandedHeader);
|
||||
await this.visiblePromise;
|
||||
|
||||
this.page.classList.remove('collapsible-header-page-is-active');
|
||||
CoreUtils.nextTick();
|
||||
await CoreUtils.nextTick();
|
||||
|
||||
// Add floating title and measure initial position.
|
||||
const collapsedHeaderTitle = this.collapsedHeader.querySelector('h1') as HTMLHeadingElement;
|
||||
|
@ -370,6 +352,8 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
this.collapsedFontStyles = collapsedFontStyles;
|
||||
this.expandedFontStyles = expandedFontStyles;
|
||||
this.expandedHeaderHeight = expandedHeaderHeight;
|
||||
|
||||
this.loadingFloatingTitle = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,8 +55,9 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
protected resizeListener?: CoreEventObserver;
|
||||
protected darkModeListener?: Subscription;
|
||||
protected domPromise?: CoreCancellablePromise<void>;
|
||||
protected visiblePromise?: CoreCancellablePromise<void>;
|
||||
protected uniqueId: string;
|
||||
protected calcPending = false;
|
||||
protected loadingHeight = false;
|
||||
protected pageDidEnterListener?: EventListener;
|
||||
protected page?: HTMLElement;
|
||||
|
||||
|
@ -99,9 +100,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
this.page?.addEventListener(
|
||||
'ionViewDidEnter',
|
||||
this.pageDidEnterListener = () => {
|
||||
if (this.calcPending) {
|
||||
this.calculateHeight();
|
||||
}
|
||||
this.calculateHeight();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -143,20 +142,20 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
* Calculate the height and check if we need to display show more or not.
|
||||
*/
|
||||
protected async calculateHeight(): Promise<void> {
|
||||
if (this.loadingHeight) {
|
||||
// Already calculating, return.
|
||||
return;
|
||||
}
|
||||
this.loadingHeight = true;
|
||||
|
||||
this.visiblePromise = CoreDom.waitToBeVisible(this.element);
|
||||
await this.visiblePromise;
|
||||
|
||||
// Remove max-height (if any) to calculate the real height.
|
||||
this.element.classList.add('collapsible-loading-height');
|
||||
|
||||
await this.waitFormatTextsRendered();
|
||||
|
||||
if (!this.element.clientHeight) {
|
||||
this.calcPending = true;
|
||||
this.element.classList.remove('collapsible-loading-height');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.calcPending = false;
|
||||
|
||||
this.expandedHeight = this.element.getBoundingClientRect().height;
|
||||
|
||||
// Restore the max height now.
|
||||
|
@ -167,6 +166,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
this.setExpandButtonEnabled(enable);
|
||||
this.setGradientColor();
|
||||
|
||||
this.loadingHeight = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,6 +298,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
this.resizeListener?.off();
|
||||
this.darkModeListener?.unsubscribe();
|
||||
this.domPromise?.cancel();
|
||||
this.visiblePromise?.cancel();
|
||||
|
||||
if (this.page && this.pageDidEnterListener) {
|
||||
this.page.removeEventListener('ionViewDidEnter', this.pageDidEnterListener);
|
||||
|
|
Loading…
Reference in New Issue