mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 07:21:58 +00:00
feat: add player lock button
This commit is contained in:
parent
56b292f79a
commit
fbc32bcd22
1 changed files with 93 additions and 74 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue