feat: add player lock button

This commit is contained in:
chrisk325 2026-03-22 15:43:55 +05:30 committed by GitHub
parent 56b292f79a
commit fbc32bcd22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -30,6 +30,7 @@ import { useSettings } from '../../hooks/useSettings';
// Shared Components // Shared Components
import { GestureControls, PauseOverlay, SpeedActivatedOverlay } from './components'; import { GestureControls, PauseOverlay, SpeedActivatedOverlay } from './components';
import { LockOverlay, LockOverlayRef } from './modals/LockOverlay';
import LoadingOverlay from './modals/LoadingOverlay'; import LoadingOverlay from './modals/LoadingOverlay';
import PlayerControls from './controls/PlayerControls'; import PlayerControls from './controls/PlayerControls';
import { AudioTrackModal } from './modals/AudioTrackModal'; import { AudioTrackModal } from './modals/AudioTrackModal';
@ -91,6 +92,8 @@ const AndroidVideoPlayer: React.FC = () => {
const mpvPlayerRef = useRef<MpvPlayerRef>(null); const mpvPlayerRef = useRef<MpvPlayerRef>(null);
const exoPlayerRef = useRef<any>(null); const exoPlayerRef = useRef<any>(null);
const pinchRef = useRef(null); const pinchRef = useRef(null);
const lockOverlayRef = useRef<LockOverlayRef>(null);
const [isLocked, setIsLocked] = useState(false);
const tracksHook = usePlayerTracks(); const tracksHook = usePlayerTracks();
const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(uri); const [currentStreamUrl, setCurrentStreamUrl] = useState<string>(uri);
@ -271,7 +274,6 @@ const AndroidVideoPlayer: React.FC = () => {
const nextEpisodeHook = useNextEpisode(type, season, episode, groupedEpisodes, (metadataResult as any)?.groupedEpisodes, episodeId); const nextEpisodeHook = useNextEpisode(type, season, episode, groupedEpisodes, (metadataResult as any)?.groupedEpisodes, episodeId);
const { segments: skipIntervals, outroSegment } = useSkipSegments({ const { segments: skipIntervals, outroSegment } = useSkipSegments({
imdbId: resolvedImdbId || (id?.startsWith('tt') ? id : undefined), imdbId: resolvedImdbId || (id?.startsWith('tt') ? id : undefined),
type, type,
@ -1047,29 +1049,31 @@ const AndroidVideoPlayer: React.FC = () => {
controlsVisible={playerState.showControls} controlsVisible={playerState.showControls}
controlsExtraOffset={100} controlsExtraOffset={100}
/> />
<GestureControls <View pointerEvents={isLocked ? 'none' : 'box-none'} style={StyleSheet.absoluteFill}>
screenDimensions={playerState.screenDimensions} <GestureControls
gestureControls={gestureControls} screenDimensions={playerState.screenDimensions}
onLongPressActivated={speedControl.activateSpeedBoost} gestureControls={gestureControls}
onLongPressEnd={speedControl.deactivateSpeedBoost} onLongPressActivated={speedControl.activateSpeedBoost}
onLongPressStateChange={(e) => { onLongPressEnd={speedControl.deactivateSpeedBoost}
const state = e.nativeEvent.state; onLongPressStateChange={(e) => {
if (state === 5 || state === 3 || state === 1) { // END, CANCELLED, FAILED const state = e.nativeEvent.state;
speedControl.deactivateSpeedBoost(); if (state === 5 || state === 3 || state === 1) { // END, CANCELLED, FAILED
} speedControl.deactivateSpeedBoost();
}} }
toggleControls={toggleControls} }}
showControls={playerState.showControls} toggleControls={toggleControls}
hideControls={hideControls} showControls={playerState.showControls}
volume={volume} hideControls={hideControls}
controlsTimeout={controlsTimeout} volume={volume}
resizeMode={playerState.resizeMode} controlsTimeout={controlsTimeout}
skip={controlsHook.skip} resizeMode={playerState.resizeMode}
currentTime={playerState.currentTime} skip={controlsHook.skip}
duration={playerState.duration} currentTime={playerState.currentTime}
seekToTime={controlsHook.seekToTime} duration={playerState.duration}
formatTime={formatTime} seekToTime={controlsHook.seekToTime}
/> formatTime={formatTime}
/>
</View>
{/* Buffering Indicator (Visible when controls are hidden) */} {/* Buffering Indicator (Visible when controls are hidden) */}
{playerState.isBuffering && !playerState.showControls && ( {playerState.isBuffering && !playerState.showControls && (
@ -1078,58 +1082,73 @@ const AndroidVideoPlayer: React.FC = () => {
</View> </View>
)} )}
<PlayerControls <View pointerEvents={isLocked ? 'none' : 'box-none'} style={StyleSheet.absoluteFill}>
showControls={playerState.showControls} <PlayerControls
fadeAnim={fadeAnim} showControls={playerState.showControls}
paused={playerState.paused} fadeAnim={fadeAnim}
title={title} paused={playerState.paused}
episodeTitle={episodeTitle} title={title}
season={season} episodeTitle={episodeTitle}
episode={episode} season={season}
quality={currentQuality || quality} episode={episode}
year={year} quality={currentQuality || quality}
streamProvider={currentStreamProvider || streamProvider} year={year}
streamName={currentStreamName} streamProvider={currentStreamProvider || streamProvider}
currentTime={playerState.currentTime} streamName={currentStreamName}
duration={playerState.duration} currentTime={playerState.currentTime}
zoomScale={1} duration={playerState.duration}
currentResizeMode={playerState.resizeMode} zoomScale={1}
ksAudioTracks={tracksHook.ksAudioTracks} currentResizeMode={playerState.resizeMode}
selectedAudioTrack={tracksHook.computedSelectedAudioTrack} ksAudioTracks={tracksHook.ksAudioTracks}
availableStreams={availableStreams} selectedAudioTrack={tracksHook.computedSelectedAudioTrack}
togglePlayback={controlsHook.togglePlayback} availableStreams={availableStreams}
skip={controlsHook.skip} togglePlayback={controlsHook.togglePlayback}
handleClose={handleClose} skip={controlsHook.skip}
cycleAspectRatio={cycleResizeMode} handleClose={handleClose}
cyclePlaybackSpeed={() => { cycleAspectRatio={cycleResizeMode}
const speeds = [0.5, 1, 1.25, 1.5, 2]; cyclePlaybackSpeed={() => {
const idx = speeds.indexOf(speedControl.playbackSpeed); const speeds = [0.5, 1, 1.25, 1.5, 2];
const next = speeds[(idx + 1) % speeds.length]; const idx = speeds.indexOf(speedControl.playbackSpeed);
speedControl.setPlaybackSpeed(next); const next = speeds[(idx + 1) % speeds.length];
speedControl.setPlaybackSpeed(next);
}}
currentPlaybackSpeed={speedControl.playbackSpeed}
setShowAudioModal={modals.setShowAudioModal}
setShowSubtitleModal={modals.setShowSubtitleModal}
setShowSpeedModal={modals.setShowSpeedModal}
setShowSubmitIntroModal={modals.setShowSubmitIntroModal}
isSubtitleModalOpen={modals.showSubtitleModal}
setShowSourcesModal={modals.setShowSourcesModal}
setShowEpisodesModal={type === 'series' ? modals.setShowEpisodesModal : undefined}
onSliderValueChange={(val) => { playerState.isDragging.current = true; }}
onSlidingStart={() => { playerState.isDragging.current = true; }}
onSlidingComplete={(val) => {
playerState.isDragging.current = false;
controlsHook.seekToTime(val);
}}
buffered={playerState.buffered}
formatTime={formatTime}
playerBackend={useExoPlayer ? 'ExoPlayer' : 'MPV'}
onSwitchToMPV={handleManualSwitchToMPV}
useExoPlayer={useExoPlayer}
canEnterPictureInPicture={canShowPipButton}
onEnterPictureInPicture={handleEnterPictureInPicture}
isBuffering={playerState.isBuffering}
imdbId={resolvedImdbId}
onLock={() => lockOverlayRef.current?.lock()}
/>
</View>
<LockOverlay
ref={lockOverlayRef}
onHideControls={() => {
setIsLocked(true);
playerState.setShowControls(false);
}} }}
currentPlaybackSpeed={speedControl.playbackSpeed} onShowControls={() => {
setShowAudioModal={modals.setShowAudioModal} setIsLocked(false);
setShowSubtitleModal={modals.setShowSubtitleModal} playerState.setShowControls(true);
setShowSpeedModal={modals.setShowSpeedModal}
setShowSubmitIntroModal={modals.setShowSubmitIntroModal}
isSubtitleModalOpen={modals.showSubtitleModal}
setShowSourcesModal={modals.setShowSourcesModal}
setShowEpisodesModal={type === 'series' ? modals.setShowEpisodesModal : undefined}
onSliderValueChange={(val) => { playerState.isDragging.current = true; }}
onSlidingStart={() => { playerState.isDragging.current = true; }}
onSlidingComplete={(val) => {
playerState.isDragging.current = false;
controlsHook.seekToTime(val);
}} }}
buffered={playerState.buffered}
formatTime={formatTime}
playerBackend={useExoPlayer ? 'ExoPlayer' : 'MPV'}
onSwitchToMPV={handleManualSwitchToMPV}
useExoPlayer={useExoPlayer}
canEnterPictureInPicture={canShowPipButton}
onEnterPictureInPicture={handleEnterPictureInPicture}
isBuffering={playerState.isBuffering}
imdbId={resolvedImdbId}
/> />
<SpeedActivatedOverlay <SpeedActivatedOverlay