From 9e0a7f047cfa0ff825cebba7d62764b2401c394e Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Thu, 12 Dec 2024 15:44:53 +1100 Subject: [PATCH 1/5] Added new pulled state, to stop infinite callback for useEffect hookt in MediaContext --- .gitignore | 2 +- .vscode/settings.json | 17 ----------------- components/settings/MediaContext.tsx | 14 +++++++++++--- 3 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 27dc1f71..9807205f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ credentials.json *.apk *.ipa .continuerc.json - +.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4571e3a1..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - }, - "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true - }, - "[swift]": { - "editor.defaultFormatter": "sswg.swift-lang" - }, - "java.configuration.updateBuildConfiguration": "interactive", - "java.compile.nullAnalysis.mode": "automatic" -} diff --git a/components/settings/MediaContext.tsx b/components/settings/MediaContext.tsx index 64acd5d1..a1dd871f 100644 --- a/components/settings/MediaContext.tsx +++ b/components/settings/MediaContext.tsx @@ -1,6 +1,12 @@ import { Settings, useSettings } from "@/utils/atoms/settings"; import { useAtomValue } from "jotai"; -import React, { createContext, useContext, ReactNode, useEffect } from "react"; +import React, { + createContext, + useContext, + ReactNode, + useEffect, + useState, +} from "react"; import { apiAtom } from "@/providers/JellyfinProvider"; import { getLocalizationApi, getUserApi } from "@jellyfin/sdk/lib/utils/api"; import { @@ -31,6 +37,7 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { const [settings, updateSettings] = useSettings(); const api = useAtomValue(apiAtom); const queryClient = useQueryClient(); + const [pulledPreferences, setPulledPreferences] = useState(false); const updateSetingsWrapper = (update: Partial) => { const updateUserConfiguration = async ( @@ -111,7 +118,7 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { // Set default settings from user configuration.s useEffect(() => { - if (user && cultures) { + if (user && cultures.length != 0 && !pulledPreferences) { const userSubtitlePreference = user?.Configuration?.SubtitleLanguagePreference; const userAudioPreference = user?.Configuration?.AudioLanguagePreference; @@ -132,8 +139,9 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { rememberSubtitleSelections: user?.Configuration?.RememberSubtitleSelections, }); + setPulledPreferences(true); } - }, [user, cultures]); + }, [user, cultures, pulledPreferences]); if (!api) return null; From 67fb339d40bb4d844cd948ef18dd87b289d29e8a Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Thu, 12 Dec 2024 16:33:30 +1100 Subject: [PATCH 2/5] Added fix that fully stops the UseEffect hook from been calling indefinetly --- components/settings/MediaContext.tsx | 50 ++++++++++++---------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/components/settings/MediaContext.tsx b/components/settings/MediaContext.tsx index a1dd871f..c425b110 100644 --- a/components/settings/MediaContext.tsx +++ b/components/settings/MediaContext.tsx @@ -37,7 +37,6 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { const [settings, updateSettings] = useSettings(); const api = useAtomValue(apiAtom); const queryClient = useQueryClient(); - const [pulledPreferences, setPulledPreferences] = useState(false); const updateSetingsWrapper = (update: Partial) => { const updateUserConfiguration = async ( @@ -94,16 +93,14 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { queryKey: ["authUser"], queryFn: async () => { if (!api) return; - const userApi = await getUserApi(api).getCurrentUser(); return userApi.data; }, enabled: !!api, staleTime: 0, - refetchOnMount: true, }); - const { data: cultures = [] } = useQuery({ + const { data: cultures = [], isFetched: isCulturesFetched } = useQuery({ queryKey: ["cultures"], queryFn: async () => { if (!api) return []; @@ -112,36 +109,33 @@ export const MediaProvider = ({ children }: { children: ReactNode }) => { return cultures; }, enabled: !!api, - staleTime: 0, - refetchOnMount: true, + staleTime: 43200000, // 12 hours }); // Set default settings from user configuration.s useEffect(() => { - if (user && cultures.length != 0 && !pulledPreferences) { - const userSubtitlePreference = - user?.Configuration?.SubtitleLanguagePreference; - const userAudioPreference = user?.Configuration?.AudioLanguagePreference; + if (!user || cultures.length === 0) return; + const userSubtitlePreference = + user?.Configuration?.SubtitleLanguagePreference; + const userAudioPreference = user?.Configuration?.AudioLanguagePreference; - const subtitlePreference = cultures.find( - (x) => x.ThreeLetterISOLanguageName === userSubtitlePreference - ); - const audioPreference = cultures.find( - (x) => x.ThreeLetterISOLanguageName === userAudioPreference - ); + const subtitlePreference = cultures.find( + (x) => x.ThreeLetterISOLanguageName === userSubtitlePreference + ); + const audioPreference = cultures.find( + (x) => x.ThreeLetterISOLanguageName === userAudioPreference + ); - updateSettings({ - defaultSubtitleLanguage: subtitlePreference, - defaultAudioLanguage: audioPreference, - subtitleMode: user?.Configuration?.SubtitleMode, - playDefaultAudioTrack: user?.Configuration?.PlayDefaultAudioTrack, - rememberAudioSelections: user?.Configuration?.RememberAudioSelections, - rememberSubtitleSelections: - user?.Configuration?.RememberSubtitleSelections, - }); - setPulledPreferences(true); - } - }, [user, cultures, pulledPreferences]); + updateSettings({ + defaultSubtitleLanguage: subtitlePreference, + defaultAudioLanguage: audioPreference, + subtitleMode: user?.Configuration?.SubtitleMode, + playDefaultAudioTrack: user?.Configuration?.PlayDefaultAudioTrack, + rememberAudioSelections: user?.Configuration?.RememberAudioSelections, + rememberSubtitleSelections: + user?.Configuration?.RememberSubtitleSelections, + }); + }, [user, isCulturesFetched]); if (!api) return null; From ddfd9f6ce3edbfc08eef340c0f35679f5c11b3e1 Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Thu, 12 Dec 2024 16:36:17 +1100 Subject: [PATCH 3/5] Added vscode styling for pretier extension --- .gitignore | 1 - .vscode/settings.json | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 9807205f..45470905 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,3 @@ credentials.json *.apk *.ipa .continuerc.json -.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..22480b68 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[swift]": { + "editor.defaultFormatter": "sswg.swift-lang" + } +} From 72f64c71dd26feb691deafa2ac0a1dd1d2316a68 Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Thu, 12 Dec 2024 16:37:06 +1100 Subject: [PATCH 4/5] Added .vscode to git ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 45470905..33ed8e6d 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ credentials.json *.apk *.ipa .continuerc.json + +.vscode/ \ No newline at end of file From 0e29b8b671ec6a123b76188427ddcaac91b084c9 Mon Sep 17 00:00:00 2001 From: Alex Kim Date: Thu, 12 Dec 2024 21:41:22 +1100 Subject: [PATCH 5/5] Added temporary fix --- app/(auth)/player/transcoding-player.tsx | 11 +++++++-- components/video-player/controls/Controls.tsx | 2 +- .../dropdown/DropdownViewTranscoding.tsx | 24 ++++++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/app/(auth)/player/transcoding-player.tsx b/app/(auth)/player/transcoding-player.tsx index b72a9185..ce8a4c97 100644 --- a/app/(auth)/player/transcoding-player.tsx +++ b/app/(auth)/player/transcoding-player.tsx @@ -38,7 +38,6 @@ import Video, { SelectedTrackType, VideoRef, } from "react-native-video"; -import index from "../(tabs)/(home)"; const Player = () => { const api = useAtomValue(apiAtom); @@ -54,6 +53,7 @@ const Player = () => { const [ignoreSafeAreas, setIgnoreSafeAreas] = useState(false); const [isPlaying, setIsPlaying] = useState(false); const [isBuffering, setIsBuffering] = useState(true); + const [isVideoLoaded, setIsVideoLoaded] = useState(false); const setShowControls = useCallback((show: boolean) => { _setShowControls(show); @@ -117,7 +117,14 @@ const Player = () => { isLoading: isLoadingStreamUrl, isError: isErrorStreamUrl, } = useQuery({ - queryKey: ["stream-url", itemId, bitrateValue, mediaSourceId], + queryKey: [ + "stream-url", + itemId, + bitrateValue, + mediaSourceId, + subtitleIndex, + audioIndex, + ], queryFn: async () => { if (!api) { diff --git a/components/video-player/controls/Controls.tsx b/components/video-player/controls/Controls.tsx index bedfeb31..bd3ea18a 100644 --- a/components/video-player/controls/Controls.tsx +++ b/components/video-player/controls/Controls.tsx @@ -318,7 +318,7 @@ export const Controls: React.FC = ({ const minutes = Math.floor((progressInSeconds % 3600) / 60); const seconds = progressInSeconds % 60; setTime({ hours, minutes, seconds }); - }, 10), + }, 3), [] ); diff --git a/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx b/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx index a555616a..515092a6 100644 --- a/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx +++ b/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx @@ -34,10 +34,15 @@ const DropdownView: React.FC = ({ showControls }) => { }>(); // Either its on a text subtitle or its on not on any subtitle therefore it should show all the embedded HLS subtitles. - const isOnTextSubtitle = - mediaSource?.MediaStreams?.find( - (x) => x.Index === parseInt(subtitleIndex) && x.IsTextSubtitleStream - ) || subtitleIndex === "-1"; + + const isOnTextSubtitle = useMemo(() => { + const res = Boolean( + mediaSource?.MediaStreams?.find( + (x) => x.Index === parseInt(subtitleIndex) && x.IsTextSubtitleStream + ) || subtitleIndex === "-1" + ); + return res; + }, []); const allSubs = mediaSource?.MediaStreams?.filter((x) => x.Type === "Subtitle") ?? []; @@ -76,8 +81,6 @@ const DropdownView: React.FC = ({ showControls }) => { } }); - console.log("sortedSubtitles", sortedSubtitles); - return [disableSubtitle, ...sortedSubtitles]; } @@ -90,7 +93,7 @@ const DropdownView: React.FC = ({ showControls }) => { return [disableSubtitle, ...transcodedSubtitle]; }, [item, isVideoLoaded, subtitleTracks, mediaSource?.MediaStreams]); - const ChangeTranscodingSubtitle = useCallback( + const changeToImageBasedSub = useCallback( (subtitleIndex: number) => { const queryParams = new URLSearchParams({ itemId: item.Id ?? "", // Ensure itemId is a string @@ -180,7 +183,7 @@ const DropdownView: React.FC = ({ showControls }) => { = ({ showControls }) => { console.log("sub", sub); if ( subtitleIndex === - (sub.IsTextSubtitleStream && isOnTextSubtitle + (isOnTextSubtitle && sub.IsTextSubtitleStream ? getSourceSubtitleIndex(sub.index).toString() : sub?.index.toString()) ) @@ -206,8 +209,7 @@ const DropdownView: React.FC = ({ showControls }) => { setSubtitleTrack && setSubtitleTrack(sub.index); return; } - console.log("ChangeTranscodingSubtitle", subtitleIndex); - ChangeTranscodingSubtitle(sub.index); + changeToImageBasedSub(sub.index); }} >