Skip to content

Commit

Permalink
perf(tabs): improve tab switching response
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat authored and adamdbradley committed Nov 28, 2016
1 parent d2ebac3 commit 907191b
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 16 deletions.
2 changes: 1 addition & 1 deletion scripts/gulp/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function createTempTsConfig(includeGlob: string[], target: string, module
}

function removeDebugStatements() {
let replacer = new Replacer(['console.debug', 'assert']);
let replacer = new Replacer(['console.debug', 'assert', 'runInDev']);
return through.obj(function (file, encoding, callback) {
const content = file.contents.toString();
const cleanedJs = replacer.replace(content);
Expand Down
5 changes: 3 additions & 2 deletions src/components/app/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,17 @@ ion-tabs {
}

ion-tab {
transform: translateY(-200%);
display: none;
}

ion-tab.show-tab {
transform: translateY(0);
display: block;
}

ion-app,
ion-nav,
ion-tab,
ion-tabs,
.app-root,
.ion-page {
contain: strict;
Expand Down
24 changes: 23 additions & 1 deletion src/components/content/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export class Content extends Ion {
_sbPadding: boolean;
_fullscreen: boolean;
_footerEle: HTMLElement;
_dirty: boolean = false;

/*
* @private
Expand Down Expand Up @@ -472,7 +473,6 @@ export class Content extends Ion {
/**
* Tell the content to recalculate its dimensions. This should be called
* after dynamically adding headers, footers, or tabs.
*
*/
resize() {
nativeRaf(() => {
Expand All @@ -486,6 +486,14 @@ export class Content extends Ion {
* DOM READ
*/
readDimensions() {
let cachePaddingTop = this._paddingTop;
let cachePaddingRight = this._paddingRight;
let cachePaddingBottom = this._paddingBottom;
let cachePaddingLeft = this._paddingLeft;
let cacheHeaderHeight = this._headerHeight;
let cacheFooterHeight = this._footerHeight;
let cacheTabsPlacement = this._tabsPlacement;

this._paddingTop = 0;
this._paddingRight = 0;
this._paddingBottom = 0;
Expand Down Expand Up @@ -542,13 +550,27 @@ export class Content extends Ion {

ele = ele.parentElement;
}

this._dirty = (
cachePaddingTop !== this._paddingTop ||
cachePaddingBottom !== this._paddingBottom ||
cachePaddingLeft !== this._paddingLeft ||
cachePaddingRight !== this._paddingRight ||
cacheHeaderHeight !== this._headerHeight ||
cacheFooterHeight !== this._footerHeight ||
cacheTabsPlacement !== this._tabsPlacement
);
}

/**
* @private
* DOM WRITE
*/
writeDimensions() {
if (!this._dirty) {
console.debug('Skipping writeDimenstions');
return;
}

let scrollEle = this._scrollEle as any;
if (!scrollEle) {
Expand Down
9 changes: 9 additions & 0 deletions src/components/tabs/tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Config } from '../../config/config';
import { DeepLinker } from '../../navigation/deep-linker';
import { GestureController } from '../../gestures/gesture-controller';
import { isTrueProperty } from '../../util/util';
import { nativeRaf } from '../../util/dom';
import { Keyboard } from '../../util/keyboard';
import { NavControllerBase } from '../../navigation/nav-controller-base';
import { NavOptions } from '../../navigation/nav-util';
Expand Down Expand Up @@ -303,10 +304,18 @@ export class Tab extends NavControllerBase {
*/
load(opts: NavOptions, done?: Function) {
if (!this._loaded && this.root) {
this.setElementClass('show-tab', true);
this.push(this.root, this.rootParams, opts, done);
this._loaded = true;

} else {
// if this is not the Tab's initial load then we need
// to refresh the tabbar and content dimensions to be sure
// they're lined up correctly
nativeRaf(() => {
var content = this.getActive().getIONContent();
content.resize();
});
done(true);
}
}
Expand Down
11 changes: 0 additions & 11 deletions src/components/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, Opti

import { App } from '../app/app';
import { Config } from '../../config/config';
import { Content } from '../content/content';
import { DeepLinker } from '../../navigation/deep-linker';
import { Ion } from '../ion';
import { isBlank } from '../../util/util';
Expand Down Expand Up @@ -422,16 +421,6 @@ export class Tabs extends Ion implements AfterViewInit {
if (this._selectHistory[this._selectHistory.length - 1] !== selectedTab.id) {
this._selectHistory.push(selectedTab.id);
}

// if this is not the Tab's initial load then we need
// to refresh the tabbar and content dimensions to be sure
// they're lined up correctly
if (alreadyLoaded && selectedPage) {
let content = <Content>selectedPage.getIONContent();
if (content) {
content.resize();
}
}
});
}

Expand Down
1 change: 1 addition & 0 deletions src/components/tabs/test/badges/app-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class E2EPage {}
`
ion-tabs {
margin-bottom: 20px;
contain: none;
}
`,
`
Expand Down
1 change: 1 addition & 0 deletions src/components/tabs/test/colors/app-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class E2EPage {}
`
ion-tabs {
margin-bottom: 20px;
contain: none;
}
`,

Expand Down
1 change: 1 addition & 0 deletions src/components/tabs/test/tab-bar-scenarios/app-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class E2EPage {}
`
ion-tabs {
margin-bottom: 20px;
contain: none;
}
`,
`
Expand Down
21 changes: 20 additions & 1 deletion src/components/tap-click/tap-click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ActivatorBase } from './activator-base';
import { Activator } from './activator';
import { App } from '../app/app';
import { Config } from '../../config/config';
import { assert } from '../../util/util';
import { assert, runInDev } from '../../util/util';
import { hasPointerMoved, pointerCoord } from '../../util/dom';
import { RippleActivator } from './ripple';
import { UIEventManager, PointerEvents, PointerEventType } from '../../util/ui-event-manager';
Expand All @@ -20,6 +20,7 @@ export class TapClick {
private startCoord: any;
private events: UIEventManager = new UIEventManager(false);
private pointerEvents: PointerEvents;
private lastTouchEnd: number;

constructor(
config: Config,
Expand Down Expand Up @@ -57,6 +58,8 @@ export class TapClick {
this.startCoord = null;
return false;
}

this.lastTouchEnd = 0;
this.startCoord = pointerCoord(ev);
this.activator && this.activator.downAction(ev, activatableEle, this.startCoord);
return true;
Expand All @@ -71,6 +74,8 @@ export class TapClick {
}

pointerEnd(ev: any, type: PointerEventType) {
runInDev(() => this.lastTouchEnd = Date.now());

if (!this.startCoord) {
return;
}
Expand Down Expand Up @@ -108,6 +113,7 @@ export class TapClick {
console.debug(`click prevent ${preventReason} ${Date.now()}`);
ev.preventDefault();
ev.stopPropagation();
return;

} else if (this.activator) {
// cool, a click is gonna happen, let's tell the activator
Expand All @@ -117,6 +123,19 @@ export class TapClick {
this.activator.clickAction(ev, activatableEle, this.startCoord);
}
}
runInDev(() => {
if (this.lastTouchEnd) {
let diff = Date.now() - this.lastTouchEnd;
if (diff < 100) {
console.debug(`FAST click dispatched. Delay(ms):`, diff);
} else {
console.warn(`SLOW click dispatched. Delay(ms):`, diff, ev);
}
this.lastTouchEnd = null;
} else {
console.debug('Click dispatched. Unknown delay');
}
});
}

handleTapPolyfill(ev: any) {
Expand Down
8 changes: 8 additions & 0 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ const ASSERT_ENABLED = true;
/**
* @private
*/

function _runInDev(fn: Function) {
if (ASSERT_ENABLED === true) {
return fn();
}
}

function _assert(actual: any, reason?: string) {
if (!actual && ASSERT_ENABLED === true) {
let message = 'IONIC ASSERT: ' + reason;
Expand All @@ -191,3 +198,4 @@ function _assert(actual: any, reason?: string) {
}

export { _assert as assert};
export { _runInDev as runInDev};

1 comment on commit 907191b

@elkhalifte
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

Please sign in to comment.