mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
fix: start position and errors
This commit is contained in:
@@ -15,14 +15,21 @@ import {
|
||||
usePlaySettings,
|
||||
} from "@/providers/PlaySettingsProvider";
|
||||
import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl";
|
||||
import { writeToLog } from "@/utils/log";
|
||||
import { msToTicks, ticksToMs } from "@/utils/time";
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { getPlaystateApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import * as Haptics from "expo-haptics";
|
||||
import { useFocusEffect } from "expo-router";
|
||||
import { useFocusEffect, useRouter } from "expo-router";
|
||||
import { useAtomValue } from "jotai";
|
||||
import React, { useCallback, useMemo, useRef, useState } from "react";
|
||||
import { Dimensions, Pressable, StatusBar, View } from "react-native";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Alert, Dimensions, Pressable, StatusBar, View } from "react-native";
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
|
||||
export default function page() {
|
||||
@@ -33,6 +40,8 @@ export default function page() {
|
||||
// const poster = usePoster(playSettings, api);
|
||||
// const user = useAtomValue(userAtom);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const screenDimensions = Dimensions.get("screen");
|
||||
|
||||
const [isPlaybackStopped, setIsPlaybackStopped] = useState(false);
|
||||
@@ -46,8 +55,11 @@ export default function page() {
|
||||
const isSeeking = useSharedValue(false);
|
||||
const cacheProgress = useSharedValue(0);
|
||||
|
||||
if (!playSettings || !playUrl || !api || !playSettings.item || !mediaSource)
|
||||
if (!playSettings || !playUrl || !api || !playSettings.item || !mediaSource) {
|
||||
Alert.alert("Error", "Invalid play settings");
|
||||
router.back();
|
||||
return null;
|
||||
}
|
||||
|
||||
const togglePlay = useCallback(
|
||||
async (ticks: number) => {
|
||||
@@ -136,6 +148,7 @@ export default function page() {
|
||||
|
||||
const { currentTime, isPlaying } = data.nativeEvent;
|
||||
|
||||
progress.value = currentTime;
|
||||
const currentTimeInTicks = msToTicks(currentTime);
|
||||
|
||||
await getPlaystateApi(api).onPlaybackProgress({
|
||||
@@ -198,6 +211,13 @@ export default function page() {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log(
|
||||
"PlaybackPositionTicks",
|
||||
playSettings.item?.UserData?.PlaybackPositionTicks
|
||||
);
|
||||
}, [playSettings.item]);
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
@@ -232,6 +252,14 @@ export default function page() {
|
||||
onVideoLoadEnd={() => {
|
||||
setIsVideoLoaded(true);
|
||||
}}
|
||||
onVideoError={(e) => {
|
||||
console.error("Video Error:", e.nativeEvent);
|
||||
Alert.alert(
|
||||
"Error",
|
||||
"An error occurred while playing the video. Check logs in settings."
|
||||
);
|
||||
writeToLog("ERROR", "Video Error", e.nativeEvent);
|
||||
}}
|
||||
/>
|
||||
</Pressable>
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ public class VlcPlayerModule: Module {
|
||||
"onVideoStateChange",
|
||||
"onVideoLoadStart",
|
||||
"onVideoLoadEnd",
|
||||
"onVideoProgress"
|
||||
"onVideoProgress",
|
||||
"onVideoError"
|
||||
)
|
||||
|
||||
AsyncFunction("play") { (view: VlcPlayerView) in
|
||||
|
||||
@@ -99,7 +99,13 @@ class VlcPlayerView: ExpoView {
|
||||
let isNetwork = source["isNetwork"] as? Bool ?? false
|
||||
let startPosition = source["startPosition"] as? Int32 ?? 0
|
||||
|
||||
guard let uri = uri, !uri.isEmpty else { return }
|
||||
guard let uri = uri, !uri.isEmpty else {
|
||||
print("Error: Invalid or empty URI")
|
||||
self.onVideoError?(["error": "Invalid or empty URI"])
|
||||
return
|
||||
}
|
||||
|
||||
self.onVideoLoadStart?(["target": self.reactTag ?? NSNull()])
|
||||
|
||||
if initType == 2, let options = initOptions {
|
||||
self.mediaPlayer = VLCMediaPlayer(options: options)
|
||||
@@ -128,6 +134,7 @@ class VlcPlayerView: ExpoView {
|
||||
media = VLCMedia(path: uri)
|
||||
}
|
||||
}
|
||||
|
||||
// Apply subtitle options
|
||||
let subtitleOptions = self.getSubtitleOptions()
|
||||
media.addOptions(subtitleOptions)
|
||||
@@ -141,6 +148,7 @@ class VlcPlayerView: ExpoView {
|
||||
print("Debug: No additional media options provided")
|
||||
}
|
||||
|
||||
// Apply subtitle options
|
||||
let subtitleTrackIndex = source["subtitleTrackIndex"] as? Int ?? -1
|
||||
print("Debug: Subtitle track index from source: \(subtitleTrackIndex)")
|
||||
|
||||
@@ -154,14 +162,25 @@ class VlcPlayerView: ExpoView {
|
||||
self.mediaPlayer?.media = media
|
||||
|
||||
if startPosition > 0 {
|
||||
self.mediaPlayer?.time = VLCTime(int: startPosition)
|
||||
// Wait for the media to be ready before setting the start position
|
||||
NotificationCenter.default.addObserver(
|
||||
forName: NSNotification.Name(rawValue: VLCMediaPlayerStateChanged), object: nil,
|
||||
queue: nil
|
||||
) { [weak self] notification in
|
||||
guard let self = self, let player = self.mediaPlayer,
|
||||
player.isPlaying == false
|
||||
else { return }
|
||||
|
||||
self.mediaPlayer?.time = VLCTime(int: startPosition)
|
||||
NotificationCenter.default.removeObserver(
|
||||
self, name: NSNotification.Name(rawValue: VLCMediaPlayerStateChanged),
|
||||
object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
if autoplay {
|
||||
self.play()
|
||||
}
|
||||
|
||||
self.onVideoLoadStart?(["target": self.reactTag ?? NSNull()])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,6 +539,7 @@ class VlcPlayerView: ExpoView {
|
||||
@objc var onVideoStateChange: RCTDirectEventBlock?
|
||||
@objc var onVideoProgress: RCTDirectEventBlock?
|
||||
@objc var onVideoLoadEnd: RCTDirectEventBlock?
|
||||
@objc var onVideoError: RCTDirectEventBlock?
|
||||
|
||||
// MARK: - Deinitialization
|
||||
|
||||
@@ -545,6 +565,7 @@ extension VlcPlayerView: VLCMediaPlayerDelegate {
|
||||
"target": self.reactTag ?? NSNull(),
|
||||
"currentTime": player.time.intValue,
|
||||
"duration": player.media?.length.intValue ?? 0,
|
||||
"error": false,
|
||||
]
|
||||
|
||||
if player.isPlaying {
|
||||
@@ -556,9 +577,16 @@ extension VlcPlayerView: VLCMediaPlayerDelegate {
|
||||
stateInfo["state"] = "Paused"
|
||||
}
|
||||
|
||||
if player.state == .buffering {
|
||||
if player.state == VLCMediaPlayerState.buffering {
|
||||
stateInfo["isBuffering"] = true
|
||||
stateInfo["state"] = "Buffering"
|
||||
} else if player.state == VLCMediaPlayerState.error {
|
||||
print("player.state ~ error")
|
||||
stateInfo["state"] = "Error"
|
||||
self.onVideoLoadEnd?(stateInfo)
|
||||
} else if player.state == VLCMediaPlayerState.opening {
|
||||
print("player.state ~ opening")
|
||||
stateInfo["state"] = "Opening"
|
||||
}
|
||||
|
||||
// Dermine if the media has finished loading
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
export type PlaybackStatePayload = {
|
||||
nativeEvent: {
|
||||
target: number;
|
||||
state:
|
||||
| "Opening"
|
||||
| "Buffering"
|
||||
| "Playing"
|
||||
| "Paused"
|
||||
| "Stopped"
|
||||
| "Ended"
|
||||
| "Error"
|
||||
| "Unknown";
|
||||
state: "Opening" | "Buffering" | "Playing" | "Paused" | "Error";
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
isBuffering: boolean;
|
||||
@@ -69,6 +61,7 @@ export type VlcPlayerViewProps = {
|
||||
onVideoStateChange?: (event: PlaybackStatePayload) => void;
|
||||
onVideoLoadStart?: (event: VideoLoadStartPayload) => void;
|
||||
onVideoLoadEnd?: (event: VideoLoadStartPayload) => void;
|
||||
onVideoError?: (event: PlaybackStatePayload) => void;
|
||||
};
|
||||
|
||||
export interface VlcPlayerViewRef {
|
||||
|
||||
@@ -95,6 +95,7 @@ const VlcPlayerView = React.forwardRef<VlcPlayerViewRef, VlcPlayerViewProps>(
|
||||
onVideoStateChange,
|
||||
onVideoProgress,
|
||||
onVideoLoadEnd,
|
||||
onVideoError,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
@@ -120,6 +121,7 @@ const VlcPlayerView = React.forwardRef<VlcPlayerViewRef, VlcPlayerViewProps>(
|
||||
onVideoLoadEnd={onVideoLoadEnd}
|
||||
onVideoStateChange={onVideoStateChange}
|
||||
onVideoProgress={onVideoProgress}
|
||||
onVideoError={onVideoError}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user