fix(routing): flickering (part 1)

This commit is contained in:
Manu Mtz.-Almeida
2018-03-07 00:14:05 +01:00
parent 9650bec06a
commit 7b264f983b
7 changed files with 78 additions and 45 deletions

View File

@@ -223,6 +223,11 @@ export class NavControllerBase implements NavOutlet {
return null;
}
@Method()
markVisible() {
return Promise.resolve();
}
@Method()
getContentElement(): HTMLElement {
const active = this.getActive();

View File

@@ -71,6 +71,9 @@ Return a view controller
#### insertPages()
#### markVisible()
#### pop()

View File

@@ -18,9 +18,11 @@ export function writeNavState(root: HTMLElement, chain: RouteChain, index: numbe
}
const nextEl = node.getContentElement();
if (nextEl) {
return writeNavState(nextEl, chain, index + 1, direction);
return writeNavState(nextEl, chain, index + 1, direction)
.then(() => node.markVisible());
} else {
return node.markVisible();
}
return null;
});
}

View File

@@ -1,7 +1,9 @@
export interface NavOutlet {
setRouteId(id: any, data: any, direction: number): Promise<boolean>;
markVisible(): Promise<void>;
getRouteId(): string;
getContentElement(): HTMLElement | null;
}

View File

@@ -9,7 +9,7 @@ import { asyncRaf } from '../../utils/helpers';
export class Tab {
private loaded = false;
@Element() el: HTMLElement;
@Element() el: HTMLIonTabElement;
@State() init = false;
@@ -92,7 +92,7 @@ export class Tab {
}
@Method()
setActive(): Promise<any> {
setActive(): Promise<HTMLIonTabElement> {
return this.prepareLazyLoaded().then(() => this.showTab());
}
@@ -104,9 +104,9 @@ export class Tab {
return Promise.resolve();
}
private showTab(): Promise<any|void> {
private showTab(): Promise<HTMLIonTabElement> {
this.active = true;
return Promise.resolve();
return Promise.resolve(this.el);
}
hostData() {

View File

@@ -240,6 +240,9 @@ Emitted when the tab changes.
#### getTabs()
#### markVisible()
#### select()

View File

@@ -9,6 +9,8 @@ import { Config, NavOutlet } from '../../index';
export class Tabs implements NavOutlet {
private ids = -1;
private transitioning = false;
private routingView: HTMLIonTabElement;
private tabsId: number = (++tabIds);
@Element() el: HTMLElement;
@@ -73,10 +75,7 @@ export class Tabs implements NavOutlet {
}
componentDidLoad() {
return this.initTabs().then(() => {
const useRouter = !!document.querySelector('ion-router');
return useRouter ? this.initSelect() : Promise.resolve();
});
return this.initTabs().then(() => this.initSelect());
}
componentDidUnload() {
@@ -95,37 +94,8 @@ export class Tabs implements NavOutlet {
*/
@Method()
select(tabOrIndex: number | HTMLIonTabElement): Promise<boolean> {
if (this.transitioning) {
return Promise.resolve(false);
}
const selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
if (!selectedTab) {
return Promise.resolve(false);
}
// Reset rest of tabs
for (const tab of this.tabs) {
if (selectedTab !== tab) {
tab.selected = false;
}
}
const leavingTab = this.selectedTab;
this.transitioning = true;
return selectedTab.setActive().then(() => {
this.transitioning = false;
selectedTab.selected = true;
if (leavingTab !== selectedTab) {
if (leavingTab) {
leavingTab.active = false;
}
this.selectedTab = selectedTab;
this.ionChange.emit(selectedTab);
this.ionNavChanged.emit({isPop: false});
return true;
}
return false;
});
return this.setActive(tabOrIndex)
.then(selectedTab => this.tabSwitch(selectedTab));
}
/**
@@ -161,9 +131,18 @@ export class Tabs implements NavOutlet {
return Promise.resolve(false);
}
const tab = this.tabs.find(t => id === t.getRouteId());
return this.select(tab).then(() => true);
return this.setActive(tab).then(() => {
this.routingView = tab;
return true;
});
}
@Method()
markVisible(): Promise<void> {
this.tabSwitch(this.routingView);
this.routingView = null;
return Promise.resolve();
}
@Method()
getRouteId(): string|null {
@@ -176,7 +155,7 @@ export class Tabs implements NavOutlet {
@Method()
getContentElement(): HTMLElement {
return this.selectedTab;
return this.routingView || this.selectedTab;
}
private initTabs() {
@@ -191,7 +170,7 @@ export class Tabs implements NavOutlet {
return Promise.all(tabPromises);
}
private initSelect() {
private initSelect(): Promise<void> {
if (document.querySelector('ion-router')) {
return Promise.resolve();
}
@@ -205,7 +184,7 @@ export class Tabs implements NavOutlet {
tab.selected = false;
}
}
const promise = selectedTab ? selectedTab.setActive() : Promise.resolve();
const promise = selectedTab ? selectedTab.setActive() : Promise.resolve(null);
return promise.then(() => {
this.selectedTab = selectedTab;
if (selectedTab) {
@@ -222,6 +201,45 @@ export class Tabs implements NavOutlet {
}
}
private setActive(tabOrIndex: number | HTMLIonTabElement): Promise<HTMLIonTabElement|null> {
if (this.transitioning) {
return Promise.resolve(null);
}
const selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
if (!selectedTab) {
return Promise.resolve(null);
}
// Reset rest of tabs
for (const tab of this.tabs) {
if (selectedTab !== tab) {
tab.selected = false;
}
}
this.transitioning = true;
return selectedTab.setActive();
}
private tabSwitch(selectedTab: HTMLIonTabElement | null): boolean {
this.transitioning = false;
if (!selectedTab) {
return false;
}
const leavingTab = this.selectedTab;
selectedTab.selected = true;
if (leavingTab !== selectedTab) {
if (leavingTab) {
leavingTab.active = false;
}
this.selectedTab = selectedTab;
this.ionChange.emit(selectedTab);
this.ionNavChanged.emit({isPop: false});
return true;
}
return false;
}
render() {
const dom = [
<div class='tabs-inner'>