UNPKG

@8man/react-native-media-console

Version:
443 lines (432 loc) 15.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _reactNative = require("react-native"); var _react = _interopRequireWildcard(require("react")); var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated")); var _MaterialIcons = _interopRequireDefault(require("@expo/vector-icons/MaterialIcons")); var _reactNativeSystemSetting = _interopRequireDefault(require("react-native-system-setting")); var _reactNativeGestureHandler = require("react-native-gesture-handler"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } //@ts-ignore const SWIPE_RANGE = 370; const Ripple = ({ visible, isLeft, totalTime, showControls }) => { const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = _reactNative.Dimensions.get('window'); const scale = (0, _reactNativeReanimated.useSharedValue)(0); const opacity = (0, _reactNativeReanimated.useSharedValue)(0); _react.default.useEffect(() => { if (visible) { scale.value = (0, _reactNativeReanimated.withSequence)((0, _reactNativeReanimated.withTiming)(1.5, { duration: 400 }), (0, _reactNativeReanimated.withDelay)(400, (0, _reactNativeReanimated.withTiming)(0, { duration: 400 }))); opacity.value = (0, _reactNativeReanimated.withSequence)((0, _reactNativeReanimated.withTiming)(0.4, { duration: 400 }), (0, _reactNativeReanimated.withDelay)(400, (0, _reactNativeReanimated.withTiming)(0, { duration: 400 }))); } }, [visible]); const rippleStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({ opacity: opacity.value, //@ts-ignore transform: [{ scale: scale.value }] })); return visible ? /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { position: 'absolute', top: showControls ? -70 : -45, left: isLeft ? '-10%' : undefined, right: isLeft ? undefined : '-10%', width: SCREEN_WIDTH / 2.5, height: SCREEN_HEIGHT, zIndex: 999 } }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [{ position: 'absolute', width: '100%', height: '100%', backgroundColor: 'rgba(0,0,0,0.9)', justifyContent: 'center', alignItems: 'center', borderRadius: SCREEN_HEIGHT / 2 }, rippleStyle] }, /*#__PURE__*/_react.default.createElement(_MaterialIcons.default, { name: isLeft ? 'fast-rewind' : 'fast-forward', size: 28, color: "white" }), !isNaN(totalTime) && totalTime > 0 && /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: { color: 'white', marginTop: 8, fontSize: 12 } }, Math.floor(totalTime), "s"))) : null; }; const Gestures = ({ forward, rewind, togglePlayPause, toggleControls, doubleTapTime, tapActionTimeout, tapAnywhereToPause, rewindTime = 10, showControls, disableGesture }) => { const [rippleVisible, setRippleVisible] = (0, _react.useState)(false); // const [ripplePosition,setRipplePosition] = useState({x: 0, y: 0}); const [isLeftRipple, setIsLeftRipple] = (0, _react.useState)(false); const [totalSkipTime, setTotalSkipTime] = (0, _react.useState)(0); const initialTapPosition = (0, _react.useRef)({ x: 0, y: 0 }); const isDoubleTapRef = (0, _react.useRef)(false); const currentSideRef = (0, _react.useRef)(null); const tapCountRef = (0, _react.useRef)(0); const skipTimeoutRef = (0, _react.useRef)(null); const lastTapTimeRef = (0, _react.useRef)(0); const { width: SCREEN_WIDTH } = _reactNative.Dimensions.get('window'); const resetState = () => { isDoubleTapRef.current = false; currentSideRef.current = null; tapCountRef.current = 0; lastTapTimeRef.current = 0; setTotalSkipTime(0); setRippleVisible(false); if (skipTimeoutRef.current) { clearTimeout(skipTimeoutRef.current); skipTimeoutRef.current = null; } }; const handleSkip = async () => { try { const count = Number(tapCountRef.current) - 1; const baseTime = Number(rewindTime); const skipTime = baseTime * count; console.log('Skip calculation:', { count, baseTime, skipTime, side: currentSideRef.current, isValidNumber: !isNaN(skipTime) && skipTime > 0 }); if (!isNaN(skipTime) && skipTime > 0) { if (currentSideRef.current === 'left') { rewind(skipTime); } else if (currentSideRef.current === 'right') { forward(skipTime); } } } catch (error) { console.error('Error while skipping:', error); } finally { resetState(); } }; const handleTap = (e, side) => { const now = Date.now(); const touchX = e.nativeEvent.locationX; const touchY = e.nativeEvent.locationY; console.log('Tap details:', { touchX, side, isDoubleTap: isDoubleTapRef.current, timeSinceLastTap: now - lastTapTimeRef.current }); if (now - lastTapTimeRef.current > 500) { resetState(); } if (!isDoubleTapRef.current) { isDoubleTapRef.current = true; initialTapPosition.current = { x: touchX, y: touchY }; currentSideRef.current = side; tapCountRef.current = 1; lastTapTimeRef.current = now; tapActionTimeout.current = setTimeout(() => { if (tapAnywhereToPause) { togglePlayPause(); } else { toggleControls(); } resetState(); }, doubleTapTime); } else { if (tapActionTimeout.current) { clearTimeout(tapActionTimeout.current); tapActionTimeout.current = null; } if (currentSideRef.current === side) { tapCountRef.current += 1; lastTapTimeRef.current = now; const count = Number(tapCountRef.current) - 1; const baseTime = Number(rewindTime); const newSkipTime = baseTime * count; console.log('Multiple tap calculation:', { count, baseTime, newSkipTime, tapCount: tapCountRef.current, side }); setTotalSkipTime(newSkipTime); setRippleVisible(true); // setRipplePosition(initialTapPosition.current); setIsLeftRipple(side === 'left'); if (skipTimeoutRef.current) { clearTimeout(skipTimeoutRef.current); } skipTimeoutRef.current = setTimeout(handleSkip, 500); } else { resetState(); isDoubleTapRef.current = true; initialTapPosition.current = { x: touchX, y: touchY }; currentSideRef.current = side; tapCountRef.current = 1; lastTapTimeRef.current = now; tapActionTimeout.current = setTimeout(() => { resetState(); }, doubleTapTime); } } }; _react.default.useEffect(() => { return () => { if (skipTimeoutRef.current) { clearTimeout(skipTimeoutRef.current); } if (tapActionTimeout.current) { clearTimeout(tapActionTimeout.current); } }; }, []); const volumeValue = (0, _reactNativeReanimated.useSharedValue)(0); const brightnessValue = (0, _reactNativeReanimated.useSharedValue)(0); const startVolume = (0, _reactNativeReanimated.useSharedValue)(0); const startBrightness = (0, _reactNativeReanimated.useSharedValue)(0); const [displayVolume, setDisplayVolume] = (0, _react.useState)(0); const [displayBrightness, setDisplayBrightness] = (0, _react.useState)(0); const [isVolumeVisible, setIsVolumeVisible] = (0, _react.useState)(false); const [isBrightnessVisible, setIsBrightnessVisible] = (0, _react.useState)(false); // Store original values in refs to maintain latest values for cleanup const originalSettings = (0, _react.useRef)({ volume: 0, brightness: 0 }); _react.default.useEffect(() => { const initializeSettings = async () => { try { const currentVolume = await _reactNativeSystemSetting.default.getVolume(); const currentBrightness = await _reactNativeSystemSetting.default.getBrightness(); volumeValue.value = currentVolume; brightnessValue.value = currentBrightness; setDisplayVolume(currentVolume); setDisplayBrightness(currentBrightness); } catch (error) { console.error('Error initializing settings:', error); } }; initializeSettings(); }, []); const updateSystemVolume = _react.default.useCallback(newVolume => { const clampedVolume = Math.max(0, Math.min(1, newVolume)); _reactNativeSystemSetting.default.setVolume(clampedVolume); setDisplayVolume(clampedVolume); }, []); const updateSystemBrightness = _react.default.useCallback(newBrightness => { const clampedBrightness = Math.max(0, Math.min(1, newBrightness)); _reactNativeSystemSetting.default.setAppBrightness(clampedBrightness); setDisplayBrightness(clampedBrightness); }, []); const panGesture = _reactNativeGestureHandler.Gesture.Pan().minDistance(10) // Minimum distance before gesture starts .onStart(event => { 'worklet'; const isLeftSide = event.x < SCREEN_WIDTH / 2; if (isLeftSide) { startBrightness.value = brightnessValue.value; (0, _reactNativeReanimated.runOnJS)(setIsBrightnessVisible)(true); } else { startVolume.value = volumeValue.value; (0, _reactNativeReanimated.runOnJS)(setIsVolumeVisible)(true); } }).onUpdate(event => { 'worklet'; const isLeftSide = event.x < SCREEN_WIDTH / 2; const change = -event.translationY / SWIPE_RANGE; if (isLeftSide) { // Brightness control const newBrightness = Math.max(0, Math.min(1, startBrightness.value + change)); brightnessValue.value = newBrightness; (0, _reactNativeReanimated.runOnJS)(updateSystemBrightness)(newBrightness); } else { // Volume control const newVolume = Math.max(0, Math.min(1, startVolume.value + change)); volumeValue.value = newVolume; (0, _reactNativeReanimated.runOnJS)(updateSystemVolume)(newVolume); } }).onFinalize(() => { 'worklet'; (0, _reactNativeReanimated.runOnJS)(setIsVolumeVisible)(false); (0, _reactNativeReanimated.runOnJS)(setIsBrightnessVisible)(false); }); const ControlOverlay = /*#__PURE__*/_react.default.memo(({ value, isVisible, isVolume }) => { if (!isVisible) return null; return /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { // @ts-ignore style: { position: 'absolute', top: '50%', left: !isVolume ? undefined : '15%', right: !isVolume ? '15%' : undefined, transform: [{ translateX: 0 }, { translateY: showControls ? -20 : 0 }], backgroundColor: 'rgba(0, 0, 0, 0.6)', borderRadius: 10, minWidth: 50, padding: 10, alignItems: 'center', zIndex: 1000 } }, /*#__PURE__*/_react.default.createElement(_MaterialIcons.default, { name: isVolume ? value === 0 ? 'volume-mute' : value < 0.3 ? 'volume-down' : 'volume-up' : 'brightness-6', size: 24, color: "white" }), /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: { color: 'white', marginTop: 5 } }, Math.round(value * 100))); }); // Initialize and store original settings (0, _react.useEffect)(() => { let mounted = true; const initializeSettings = async () => { try { const [currentVolume, currentBrightness] = await Promise.all([_reactNativeSystemSetting.default.getVolume(), _reactNativeSystemSetting.default.getBrightness()]); if (mounted) { // Store original values originalSettings.current = { volume: currentVolume, brightness: currentBrightness }; // Set initial values volumeValue.value = currentVolume; brightnessValue.value = currentBrightness; setDisplayVolume(currentVolume); setDisplayBrightness(currentBrightness); console.log('Original settings stored:🔥', { volume: currentVolume, brightness: currentBrightness }); } } catch (error) { console.error('Error initializing settings:', error); } }; initializeSettings(); // Cleanup function return () => { mounted = false; const resetSettings = async () => { try { // console.log('Resetting to original settings:🔥', originalSettings.current); await Promise.all([ // SystemSetting.setVolume(originalSettings.current.volume), _reactNativeSystemSetting.default.setAppBrightness(originalSettings.current.brightness)]); // console.log('Settings reset successfully'); } catch (error) { console.error('Error resetting settings:', error); } }; resetSettings(); }; }, []); if (disableGesture) { return null; } return /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.GestureHandlerRootView, { style: { width: '100%', height: '70%' } }, /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.GestureDetector, { gesture: panGesture }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { position: 'relative', width: '100%', height: '100%', flexDirection: 'row' } }, /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, { onPress: e => handleTap(e, 'left'), style: { flex: 1, top: 40, height: '100%', position: 'relative' } }, /*#__PURE__*/_react.default.createElement(Ripple, { visible: rippleVisible && isLeftRipple, showControls: showControls, isLeft: true, totalTime: totalSkipTime })), /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, { onPress: e => handleTap(e, 'right'), style: { top: 40, flex: 1, height: '100%', position: 'relative' } }, /*#__PURE__*/_react.default.createElement(Ripple, { visible: rippleVisible && !isLeftRipple, showControls: showControls, isLeft: false, totalTime: totalSkipTime })))), /*#__PURE__*/_react.default.createElement(ControlOverlay, { value: displayVolume, isVisible: isVolumeVisible, isVolume: true }), /*#__PURE__*/_react.default.createElement(ControlOverlay, { value: displayBrightness, isVisible: isBrightnessVisible, isVolume: false })); }; var _default = exports.default = Gestures; //# sourceMappingURL=Gestures.js.map