From bfab26d6815b36d9f17e209c441f0d2824667f99 Mon Sep 17 00:00:00 2001 From: zxcpoiu Date: Tue, 5 Jul 2016 18:06:30 +0800 Subject: [PATCH 1/2] ios: complete Vibration pattern supports in js --- Libraries/Vibration/Vibration.js | 60 ++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/Libraries/Vibration/Vibration.js b/Libraries/Vibration/Vibration.js index a60f75453928d3..e3d9e5a3959217 100644 --- a/Libraries/Vibration/Vibration.js +++ b/Libraries/Vibration/Vibration.js @@ -20,12 +20,59 @@ var Platform = require('Platform'); * * There will be no effect on devices that do not support Vibration, eg. the simulator. * - * Note for android + * **Note for android** * add `` to `AndroidManifest.xml` * - * Vibration patterns are currently unsupported. + * **Android Usage:** + * + * [0, 500, 200, 500] + * V(0.5s) --wait(0.2s)--> V(0.5s) + * + * [300, 500, 200, 500] + * --wait(0.3s)--> V(0.5s) --wait(0.2s)--> V(0.5s) + * + * **iOS Usage:** + * if first argument is 0, it will not be included in pattern array. + * + * [0, 1000, 2000, 3000] + * V(fixed) --wait(1s)--> V(fixed) --wait(2s)--> V(fixed) --wait(3s)--> V(fixed) */ +var _vibrating: boolean = false; +var _id: number = 0; // _id is necessary to prevent race condition. + +function vibrateByPattern(pattern: Array, repeat: boolean = false) { + if (_vibrating) { + return; + } + _vibrating = true; + if (pattern[0] === 0) { + RCTVibration.vibrate(); + pattern = pattern.slice(1); + } + if (pattern.length === 0) { + _vibrating = false; + return; + } + setTimeout(() => vibrateScheduler(++_id, pattern, repeat, 1), pattern[0]); +} + +function vibrateScheduler(id, pattern: Array, repeat: boolean, nextIndex: number) { + if (!_vibrating || id !== _id) { + return; + } + RCTVibration.vibrate(); + if (nextIndex >= pattern.length) { + if (repeat) { + nextIndex = 0; + } else { + _vibrating = false; + return; + } + } + setTimeout(() => vibrateScheduler(id, pattern, repeat, nextIndex+1), pattern[nextIndex]); +} + var Vibration = { vibrate: function(pattern: number | Array = 400, repeat: boolean = false) { if (Platform.OS === 'android') { @@ -37,10 +84,13 @@ var Vibration = { throw new Error('Vibration pattern should be a number or array'); } } else { + if (_vibrating) { + return; + } if (typeof pattern === 'number') { RCTVibration.vibrate(); } else if (Array.isArray(pattern)) { - console.warn('Vibration patterns are not supported on iOS'); + vibrateByPattern(pattern, repeat); } else { throw new Error('Vibration pattern should be a number or array'); } @@ -48,12 +98,10 @@ var Vibration = { }, /** * Stop vibration - * - * @platform android */ cancel: function() { if (Platform.OS === 'ios') { - console.warn('Vibration.cancel is not supported on iOS'); + _vibrating = false; } else { RCTVibration.cancel(); } From 6fb623b25877f324f65367a8e898d3b08e6e58b1 Mon Sep 17 00:00:00 2001 From: zxcpoiu Date: Tue, 5 Jul 2016 18:08:15 +0800 Subject: [PATCH 2/2] ios: Vibration example in UIExplorer --- Examples/UIExplorer/js/VibrationExample.js | 41 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Examples/UIExplorer/js/VibrationExample.js b/Examples/UIExplorer/js/VibrationExample.js index 554ae2f1f5514d..00e8cbd97bc4e0 100644 --- a/Examples/UIExplorer/js/VibrationExample.js +++ b/Examples/UIExplorer/js/VibrationExample.js @@ -30,12 +30,45 @@ var { Text, TouchableHighlight, Vibration, + Platform, } = ReactNative; exports.framework = 'React'; exports.title = 'Vibration'; exports.description = 'Vibration API'; + +var pattern, patternLiteral, patternDescription; +if (Platform.OS === 'android') { + pattern = [0, 500, 200, 500]; + patternLiteral = '[0, 500, 200, 500]'; + patternDescription = `${patternLiteral} +arg 0: duration to wait before turning the vibrator on. +arg with odd: vibration length. +arg with even: duration to wait before next vibration. +`; +} else { + pattern = [0, 1000, 2000, 3000]; + patternLiteral = '[0, 1000, 2000, 3000]'; + patternDescription = `${patternLiteral} +vibration length on iOS is fixed. +pattern controls durations BETWEEN each vibration only. + +arg 0: duration to wait before turning the vibrator on. +subsequent args: duration to wait before next vibrattion. +`; +} + exports.examples = [ + { + title: 'Pattern Descriptions', + render() { + return ( + + {patternDescription} + + ); + }, + }, { title: 'Vibration.vibrate()', render() { @@ -51,12 +84,12 @@ exports.examples = [ }, }, { - title: 'Vibration.vibrate([0, 500, 200, 500])', + title: `Vibration.vibrate(${patternLiteral})`, render() { return ( Vibration.vibrate([0, 500, 200, 500])}> + onPress={() => Vibration.vibrate(pattern)}> Vibrate once @@ -65,12 +98,12 @@ exports.examples = [ }, }, { - title: 'Vibration.vibrate([0, 500, 200, 500], true)', + title: `Vibration.vibrate(${patternLiteral}, true)`, render() { return ( Vibration.vibrate([0, 500, 200, 500], true)}> + onPress={() => Vibration.vibrate(pattern, true)}> Vibrate until cancel