forked from Ninjalama/streamyfin_mirror
Fix correct time not being reported when switching quality in the beg… (#855)
Co-authored-by: Alex Kim <alexkim@Alexs-MacBook-Pro.local>
This commit is contained in:
@@ -1,6 +1,26 @@
|
||||
import {
|
||||
type BaseItemDto,
|
||||
type MediaSourceInfo,
|
||||
PlaybackOrder,
|
||||
type PlaybackProgressInfo,
|
||||
PlaybackStartInfo,
|
||||
RepeatMode,
|
||||
} from "@jellyfin/sdk/lib/generated-client";
|
||||
import {
|
||||
getPlaystateApi,
|
||||
getUserLibraryApi,
|
||||
} from "@jellyfin/sdk/lib/utils/api";
|
||||
import { activateKeepAwakeAsync, deactivateKeepAwake } from "expo-keep-awake";
|
||||
import { router, useGlobalSearchParams, useNavigation } from "expo-router";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Alert, Platform, View } from "react-native";
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { BITRATES } from "@/components/BitrateSelector";
|
||||
import { Loader } from "@/components/Loader";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { Loader } from "@/components/Loader";
|
||||
import { Controls } from "@/components/video-player/controls/Controls";
|
||||
import { getDownloadedFileUrl } from "@/hooks/useDownloadedFileOpener";
|
||||
import { useHaptic } from "@/hooks/useHaptic";
|
||||
@@ -20,35 +40,10 @@ import { writeToLog } from "@/utils/log";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import generateDeviceProfile from "@/utils/profiles/native";
|
||||
import { msToTicks, ticksToSeconds } from "@/utils/time";
|
||||
import {
|
||||
type BaseItemDto,
|
||||
type MediaSourceInfo,
|
||||
PlaybackOrder,
|
||||
type PlaybackProgressInfo,
|
||||
PlaybackStartInfo,
|
||||
RepeatMode,
|
||||
} from "@jellyfin/sdk/lib/generated-client";
|
||||
import {
|
||||
getPlaystateApi,
|
||||
getUserLibraryApi,
|
||||
} from "@jellyfin/sdk/lib/utils/api";
|
||||
import { activateKeepAwakeAsync, deactivateKeepAwake } from "expo-keep-awake";
|
||||
import { useGlobalSearchParams, useNavigation } from "expo-router";
|
||||
import { useAtomValue } from "jotai";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Alert, Platform, View } from "react-native";
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
const downloadProvider = !Platform.isTV
|
||||
? require("@/providers/DownloadProvider")
|
||||
: null;
|
||||
: { useDownload: () => null };
|
||||
|
||||
const IGNORE_SAFE_AREAS_KEY = "video_player_ignore_safe_areas";
|
||||
|
||||
@@ -79,10 +74,7 @@ export default function page() {
|
||||
? null
|
||||
: require("react-native-volume-manager");
|
||||
|
||||
let getDownloadedItem = null;
|
||||
if (!Platform.isTV) {
|
||||
getDownloadedItem = downloadProvider.useDownload();
|
||||
}
|
||||
const getDownloadedItem = downloadProvider.useDownload();
|
||||
|
||||
const revalidateProgressCache = useInvalidatePlaybackProgressCache();
|
||||
|
||||
@@ -105,6 +97,7 @@ export default function page() {
|
||||
mediaSourceId,
|
||||
bitrateValue: bitrateValueStr,
|
||||
offline: offlineStr,
|
||||
playbackPosition: playbackPositionFromUrl,
|
||||
} = useGlobalSearchParams<{
|
||||
itemId: string;
|
||||
audioIndex: string;
|
||||
@@ -112,6 +105,8 @@ export default function page() {
|
||||
mediaSourceId: string;
|
||||
bitrateValue: string;
|
||||
offline: string;
|
||||
/** Playback position in ticks. */
|
||||
playbackPosition?: string;
|
||||
}>();
|
||||
const [settings] = useSettings();
|
||||
const insets = useSafeAreaInsets();
|
||||
@@ -133,6 +128,14 @@ export default function page() {
|
||||
isError: false,
|
||||
});
|
||||
|
||||
/** Gets the initial playback position from the URL or the item's user data. */
|
||||
const getInitialPlaybackTicks = useCallback((): number => {
|
||||
if (playbackPositionFromUrl) {
|
||||
return Number.parseInt(playbackPositionFromUrl, 10);
|
||||
}
|
||||
return item?.UserData?.PlaybackPositionTicks ?? 0;
|
||||
}, [playbackPositionFromUrl, item]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchItemData = async () => {
|
||||
setItemStatus({ isLoading: true, isError: false });
|
||||
@@ -190,7 +193,7 @@ export default function page() {
|
||||
const res = await getStreamUrl({
|
||||
api,
|
||||
item,
|
||||
startTimeTicks: item?.UserData?.PlaybackPositionTicks!,
|
||||
startTimeTicks: getInitialPlaybackTicks(),
|
||||
userId: user?.Id,
|
||||
audioStreamIndex: audioIndex,
|
||||
maxStreamingBitrate: bitrateValue,
|
||||
@@ -308,8 +311,12 @@ export default function page() {
|
||||
|
||||
progress.set(currentTime);
|
||||
|
||||
if (offline) return;
|
||||
// Update the playback position in the URL.
|
||||
router.setParams({
|
||||
playbackPosition: msToTicks(currentTime).toString(),
|
||||
});
|
||||
|
||||
if (offline) return;
|
||||
if (!item?.Id || !stream) return;
|
||||
|
||||
reportPlaybackProgress();
|
||||
@@ -349,12 +356,11 @@ export default function page() {
|
||||
progress,
|
||||
]);
|
||||
|
||||
/** Gets the initial playback position in seconds. */
|
||||
const startPosition = useMemo(() => {
|
||||
if (offline) return 0;
|
||||
return item?.UserData?.PlaybackPositionTicks
|
||||
? ticksToSeconds(item.UserData.PlaybackPositionTicks)
|
||||
: 0;
|
||||
}, [item, offline]);
|
||||
return ticksToSeconds(getInitialPlaybackTicks());
|
||||
}, [offline, getInitialPlaybackTicks]);
|
||||
|
||||
const volumeUpCb = useCallback(async () => {
|
||||
if (Platform.isTV) return;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import type { TrackInfo } from "@/modules/VlcPlayer.types";
|
||||
import { VideoPlayer, useSettings } from "@/utils/atoms/settings";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import type React from "react";
|
||||
import {
|
||||
type ReactNode,
|
||||
createContext,
|
||||
type ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import type { TrackInfo } from "@/modules/VlcPlayer.types";
|
||||
import { useSettings, VideoPlayer } from "@/utils/atoms/settings";
|
||||
import type { Track } from "../types";
|
||||
import { useControlContext } from "./ControlContext";
|
||||
|
||||
@@ -57,13 +57,14 @@ export const VideoProvider: React.FC<VideoProviderProps> = ({
|
||||
const allSubs =
|
||||
mediaSource?.MediaStreams?.filter((s) => s.Type === "Subtitle") || [];
|
||||
|
||||
const { itemId, audioIndex, bitrateValue, subtitleIndex } =
|
||||
const { itemId, audioIndex, bitrateValue, subtitleIndex, playbackPosition } =
|
||||
useLocalSearchParams<{
|
||||
itemId: string;
|
||||
audioIndex: string;
|
||||
subtitleIndex: string;
|
||||
mediaSourceId: string;
|
||||
bitrateValue: string;
|
||||
playbackPosition: string;
|
||||
}>();
|
||||
|
||||
const onTextBasedSubtitle = useMemo(
|
||||
@@ -88,6 +89,7 @@ export const VideoProvider: React.FC<VideoProviderProps> = ({
|
||||
subtitleIndex: chosenSubtitleIndex,
|
||||
mediaSourceId: mediaSource?.Id ?? "",
|
||||
bitrateValue: bitrateValue,
|
||||
playbackPosition: playbackPosition,
|
||||
}).toString();
|
||||
|
||||
//@ts-ignore
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import React, { useCallback } from "react";
|
||||
import { useCallback } from "react";
|
||||
import { Platform, TouchableOpacity } from "react-native";
|
||||
|
||||
const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
|
||||
import { BITRATES } from "@/components/BitrateSelector";
|
||||
|
||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||
import { BITRATES } from "@/components/BitrateSelector";
|
||||
import { useControlContext } from "../contexts/ControlContext";
|
||||
import { useVideoContext } from "../contexts/VideoContext";
|
||||
|
||||
@@ -17,13 +19,15 @@ const DropdownView = () => {
|
||||
];
|
||||
const router = useRouter();
|
||||
|
||||
const { subtitleIndex, audioIndex, bitrateValue } = useLocalSearchParams<{
|
||||
itemId: string;
|
||||
audioIndex: string;
|
||||
subtitleIndex: string;
|
||||
mediaSourceId: string;
|
||||
bitrateValue: string;
|
||||
}>();
|
||||
const { subtitleIndex, audioIndex, bitrateValue, playbackPosition } =
|
||||
useLocalSearchParams<{
|
||||
itemId: string;
|
||||
audioIndex: string;
|
||||
subtitleIndex: string;
|
||||
mediaSourceId: string;
|
||||
bitrateValue: string;
|
||||
playbackPosition: string;
|
||||
}>();
|
||||
|
||||
const changeBitrate = useCallback(
|
||||
(bitrate: string) => {
|
||||
@@ -33,11 +37,12 @@ const DropdownView = () => {
|
||||
subtitleIndex: subtitleIndex.toString() ?? "",
|
||||
mediaSourceId: mediaSource?.Id ?? "",
|
||||
bitrateValue: bitrate.toString(),
|
||||
playbackPosition: playbackPosition,
|
||||
}).toString();
|
||||
// @ts-expect-error
|
||||
router.replace(`player/direct-player?${queryParams}`);
|
||||
},
|
||||
[item, mediaSource, subtitleIndex, audioIndex],
|
||||
[item, mediaSource, subtitleIndex, audioIndex, playbackPosition],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user