Repository: cordova-plugin-vibration Updated Branches: refs/heads/master 107ba2bcd -> c5e7221e2
CB-9365 Add support for 'vibrateWithPattern' to Windows Phone 8.1 / Windows 10 Added manual test for `repeat` Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/commit/c5e7221e Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/tree/c5e7221e Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/diff/c5e7221e Branch: refs/heads/master Commit: c5e7221e238ad2c78842ce973ba9c66be2dd16e1 Parents: 107ba2b Author: daserge <[email protected]> Authored: Tue Dec 15 14:59:49 2015 +0300 Committer: daserge <[email protected]> Committed: Tue Dec 15 14:59:49 2015 +0300 ---------------------------------------------------------------------- README.md | 4 - src/windows/VibrationProxy.js | 151 ++++++++++++++++++++++++++++++++++--- tests/tests.js | 14 ++++ 3 files changed, 153 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/blob/c5e7221e/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index b7117e5..38a3742 100644 --- a/README.md +++ b/README.md @@ -111,10 +111,6 @@ Vibrates the device with a given pattern - vibrate(pattern) falls back on vibrate with default duration -####Windows Quirks - -- vibrate(pattern) falls back on vibrate with default duration - ###Cancel vibration (not supported in iOS) Immediately cancels any currently running vibration. http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/blob/c5e7221e/src/windows/VibrationProxy.js ---------------------------------------------------------------------- diff --git a/src/windows/VibrationProxy.js b/src/windows/VibrationProxy.js index 3fb954b..0c01eb1 100644 --- a/src/windows/VibrationProxy.js +++ b/src/windows/VibrationProxy.js @@ -41,7 +41,117 @@ function tryDoAction(actionName, success, fail, args, action) { } } +/** + * @typedef patternParsingResult + * @type {Object} + * @property {Array} result.parsed - Array with parsed integers + * @property {Boolean} result.passed - false in case of parsing error + * @property {*} result.failedItem - The item, which could not be parsed + */ + +/** + * Tries to convert pattern values to int + * @param {Array} pattern Array of delays + * @returns {patternParsingResult} result + */ +function tryParsePatternValues(pattern) { + var passed = true, failedItem; + + pattern = pattern.map(function (item) { + var num = parseInt(item, 10); + if (isNaN(num)) { + failedItem = item; + passed = false; + } + + return num; + }); + + return { + parsed: pattern, + passed: passed, + failedItem: failedItem + }; +} + +/** + * @typedef checkPatternReqsResult + * @type {Object} + * @property {Array} result.patternParsingResult - Array with parsed integers + * @property {Boolean} result.passed - true if all params are OK + */ + +/** + * Checks params for vibrateWithPattern function + * @return {checkPatternReqsResult} + */ +function checkPatternReqs(args, fail) { + var patternParsingResult = tryParsePatternValues(args[0]); + var repeat = args[1]; + var passed = true, errMsg = ''; + + if (!patternParsingResult.passed) { + errMsg += 'Could not parse ' + patternParsingResult.failedItem + ' in the vibration pattern'; + passed = false; + } + + if (repeat !== -1 && (repeat < 0 || repeat > args[0].length - 1)) { + errMsg += '\nrepeat parameter is out of range: ' + repeat; + passed = false; + } + + if (!passed) { + console.error(errMsg); + fail && fail(errMsg); + } + + return { + passed: passed, + patternParsingResult: patternParsingResult + }; +} + +/** + * vibrateWithPattern with `repeat` support + * @param {Array} patternArr Full pattern array + * @param {Boolean} shouldRepeat Indication on whether the vibration should be cycled + * @param {Function} fail Fail callback + * @param {Array} patternCycle Cycled part of the pattern array + * @return {Promise} Promise chaining single vibrate/pause actions + */ +function vibratePattern(patternArr, shouldRepeat, fail, patternCycle) { + return patternArr.reduce(function (previousValue, currentValue, index) { + if (index % 2 === 0) { + return previousValue.then(function () { + module.exports.vibrate(function () { }, function (err) { + console.error(err); + fail && fail(err); + }, [currentValue]); + + if (index === patternArr.length - 1 && shouldRepeat) { + return WinJS.Promise.timeout(currentValue).then(function () { + return vibratePattern(patternCycle, true, fail, patternCycle); + }); + } else { + return WinJS.Promise.timeout(currentValue); + } + }); + } else { + return previousValue.then(function () { + if (index === patternArr.length - 1 && shouldRepeat) { + return WinJS.Promise.timeout(currentValue).then(function () { + return vibratePattern(patternCycle, true, fail, patternCycle); + }); + } else { + return WinJS.Promise.timeout(currentValue); + } + }); + } + }, WinJS.Promise.as()); +} + var DEFAULT_DURATION = 200; +var patternChainPromise; var VibrationDevice = (Windows.Phone && Windows.Phone.Devices && Windows.Phone.Devices.Notification && Windows.Phone.Devices.Notification.VibrationDevice && Windows.Phone.Devices.Notification.VibrationDevice); if (VibrationDevice) { @@ -60,17 +170,34 @@ if (VibrationDevice) { fail(e); } }, - vibrateWithPattern: function(success, fail, args) { - // TODO: Implement with setTimeout. - fail('"vibrateWithPattern" is unsupported by this platform.'); + vibrateWithPattern: function (success, fail, args) { + // Cancel current vibrations first + module.exports.cancelVibration(function () { + var checkReqsResult = checkPatternReqs(args, fail); + if (!checkReqsResult.passed) { + return; + } + + var pattern = checkReqsResult.patternParsingResult.parsed; + var repeatFromIndex = args[1]; + var shouldRepeat = (repeatFromIndex !== -1); + var patternCycle; + + if (shouldRepeat) { + patternCycle = pattern.slice(repeatFromIndex); + } + + patternChainPromise = vibratePattern(pattern, shouldRepeat, fail, patternCycle); + }, fail); }, cancelVibration: function(success, fail, args) { try { + patternChainPromise && patternChainPromise.cancel(); VibrationDevice.getDefault().cancel(); - success(); + success && success(); } catch (e) { - fail(e); + fail && fail(e); } } }; @@ -85,24 +212,24 @@ if (VibrationDevice) { tryDoAction("vibrate", success, fail, [DEFAULT_DURATION], Vibration.Vibration.vibrate); }, - cancelVibration: function(success, fail, args) { + cancelVibration: function (success, fail, args) { tryDoAction("cancelVibration", success, fail, args, Vibration.Vibration.cancelVibration); } }; } else { // code paths where no vibration mechanism is present module.exports = { - vibrate: function (a, fail) { - fail('"vibrate" is unsupported by this device.'); + vibrate: function (success, fail) { + fail && fail('"vibrate" is unsupported by this device.'); }, vibrateWithPattern: function (success, fail, args) { - fail('"vibrateWithPattern" is unsupported by this device.'); + fail && fail('"vibrateWithPattern" is unsupported by this device.'); }, - cancelVibration: function(success, fail, args) { - success(); + cancelVibration: function (success, fail, args) { + success && success(); } - } + }; } require("cordova/exec/proxy").add("Vibration", module.exports); http://git-wip-us.apache.org/repos/asf/cordova-plugin-vibration/blob/c5e7221e/tests/tests.js ---------------------------------------------------------------------- diff --git a/tests/tests.js b/tests/tests.js index 79aff30..88dbc45 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -67,6 +67,13 @@ exports.defineManualTests = function (contentEl, createActionButton) { logMessage("navigator.notification.vibrateWithPattern([1000, 3000, 2000, 5000])", "green"); }; + //old vibrate with pattern with repeat call + var vibrateWithPatternOldWithRepeat = function(){ + clearLog(); + navigator.notification.vibrateWithPattern([1000, 3000, 2000, 5000], 2); + logMessage("navigator.notification.vibrateWithPattern([1000, 3000, 2000, 5000], 2)", "green"); + }; + //old cancel vibrate call var cancelOld = function(){ clearLog(); @@ -157,6 +164,8 @@ exports.defineManualTests = function (contentEl, createActionButton) { 'Expected result: Vibrate once for 2.5 seconds.' + '<p/> <div id="vibrateWithPattern_old"></div>' + 'Expected result: Pause for 1s, vibrate for 3s, pause for 2s, vibrate for 5s.' + + '<p/> <div id="vibrateWithPatternRepeat_old"></div>' + + 'Expected result: Pause for 1s, vibrate for 3s, [pause for 2s, vibrate for 5s.], repeat [steps]' + '<p/> <div id="cancelVibrate_old"></div>' + 'Expected result: Press once to initiate vibrate for 60 seconds. Press again to cancel vibrate immediately.' + '<p/> <div id="cancelVibrateWithPattern_old"></div>' + @@ -191,6 +200,11 @@ exports.defineManualTests = function (contentEl, createActionButton) { vibrateWithPatternOld(); }, 'vibrateWithPattern_old'); + //vibrate with pattern with repeat with old call + createActionButton('* Vibrate with a pattern with repeat (Old)', function () { + vibrateWithPatternOldWithRepeat(); + }, 'vibrateWithPatternRepeat_old'); + //cancel vibrate with old call createActionButton('* Cancel vibration (Old)', function() { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
