diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-06-06 19:02:04 +0300 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-06-08 22:39:19 +0300 |
| commit | 891eb4cab0732b325a27dc104d942a052c82a930 (patch) | |
| tree | db541fc036c8309efd79d2f1a86675a482ad45aa /app/lib | |
| parent | 3f9e67cf0e1793d404b29b85ceaa49c281aba591 (diff) | |
| download | mullvadvpn-891eb4cab0732b325a27dc104d942a052c82a930.tar.xz mullvadvpn-891eb4cab0732b325a27dc104d942a052c82a930.zip | |
Add flow annotations for KeyframeAnimation and relevant Electron types
Diffstat (limited to 'app/lib')
| -rw-r--r-- | app/lib/keyframe-animation.js | 189 | ||||
| -rw-r--r-- | app/lib/tray-icon-manager.js | 4 |
2 files changed, 121 insertions, 72 deletions
diff --git a/app/lib/keyframe-animation.js b/app/lib/keyframe-animation.js index 10b087e109..4890d06a0e 100644 --- a/app/lib/keyframe-animation.js +++ b/app/lib/keyframe-animation.js @@ -1,5 +1,16 @@ +// @flow import assert from 'assert'; import { nativeImage } from 'electron'; +import type { NativeImage } from 'electron'; + +export type OnFrameFn = (image: NativeImage) => void; +export type OnFinishFn = (void) => void; +export type KeyframeAnimationOptions = { + startFrame?: number, + endFrame?: number, + beginFromCurrentState?: boolean, + advanceTo?: 'end' +}; /** * Keyframe animation @@ -9,13 +20,32 @@ import { nativeImage } from 'electron'; */ export default class KeyframeAnimation { + _speed: number = 200; // ms + _repeat: boolean = false; + _reverse: boolean = false; + _alternate: boolean = false; + + _onFrame: ?OnFrameFn; + _onFinish: ?OnFinishFn; + + _nativeImages: Array<NativeImage>; + _frameRange: Array<number>; + _numFrames: number; + _currentFrame: number = 0; + + _isRunning: boolean = false; + _isFinished: boolean = false; + _isFirstRun: boolean = true; + + _timeout = null; + /** * Set callback called on each frame update * * @type {function} * @memberOf KeyframeAnimation */ - set onFrame(v) { this._onFrame = v; } + set onFrame(newValue: ?OnFrameFn) { this._onFrame = newValue; } /** * Get callback called on each frame update @@ -24,7 +54,7 @@ export default class KeyframeAnimation { * @type {function} * @memberOf KeyframeAnimation */ - get onFrame() { this._onFrame; } + get onFrame(): ?OnFrameFn { this._onFrame; } /** * Set callback called when animation finished @@ -32,7 +62,7 @@ export default class KeyframeAnimation { * @type {function} * @memberOf KeyframeAnimation */ - set onFinish(v) { this._onFinish = v; } + set onFinish(newValue: ?OnFinishFn) { this._onFinish = newValue; } /** * Get callback called when animation finished @@ -41,7 +71,7 @@ export default class KeyframeAnimation { * * @memberOf KeyframeAnimation */ - get onFinish() { this._onFinish; } + get onFinish(): ?OnFinishFn { this._onFinish; } /** * Set animation pace per frame in ms @@ -49,7 +79,7 @@ export default class KeyframeAnimation { * @type {number} * @memberOf KeyframeAnimation */ - set speed(v) { this._speed = parseInt(v); } + set speed(newValue: number) { this._speed = parseInt(newValue); } /** * Get animation pace per frame in ms @@ -58,7 +88,7 @@ export default class KeyframeAnimation { * @type {number} * @memberOf KeyframeAnimation */ - get speed() { return this._speed; } + get speed(): number { return this._speed; } /** * Set animation repetition @@ -66,7 +96,7 @@ export default class KeyframeAnimation { * * @memberOf KeyframeAnimation */ - set repeat(v) { this._repeat = !!v; } + set repeat(newValue: boolean) { this._repeat = !!newValue; } /** * Get animation repetition @@ -75,14 +105,14 @@ export default class KeyframeAnimation { * @type {bool} * @memberOf KeyframeAnimation */ - get repeat() { return this._repeat; } + get repeat(): boolean { return this._repeat; } /** * Set animation reversal * @type {bool} * @memberOf KeyframeAnimation */ - set reverse(v) { this._reverse = !!v; } + set reverse(newValue: boolean) { this._reverse = !!newValue; } /** * Get animation reversal @@ -91,14 +121,14 @@ export default class KeyframeAnimation { * @type {bool} * @memberOf KeyframeAnimation */ - get reverse() { return this._repeat; } + get reverse(): boolean { return this._repeat; } /** * Set animation alternation * @type {bool} * @memberOf KeyframeAnimation */ - set alternate(v) { this._alternate = !!v; } + set alternate(newValue: boolean) { this._alternate = !!newValue; } /** * Get animation alternation @@ -107,25 +137,16 @@ export default class KeyframeAnimation { * @type {bool} * @memberOf KeyframeAnimation */ - get alternate() { return this._alternate; } - - /** - * Source array of images - * - * @readonly - * @type {array} - * @memberOf KeyframeAnimation - */ - get source() { return this._source.slice(); } + get alternate(): boolean { return this._alternate; } /** * Array of NativeImage instances loaded based on source input * * @readonly - * @type {Electron.NativeImage[]} + * @type {Array<NativeImage>} * @memberOf KeyframeAnimation */ - get nativeImages() { return this._nativeImages.slice(); } + get nativeImages(): Array<NativeImage> { return this._nativeImages.slice(); } /** * Flag that tells whether animation finished @@ -134,83 +155,81 @@ export default class KeyframeAnimation { * @type {bool} * @memberOf KeyframeAnimation */ - get isFinished() { return this._isFinished; } + get isFinished(): boolean { return this._isFinished; } /** - * Create animation using file sequence + * Create animation from files matching filename pattern * * @static - * @param {string} filePattern - file name pattern where {s} is replaced with index - * @param {number[]} range - sequence range [start, end] + * @param {string} filePattern - file name pattern where {} is replaced with index + * @param {Array<number>} range - sequence range [start, end] * * @memberOf KeyframeAnimation * @return {KeyframeAnimation} */ - static fromFileSequence(filePattern, range) { + static fromFilePattern(filePattern: string, range: Array<number>): KeyframeAnimation { assert(range.length === 2 && range[0] < range[1], 'the animation range is invalid'); - - let images = []; + const images: Array<NativeImage> = []; for(let i = range[0]; i <= range[1]; i++) { - images.push(filePattern.replace('{s}', i)); + const filePath = filePattern.replace('{}', i.toString()); + const image = nativeImage.createFromPath(filePath); + images.push(image); } + return new KeyframeAnimation(images); + } + /** + * Create animation from file sequence + * + * @static + * @param {Array<string>} files - file paths + * @returns {KeyframeAnimation} + * + * @memberof KeyframeAnimation + */ + static fromFileSequence(files: Array<string>): KeyframeAnimation { + const images: Array<NativeImage> = files.map(filePath => nativeImage.createFromPath(filePath)); return new KeyframeAnimation(images); } /** - * Creates an instance of KeyframeAnimation. - * @param {string[]} images + * Create an instance of KeyframeAnimation + * @param {Array<NativeImage>} images - an array of instances of NativeImage * * @memberOf KeyframeAnimation */ - constructor(images) { - assert(images.length > 0, 'too few images in animation'); - - this._source = images.slice(); - this._nativeImages = images.map((pathOrNativeImage) => { - if(typeof(pathOrNativeImage) === 'string') { - return nativeImage.createFromPath(pathOrNativeImage); - } else if((pathOrNativeImage + '') === '[object NativeImage]') { - return pathOrNativeImage; - } - return nativeImage.createEmpty(); - }); - - this._speed = 200; // ms - this._repeat = false; - this._reverse = false; - this._alternate = false; + constructor(images: Array<NativeImage>) { + const len = images.length; - this._numFrames = images.length; - this._currentFrame = 0; - this._frameRange = [0, this._numFrames]; - this._isRunning = false; - this._isFinished = false; + assert(len > 0, 'too few images in animation'); - this._isFirstRun = true; + this._nativeImages = images.slice(); + this._numFrames = len; + this._frameRange = [0, len]; } /** * Get current sprite * * @readonly - * @type {Electron.NativeImage} + * @type {NativeImage} * @memberOf KeyframeAnimation */ - get currentImage() { + get currentImage(): NativeImage { return this._nativeImages[this._currentFrame]; } /** - * Prepare initial state for animation before running it. - * @param {object} [options = {}] - animation options - * @param {number} [options.startFrame] - start frame - * @param {number} [options.endFrame] - end frame - * @param {bool} [options.beginFromCurrentState] - continue animation from current state - * @param {string} [options.advanceTo] - resets current frame. (possible values: end) + * Start animation + * + * @param {object} [options = {}] - animation options + * @param {number} [options.startFrame] - start frame + * @param {number} [options.endFrame] - end frame + * @param {bool} [options.beginFromCurrentState] - continue animation from current state + * @param {string} [options.advanceTo] - resets current frame. (possible values: end) * @memberOf KeyframeAnimation */ - play(options = {}) { + play(options: KeyframeAnimationOptions = {}) { let { startFrame, endFrame, beginFromCurrentState, advanceTo } = options; if(startFrame !== undefined && endFrame !== undefined) { @@ -256,6 +275,12 @@ export default class KeyframeAnimation { this._unscheduleUpdate(); } + /** + * Cancel timer for next animation frame + * + * @private + * @memberof KeyframeAnimation + */ _unscheduleUpdate() { if(this._timeout) { clearTimeout(this._timeout); @@ -263,16 +288,34 @@ export default class KeyframeAnimation { } } + /** + * Schedule timer for next animation frame + * + * @private + * @memberof KeyframeAnimation + */ _scheduleUpdate() { - this._timeout = setTimeout(::this._onUpdateFrame, this._speed); + this._timeout = setTimeout(() => this._onUpdateFrame(), this._speed); } + /** + * Call delegate to render frame + * + * @private + * @memberof KeyframeAnimation + */ _render() { if(this._onFrame) { this._onFrame(this._nativeImages[this._currentFrame]); } } + /** + * Mark animation finished and notify delegate. + * + * @private + * @memberof KeyframeAnimation + */ _didFinish() { this._isFinished = true; @@ -281,6 +324,12 @@ export default class KeyframeAnimation { } } + /** + * Animation frame lifecycle. + * + * @private + * @memberof KeyframeAnimation + */ _onUpdateFrame() { this._advanceFrame(); @@ -332,14 +381,14 @@ export default class KeyframeAnimation { /** * Calculate next frame * @private - * @param {number} cur - current frame - * @param {number[]} frameRange - frame range - * @param {bool} isReverse - reverse sequence direction? + * @param {number} cur - current frame + * @param {Array<number>} frameRange - frame range + * @param {bool} isReverse - reverse sequence direction? * @returns {number} * * @memberOf KeyframeAnimation */ - _nextFrame(cur, frameRange, isReverse) { + _nextFrame(cur: number, frameRange: Array<number>, isReverse: boolean): number { if(isReverse) { if(cur < frameRange[0]) { return cur + 1; diff --git a/app/lib/tray-icon-manager.js b/app/lib/tray-icon-manager.js index 8898f7bc48..eb242deb6b 100644 --- a/app/lib/tray-icon-manager.js +++ b/app/lib/tray-icon-manager.js @@ -21,8 +21,8 @@ export default class TrayIconManager { assert(tray, 'Tray icon cannot be null'); const basePath = path.join(path.resolve(__dirname, '..'), 'assets/images/menubar icons'); - let filePath = path.join(basePath, 'lock-{s}.png'); - let animation = KeyframeAnimation.fromFileSequence(filePath, [1, 9]); + let filePath = path.join(basePath, 'lock-{}.png'); + let animation = KeyframeAnimation.fromFilePattern(filePath, [1, 9]); animation.onFrame = (img) => tray.setImage(img); animation.speed = 100; |
