/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @flow strict * @jsdoc */ import NativeVibration from './NativeVibration'; const Platform = require('../Utilities/Platform'); /** * Vibration API * * See https://reactnative.dev/docs/vibration */ let _vibrating: boolean = false; let _id: number = 0; // _id is necessary to prevent race condition. const _default_vibration_length = 400; function vibrateByPattern(pattern: Array, repeat: boolean = false) { if (_vibrating) { return; } _vibrating = true; if (pattern[0] === 0) { NativeVibration.vibrate(_default_vibration_length); // $FlowFixMe[reassign-const] pattern = pattern.slice(1); } if (pattern.length === 0) { _vibrating = false; return; } setTimeout(() => vibrateScheduler(++_id, pattern, repeat, 1), pattern[0]); } function vibrateScheduler( id: number, pattern: Array, repeat: boolean, nextIndex: number, ) { if (!_vibrating || id !== _id) { return; } NativeVibration.vibrate(_default_vibration_length); if (nextIndex >= pattern.length) { if (repeat) { // $FlowFixMe[reassign-const] nextIndex = 0; } else { _vibrating = false; return; } } setTimeout( () => vibrateScheduler(id, pattern, repeat, nextIndex + 1), pattern[nextIndex], ); } const Vibration = { /** * Trigger a vibration with specified `pattern`. * * See https://reactnative.dev/docs/vibration#vibrate */ vibrate: function ( pattern: number | Array = _default_vibration_length, repeat: boolean = false, ) { if (Platform.OS === 'android') { if (typeof pattern === 'number') { NativeVibration.vibrate(pattern); } else if (Array.isArray(pattern)) { NativeVibration.vibrateByPattern(pattern, repeat ? 0 : -1); } else { throw new Error('Vibration pattern should be a number or array'); } } else { if (_vibrating) { return; } if (typeof pattern === 'number') { NativeVibration.vibrate(pattern); } else if (Array.isArray(pattern)) { vibrateByPattern(pattern, repeat); } else { throw new Error('Vibration pattern should be a number or array'); } } }, /** * Stop vibration * * See https://reactnative.dev/docs/vibration#cancel */ cancel: function () { if (Platform.OS === 'ios') { _vibrating = false; } else { NativeVibration.cancel(); } }, }; module.exports = Vibration;