mirror of
https://github.com/p-stream/p-stream.git
synced 2026-03-11 09:45:33 +00:00
persist caption across sources
This commit is contained in:
parent
9009bf814c
commit
314f9574f6
4 changed files with 47 additions and 33 deletions
|
|
@ -294,7 +294,7 @@ export function CustomCaptionOption() {
|
|||
const { t } = useTranslation();
|
||||
const lang = usePlayerStore((s) => s.caption.selected?.language);
|
||||
const setCaption = usePlayerStore((s) => s.setCaption);
|
||||
const setCustomSubs = useSubtitleStore((s) => s.setCustomSubs);
|
||||
const setSubtitle = useSubtitleStore((s) => s.setSubtitle);
|
||||
const fileInput = useRef<HTMLInputElement>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ export function CustomCaptionOption() {
|
|||
srtData: converted,
|
||||
id: "custom-caption",
|
||||
});
|
||||
setCustomSubs();
|
||||
setSubtitle(true, "custom", "custom-caption");
|
||||
} catch (err) {
|
||||
setError(
|
||||
err instanceof Error
|
||||
|
|
@ -370,7 +370,7 @@ export function CustomCaptionOption() {
|
|||
export function PasteCaptionOption(props: { selected?: boolean }) {
|
||||
const { t } = useTranslation();
|
||||
const setCaption = usePlayerStore((s) => s.setCaption);
|
||||
const setCustomSubs = useSubtitleStore((s) => s.setCustomSubs);
|
||||
const setSubtitle = useSubtitleStore((s) => s.setSubtitle);
|
||||
const setDelay = useSubtitleStore((s) => s.setDelay);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
|
@ -409,7 +409,7 @@ export function PasteCaptionOption(props: { selected?: boolean }) {
|
|||
srtData: converted,
|
||||
id: "pasted-caption",
|
||||
});
|
||||
setCustomSubs();
|
||||
setSubtitle(true, parsedData.language, "pasted-caption");
|
||||
|
||||
// Set delay if included in the pasted data, otherwise reset to 0
|
||||
if (parsedData.delay !== undefined) {
|
||||
|
|
@ -476,7 +476,7 @@ export function CaptionsView({
|
|||
);
|
||||
const delay = useSubtitleStore((s) => s.delay);
|
||||
const appLanguage = useLanguageStore((s) => s.language);
|
||||
const setCustomSubs = useSubtitleStore((s) => s.setCustomSubs);
|
||||
const setSubtitle = useSubtitleStore((s) => s.setSubtitle);
|
||||
const matchScore = useCaptionMatchScore();
|
||||
|
||||
// Get combined caption list
|
||||
|
|
@ -580,7 +580,6 @@ export function CaptionsView({
|
|||
srtData: converted,
|
||||
id: "custom-caption",
|
||||
});
|
||||
setCustomSubs();
|
||||
} catch (err) {
|
||||
// Silently fail on drop - user can use the upload button for better error feedback
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
} from "../utils/captions";
|
||||
|
||||
export function useCaptions() {
|
||||
const setLanguage = useSubtitleStore((s) => s.setLanguage);
|
||||
const setSubtitle = useSubtitleStore((s) => s.setSubtitle);
|
||||
const enabled = useSubtitleStore((s) => s.enabled);
|
||||
const resetSubtitleSpecificSettings = useSubtitleStore(
|
||||
(s) => s.resetSubtitleSpecificSettings,
|
||||
|
|
@ -21,6 +21,9 @@ export function useCaptions() {
|
|||
const setCaption = usePlayerStore((s) => s.setCaption);
|
||||
const currentTranslateTask = usePlayerStore((s) => s.caption.translateTask);
|
||||
const lastSelectedLanguage = useSubtitleStore((s) => s.lastSelectedLanguage);
|
||||
const lastSelectedSubtitleId = useSubtitleStore(
|
||||
(s) => s.lastSelectedSubtitleId,
|
||||
);
|
||||
const setIsOpenSubtitles = useSubtitleStore((s) => s.setIsOpenSubtitles);
|
||||
|
||||
const captionList = usePlayerStore((s) => s.captionList);
|
||||
|
|
@ -53,7 +56,7 @@ export function useCaptions() {
|
|||
resetSubtitleSpecificSettings();
|
||||
}
|
||||
|
||||
setLanguage(caption.language);
|
||||
setSubtitle(true, caption.language, caption.id);
|
||||
|
||||
// Use native tracks for MP4 streams instead of custom rendering
|
||||
if (source?.type === "file" && enableNativeSubtitles) {
|
||||
|
|
@ -65,7 +68,7 @@ export function useCaptions() {
|
|||
},
|
||||
[
|
||||
setIsOpenSubtitles,
|
||||
setLanguage,
|
||||
setSubtitle,
|
||||
setCaption,
|
||||
resetSubtitleSpecificSettings,
|
||||
source,
|
||||
|
|
@ -135,14 +138,25 @@ export function useCaptions() {
|
|||
const disable = useCallback(async () => {
|
||||
setIsOpenSubtitles(false);
|
||||
setCaption(null);
|
||||
setLanguage(null);
|
||||
}, [setCaption, setLanguage, setIsOpenSubtitles]);
|
||||
setSubtitle(false);
|
||||
}, [setCaption, setSubtitle, setIsOpenSubtitles]);
|
||||
|
||||
const selectLastUsedLanguage = useCallback(async () => {
|
||||
if (lastSelectedSubtitleId) {
|
||||
const caption = captions.find((v) => v.id === lastSelectedSubtitleId);
|
||||
if (caption) return selectCaptionById(caption.id);
|
||||
}
|
||||
|
||||
const language = lastSelectedLanguage ?? "en";
|
||||
await selectLanguage(language);
|
||||
return true;
|
||||
}, [lastSelectedLanguage, selectLanguage]);
|
||||
}, [
|
||||
lastSelectedLanguage,
|
||||
selectLanguage,
|
||||
lastSelectedSubtitleId,
|
||||
captions,
|
||||
selectCaptionById,
|
||||
]);
|
||||
|
||||
const toggleLastUsed = useCallback(async () => {
|
||||
if (enabled) disable();
|
||||
|
|
|
|||
|
|
@ -26,12 +26,8 @@ export function useInitializeSource() {
|
|||
);
|
||||
const { selectLastUsedLanguageIfEnabled } = useCaptions();
|
||||
|
||||
// Only select subtitles on initial load, not when source changes
|
||||
const hasInitializedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (sourceIdentifier && !hasInitializedRef.current) {
|
||||
hasInitializedRef.current = true;
|
||||
if (sourceIdentifier) {
|
||||
selectLastUsedLanguageIfEnabled();
|
||||
}
|
||||
}, [sourceIdentifier, selectLastUsedLanguageIfEnabled]);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export interface SubtitleStore {
|
|||
};
|
||||
enabled: boolean;
|
||||
lastSelectedLanguage: string | null;
|
||||
lastSelectedSubtitleId: string | null;
|
||||
isOpenSubtitles: boolean;
|
||||
styling: SubtitleStyling;
|
||||
overrideCasing: boolean;
|
||||
|
|
@ -66,9 +67,12 @@ export interface SubtitleStore {
|
|||
showDelayIndicator: boolean;
|
||||
updateStyling(newStyling: Partial<SubtitleStyling>): void;
|
||||
resetStyling(): void;
|
||||
setLanguage(language: string | null): void;
|
||||
setSubtitle(
|
||||
enabled: boolean,
|
||||
language?: string | null,
|
||||
subtitleId?: string | null,
|
||||
): void;
|
||||
setIsOpenSubtitles(isOpenSubtitles: boolean): void;
|
||||
setCustomSubs(): void;
|
||||
setOverrideCasing(enabled: boolean): void;
|
||||
setDelay(delay: number): void;
|
||||
importSubtitleLanguage(lang: string | null): void;
|
||||
|
|
@ -84,6 +88,7 @@ export const useSubtitleStore = create(
|
|||
lastSelectedLanguage: null,
|
||||
},
|
||||
lastSelectedLanguage: null,
|
||||
lastSelectedSubtitleId: null,
|
||||
isOpenSubtitles: false,
|
||||
overrideCasing: false,
|
||||
delay: 0,
|
||||
|
|
@ -105,6 +110,11 @@ export const useSubtitleStore = create(
|
|||
s.overrideCasing = false;
|
||||
});
|
||||
},
|
||||
setIsOpenSubtitles(isOpenSubtitles) {
|
||||
set((s) => {
|
||||
s.isOpenSubtitles = isOpenSubtitles;
|
||||
});
|
||||
},
|
||||
updateStyling(newStyling) {
|
||||
set((s) => {
|
||||
if (newStyling.backgroundOpacity !== undefined)
|
||||
|
|
@ -153,21 +163,16 @@ export const useSubtitleStore = create(
|
|||
};
|
||||
});
|
||||
},
|
||||
setLanguage(lang) {
|
||||
setSubtitle(enabled, language, subtitleId) {
|
||||
set((s) => {
|
||||
s.enabled = !!lang;
|
||||
if (lang) s.lastSelectedLanguage = lang;
|
||||
});
|
||||
},
|
||||
setIsOpenSubtitles(isOpenSubtitles) {
|
||||
set((s) => {
|
||||
s.isOpenSubtitles = isOpenSubtitles;
|
||||
});
|
||||
},
|
||||
setCustomSubs() {
|
||||
set((s) => {
|
||||
s.enabled = true;
|
||||
s.lastSelectedLanguage = null;
|
||||
s.enabled = enabled;
|
||||
if (enabled) {
|
||||
s.lastSelectedLanguage = language ?? null;
|
||||
s.lastSelectedSubtitleId = subtitleId ?? null;
|
||||
} else {
|
||||
s.lastSelectedLanguage = null;
|
||||
s.lastSelectedSubtitleId = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
setOverrideCasing(enabled) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue