MOBILE-3947 swipe: Fix Swipe slides update component
parent
210b3a75a3
commit
522d1e2c79
|
@ -142,7 +142,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
}
|
||||
|
||||
/**
|
||||
* Component loaded.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.canNavigate = typeof this.canNavigate == 'undefined' ? true : CoreUtils.isTrueOrOne(this.canNavigate);
|
||||
|
@ -164,7 +164,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
}
|
||||
|
||||
/**
|
||||
* Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays).
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngDoCheck(): void {
|
||||
const items = this.manager?.getSource().getItems();
|
||||
|
@ -368,7 +368,7 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
|
|||
}
|
||||
|
||||
/**
|
||||
* Component destroyed.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.undeleteEventObserver?.off();
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
import {
|
||||
Component, ContentChild, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChange, TemplateRef, ViewChild,
|
||||
} from '@angular/core';
|
||||
import { AsyncDirective } from '@classes/async-directive';
|
||||
import { CoreSwipeSlidesItemsManager } from '@classes/items-management/swipe-slides-items-manager';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { IonContent } from '@ionic/angular';
|
||||
import { CoreDomUtils, VerticalPoint } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
@ -32,7 +34,7 @@ import { SwiperOptions } from 'swiper/types';
|
|||
templateUrl: 'swipe-slides.html',
|
||||
styleUrls: ['swipe-slides.scss'],
|
||||
})
|
||||
export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDestroy {
|
||||
export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDestroy, AsyncDirective {
|
||||
|
||||
@Input() manager?: CoreSwipeSlidesItemsManager<Item>;
|
||||
@Input() options: CoreSwipeSlidesOptions = {};
|
||||
|
@ -46,22 +48,21 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
* This setTimeout waits for Ionic's async initialization to complete.
|
||||
* Otherwise, an outdated swiper reference will be used.
|
||||
*/
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
if (swiperRef?.nativeElement?.swiper) {
|
||||
this.swiper = swiperRef.nativeElement.swiper as Swiper;
|
||||
|
||||
await this.initialize();
|
||||
|
||||
if (this.options.initialSlide) {
|
||||
this.swiper.slideTo(this.options.initialSlide, 0, this.options.runCallbacksOnInit);
|
||||
}
|
||||
|
||||
this.updateOptions();
|
||||
|
||||
this.swiper.on('slideChangeTransitionStart', () => this.slideWillChange());
|
||||
this.swiper.on('slideChangeTransitionEnd', () => this.slideDidChange());
|
||||
|
||||
Object.keys(this.options).forEach((key) => {
|
||||
if (this.swiper) {
|
||||
this.swiper.params[key] = this.options[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
@ -72,6 +73,7 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
protected unsubscribe?: () => void;
|
||||
protected resizeListener: CoreEventObserver;
|
||||
protected activeSlideIndexes: number[] = [];
|
||||
protected onReadyPromise = new CorePromisedValue<void>();
|
||||
|
||||
constructor(
|
||||
elementRef: ElementRef<HTMLElement>,
|
||||
|
@ -87,17 +89,11 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||
if (!this.unsubscribe && this.manager) {
|
||||
this.initialize(this.manager);
|
||||
}
|
||||
async ngOnChanges(changes: { [name: string]: SimpleChange }): Promise<void> {
|
||||
await this.initialize();
|
||||
|
||||
if (changes.options) {
|
||||
Object.keys(this.options).forEach((key) => {
|
||||
if (this.swiper) {
|
||||
this.swiper.params[key] = this.options[key];
|
||||
}
|
||||
});
|
||||
this.updateOptions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,8 +118,12 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
/**
|
||||
* Initialize some properties based on the manager.
|
||||
*/
|
||||
protected async initialize(manager: CoreSwipeSlidesItemsManager<Item>): Promise<void> {
|
||||
this.unsubscribe = manager.getSource().addListener({
|
||||
protected async initialize(): Promise<void> {
|
||||
if (this.unsubscribe || !this.swiper || !this.manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.unsubscribe = this.manager.getSource().addListener({
|
||||
onItemsUpdated: () => this.onItemsUpdated(),
|
||||
});
|
||||
|
||||
|
@ -131,16 +131,16 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
// This is because default callbacks aren't triggered for index 0, and to prevent auto scroll on init.
|
||||
this.options.runCallbacksOnInit = false;
|
||||
|
||||
await manager.getSource().waitForLoaded();
|
||||
await this.manager.getSource().waitForLoaded();
|
||||
|
||||
if (this.options.initialSlide === undefined) {
|
||||
// Calculate the initial slide.
|
||||
const index = manager.getSource().getInitialItemIndex();
|
||||
const index = this.manager.getSource().getInitialItemIndex();
|
||||
this.options.initialSlide = Math.max(index, 0);
|
||||
}
|
||||
|
||||
// Emit change events with the initial item.
|
||||
const items = manager.getSource().getItems();
|
||||
const items = this.manager.getSource().getItems();
|
||||
if (!items || !items.length) {
|
||||
return;
|
||||
}
|
||||
|
@ -155,9 +155,11 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
|
||||
this.activeSlideIndexes = [initialIndex];
|
||||
|
||||
manager.setSelectedItem(items[initialIndex]);
|
||||
this.manager.setSelectedItem(items[initialIndex]);
|
||||
this.onWillChange.emit(initialItemData);
|
||||
this.onDidChange.emit(initialItemData);
|
||||
|
||||
this.onReadyPromise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,19 +169,20 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
* @param speed Animation speed.
|
||||
* @param runCallbacks Whether to run callbacks.
|
||||
*/
|
||||
slideToIndex(index: number, speed?: number, runCallbacks?: boolean): void {
|
||||
async slideToIndex(index: number, speed?: number, runCallbacks?: boolean): Promise<void> {
|
||||
// If slides are being updated, wait for the update to finish.
|
||||
if (!this.swiper) {
|
||||
return;
|
||||
}
|
||||
await this.ready();
|
||||
|
||||
// Verify that the number of slides matches the number of items.
|
||||
const slidesLength = this.swiper.slides.length;
|
||||
const slidesLength = this.swiper?.slides?.length || 0;
|
||||
if (slidesLength !== this.items.length) {
|
||||
// Number doesn't match, do a new update to try to match them.
|
||||
this.updateSlidesComponent();
|
||||
await this.updateSlidesComponent();
|
||||
}
|
||||
|
||||
if (!this.swiper?.slides) {
|
||||
return;
|
||||
}
|
||||
this.swiper?.slideTo(index, speed, runCallbacks);
|
||||
}
|
||||
|
||||
|
@ -190,10 +193,10 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
* @param speed Animation speed.
|
||||
* @param runCallbacks Whether to run callbacks.
|
||||
*/
|
||||
slideToItem(item: Item, speed?: number, runCallbacks?: boolean): void {
|
||||
async slideToItem(item: Item, speed?: number, runCallbacks?: boolean): Promise<void> {
|
||||
const index = this.manager?.getSource().getItemIndex(item) ?? -1;
|
||||
if (index != -1) {
|
||||
this.slideToIndex(index, speed, runCallbacks);
|
||||
await this.slideToIndex(index, speed, runCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,7 +228,7 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
await CoreUtils.nextTick();
|
||||
|
||||
// Update the slides component so the slides list reflects the new items.
|
||||
this.updateSlidesComponent();
|
||||
await this.updateSlidesComponent();
|
||||
|
||||
const currentItem = this.manager?.getSelectedItem();
|
||||
|
||||
|
@ -234,10 +237,26 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
}
|
||||
|
||||
// Keep the same slide in case the list has changed.
|
||||
const newIndex = this.manager.getSource().getItemIndex(currentItem) ?? -1;
|
||||
if (newIndex != -1) {
|
||||
this.swiper?.slideTo(newIndex, 0, false);
|
||||
this.slideToItem(currentItem, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Swiper params from options.
|
||||
*/
|
||||
protected updateOptions(): void {
|
||||
if (!this.swiper) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.swiper.params === undefined) {
|
||||
this.swiper.params = {};
|
||||
}
|
||||
|
||||
Object.keys(this.options).forEach((key) => {
|
||||
if (this.swiper) {
|
||||
this.swiper.params[key] = this.options[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,8 +341,24 @@ export class CoreSwipeSlidesComponent<Item = unknown> implements OnChanges, OnDe
|
|||
/**
|
||||
* Update slides component.
|
||||
*/
|
||||
updateSlidesComponent(): void {
|
||||
async updateSlidesComponent(): Promise<void> {
|
||||
await this.ready();
|
||||
|
||||
if (!this.swiper) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.swiper?.update();
|
||||
|
||||
// We need to ensure the slides are updated before continuing.
|
||||
await CoreUtils.nextTicks(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async ready(): Promise<void> {
|
||||
return this.onReadyPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue