mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-22 00:34:43 +01:00
Added bandaid fix
This commit is contained in:
@@ -20,6 +20,7 @@ import { getLogoImageUrlById } from "@/utils/jellyfin/image/getLogoImageUrlById"
|
||||
import {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
MediaStream,
|
||||
} from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { Image } from "expo-image";
|
||||
import { useNavigation } from "expo-router";
|
||||
@@ -32,6 +33,7 @@ import { Chromecast } from "./Chromecast";
|
||||
import { ItemHeader } from "./ItemHeader";
|
||||
import { MediaSourceSelector } from "./MediaSourceSelector";
|
||||
import { MoreMoviesWithActor } from "./MoreMoviesWithActor";
|
||||
import { SubtitleHelper } from "@/utils/SubtitleHelper";
|
||||
|
||||
export type SelectedOptions = {
|
||||
bitrate: Bitrate;
|
||||
@@ -109,6 +111,36 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
|
||||
return Boolean(logoUrl && loadingLogo);
|
||||
}, [loadingLogo, logoUrl]);
|
||||
|
||||
const [isTranscoding, setIsTranscoding] = useState(false);
|
||||
const [previouslyChosenSubtitleIndex, setPreviouslyChosenSubtitleIndex] =
|
||||
useState<number | undefined>(selectedOptions?.subtitleIndex);
|
||||
|
||||
useEffect(() => {
|
||||
const isTranscoding = Boolean(selectedOptions?.bitrate.value);
|
||||
if (isTranscoding) {
|
||||
setPreviouslyChosenSubtitleIndex(selectedOptions?.subtitleIndex);
|
||||
const subHelper = new SubtitleHelper(
|
||||
selectedOptions?.mediaSource?.MediaStreams ?? []
|
||||
);
|
||||
|
||||
const newSubtitleIndex = subHelper.getMostCommonSubtitleByName(
|
||||
selectedOptions?.subtitleIndex
|
||||
);
|
||||
|
||||
setSelectedOptions((prev) => ({
|
||||
...prev!,
|
||||
subtitleIndex: newSubtitleIndex ?? -1,
|
||||
}));
|
||||
}
|
||||
if (!isTranscoding && previouslyChosenSubtitleIndex !== undefined) {
|
||||
setSelectedOptions((prev) => ({
|
||||
...prev!,
|
||||
subtitleIndex: previouslyChosenSubtitleIndex,
|
||||
}));
|
||||
}
|
||||
setIsTranscoding(isTranscoding);
|
||||
}, [selectedOptions?.bitrate]);
|
||||
|
||||
if (!selectedOptions) return null;
|
||||
|
||||
return (
|
||||
@@ -199,6 +231,7 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
|
||||
selected={selectedOptions.audioIndex}
|
||||
/>
|
||||
<SubtitleTrackSelector
|
||||
isTranscoding={isTranscoding}
|
||||
source={selectedOptions.mediaSource}
|
||||
onChange={(val) =>
|
||||
setSelectedOptions(
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
import { tc } from "@/utils/textTools";
|
||||
import { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { useMemo } from "react";
|
||||
import { TouchableOpacity, View } from "react-native";
|
||||
import { Platform, TouchableOpacity, View } from "react-native";
|
||||
import * as DropdownMenu from "zeego/dropdown-menu";
|
||||
import { Text } from "./common/Text";
|
||||
import { SubtitleHelper } from "@/utils/SubtitleHelper";
|
||||
|
||||
interface Props extends React.ComponentProps<typeof View> {
|
||||
source?: MediaSourceInfo;
|
||||
onChange: (value: number) => void;
|
||||
selected?: number | undefined;
|
||||
isTranscoding?: boolean;
|
||||
}
|
||||
|
||||
export const SubtitleTrackSelector: React.FC<Props> = ({
|
||||
source,
|
||||
onChange,
|
||||
selected,
|
||||
isTranscoding,
|
||||
...props
|
||||
}) => {
|
||||
const subtitleStreams = useMemo(
|
||||
() => source?.MediaStreams?.filter((x) => x.Type === "Subtitle") ?? [],
|
||||
[source]
|
||||
);
|
||||
const subtitleStreams = useMemo(() => {
|
||||
const subtitleHelper = new SubtitleHelper(source?.MediaStreams ?? []);
|
||||
|
||||
if (isTranscoding && Platform.OS === "ios") {
|
||||
return subtitleHelper.getUniqueSubtitles();
|
||||
}
|
||||
|
||||
return subtitleHelper.getSubtitles();
|
||||
}, [source, isTranscoding]);
|
||||
|
||||
const selectedSubtitleSteam = useMemo(
|
||||
() => subtitleStreams.find((x) => x.Index === selected),
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TranscodedSubtitle } from "../types";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||
import { SubtitleHelper } from "@/utils/SubtitleHelper";
|
||||
|
||||
interface DropdownViewProps {
|
||||
showControls: boolean;
|
||||
@@ -43,6 +44,8 @@ const DropdownView: React.FC<DropdownViewProps> = ({ showControls }) => {
|
||||
mediaSource?.MediaStreams?.filter((x) => x.Type === "Subtitle") ?? [];
|
||||
const textBasedSubs = allSubs.filter((x) => x.IsTextSubtitleStream);
|
||||
|
||||
const subtitleHelper = new SubtitleHelper(mediaSource?.MediaStreams ?? []);
|
||||
|
||||
const allSubtitleTracksForTranscodingStream = useMemo(() => {
|
||||
const disableSubtitle = {
|
||||
name: "Disable",
|
||||
@@ -57,28 +60,9 @@ const DropdownView: React.FC<DropdownViewProps> = ({ showControls }) => {
|
||||
IsTextSubtitleStream: true,
|
||||
})) || [];
|
||||
|
||||
console.log("textSubtitles", textSubtitles);
|
||||
|
||||
let textIndex = 0; // To track position in textSubtitles
|
||||
// Merge text and image subtitles in the order of allSubs
|
||||
const sortedSubtitles = allSubs.map((sub) => {
|
||||
if (sub.IsTextSubtitleStream) {
|
||||
if (textSubtitles.length === 0) return disableSubtitle;
|
||||
const textSubtitle = textSubtitles[textIndex];
|
||||
if (!textSubtitle) return disableSubtitle;
|
||||
textIndex++;
|
||||
return textSubtitle;
|
||||
} else {
|
||||
return {
|
||||
name: sub.DisplayTitle!,
|
||||
index: sub.Index!,
|
||||
IsTextSubtitleStream: sub.IsTextSubtitleStream,
|
||||
} as TranscodedSubtitle;
|
||||
}
|
||||
});
|
||||
const sortedSubtitles = subtitleHelper.getSortedSubtitles(textSubtitles);
|
||||
|
||||
console.log("sortedSubtitles", sortedSubtitles);
|
||||
|
||||
return [disableSubtitle, ...sortedSubtitles];
|
||||
}
|
||||
|
||||
@@ -114,16 +98,6 @@ const DropdownView: React.FC<DropdownViewProps> = ({ showControls }) => {
|
||||
index: x.Index!,
|
||||
})) || [];
|
||||
|
||||
// HLS stream indexes are not the same as the actual source indexes.
|
||||
// This function aims to get the source subtitle index from the embedded track index.
|
||||
const getSourceSubtitleIndex = (embeddedTrackIndex: number): number => {
|
||||
// If we're not on text-based subtitles, return the embedded track index
|
||||
if (!isOnTextSubtitle) {
|
||||
return parseInt(subtitleIndex);
|
||||
}
|
||||
return textBasedSubs[embeddedTrackIndex]?.Index ?? -1;
|
||||
};
|
||||
|
||||
const ChangeTranscodingAudio = useCallback(
|
||||
(audioIndex: number) => {
|
||||
console.log("ChangeTranscodingAudio", subtitleIndex, audioIndex);
|
||||
@@ -182,7 +156,9 @@ const DropdownView: React.FC<DropdownViewProps> = ({ showControls }) => {
|
||||
value={
|
||||
subtitleIndex ===
|
||||
(isOnTextSubtitle && sub.IsTextSubtitleStream
|
||||
? getSourceSubtitleIndex(sub.index).toString()
|
||||
? subtitleHelper
|
||||
.getSourceSubtitleIndex(sub.index)
|
||||
.toString()
|
||||
: sub?.index.toString())
|
||||
}
|
||||
key={`subtitle-item-${idx}`}
|
||||
@@ -191,17 +167,18 @@ const DropdownView: React.FC<DropdownViewProps> = ({ showControls }) => {
|
||||
if (
|
||||
subtitleIndex ===
|
||||
(isOnTextSubtitle && sub.IsTextSubtitleStream
|
||||
? getSourceSubtitleIndex(sub.index).toString()
|
||||
? subtitleHelper
|
||||
.getSourceSubtitleIndex(sub.index)
|
||||
.toString()
|
||||
: sub?.index.toString())
|
||||
)
|
||||
return;
|
||||
|
||||
router.setParams({
|
||||
subtitleIndex: getSourceSubtitleIndex(
|
||||
sub.index
|
||||
).toString(),
|
||||
subtitleIndex: subtitleHelper
|
||||
.getSourceSubtitleIndex(sub.index)
|
||||
.toString(),
|
||||
});
|
||||
console.log("Got here");
|
||||
|
||||
if (sub.IsTextSubtitleStream && isOnTextSubtitle) {
|
||||
setSubtitleTrack && setSubtitleTrack(sub.index);
|
||||
|
||||
Reference in New Issue
Block a user