From 11c503cf710f44fcfcbbb466a57e350c2826b321 Mon Sep 17 00:00:00 2001 From: chrisk325 Date: Sun, 22 Mar 2026 15:46:56 +0530 Subject: [PATCH] feat: add player lock button --- src/components/player/modals/LockOverlay.tsx | 124 +++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/components/player/modals/LockOverlay.tsx diff --git a/src/components/player/modals/LockOverlay.tsx b/src/components/player/modals/LockOverlay.tsx new file mode 100644 index 00000000..57b2008f --- /dev/null +++ b/src/components/player/modals/LockOverlay.tsx @@ -0,0 +1,124 @@ +import React, { useRef, useCallback, useImperativeHandle, forwardRef, useState } from 'react'; +import { View, TouchableOpacity, Animated, StyleSheet, Text } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; + +export interface LockOverlayRef { + lock: () => void; +} + +interface LockOverlayProps { + onHideControls: () => void; + onShowControls: () => void; +} + +const UNLOCK_BUTTON_VISIBLE_MS = 5000; + +export const LockOverlay = forwardRef(({ onHideControls, onShowControls }, ref) => { + const [isLocked, setIsLocked] = useState(false); + const isButtonVisibleRef = useRef(false); + const buttonOpacity = useRef(new Animated.Value(0)).current; + const hideTimerRef = useRef(null); + + const clearHideTimer = useCallback(() => { + if (hideTimerRef.current) { + clearTimeout(hideTimerRef.current); + hideTimerRef.current = null; + } + }, []); + + const hideButton = useCallback(() => { + isButtonVisibleRef.current = false; + Animated.timing(buttonOpacity, { + toValue: 0, + duration: 400, + useNativeDriver: true, + }).start(); + }, [buttonOpacity]); + + const showButton = useCallback(() => { + clearHideTimer(); + isButtonVisibleRef.current = true; + Animated.timing(buttonOpacity, { + toValue: 1, + duration: 200, + useNativeDriver: true, + }).start(); + hideTimerRef.current = setTimeout(hideButton, UNLOCK_BUTTON_VISIBLE_MS); + }, [buttonOpacity, clearHideTimer, hideButton]); + + const lock = useCallback(() => { + setIsLocked(true); + onHideControls(); + showButton(); + }, [showButton, onHideControls]); + + const unlock = useCallback(() => { + clearHideTimer(); + buttonOpacity.setValue(0); + isButtonVisibleRef.current = false; + setIsLocked(false); + onShowControls(); + }, [buttonOpacity, clearHideTimer, onShowControls]); + + useImperativeHandle(ref, () => ({ lock }), [lock]); + + const handleScreenTap = useCallback(() => { + if (isButtonVisibleRef.current) return; + showButton(); + }, [showButton]); + + if (!isLocked) return null; + + return ( + + + + + + Unlock + + + + ); +}); + +const styles = StyleSheet.create({ + fullScreenBlocker: { + ...StyleSheet.absoluteFillObject, + zIndex: 100, + backgroundColor: 'transparent', + justifyContent: 'center', + alignItems: 'center', + }, + unlockButtonContainer: { + position: 'absolute', + alignSelf: 'center', + }, + unlockButton: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + paddingVertical: 12, + paddingHorizontal: 24, + borderRadius: 24, + backgroundColor: 'rgba(0, 0, 0, 0.70)', + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.3)', + }, + unlockText: { + color: 'white', + fontSize: 15, + fontWeight: '600', + }, +});