Merge remote-tracking branch 'origin/develop' into feat/tv-interface

Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
This commit is contained in:
Lance Chant
2026-05-28 09:04:32 +02:00
25 changed files with 2321 additions and 2318 deletions

View File

@@ -61,7 +61,10 @@ export default function Page() {
setLoading(true);
try {
logsFile.write(JSON.stringify(filteredLogs));
await Sharing.shareAsync(logsFile.uri, { mimeType: "txt", UTI: "txt" });
await Sharing.shareAsync(logsFile.uri, {
mimeType: "text/plain",
UTI: "public.plain-text",
});
} catch (e: any) {
writeErrorLog("Something went wrong attempting to export", e);
} finally {

View File

@@ -53,6 +53,7 @@ import { OfflineModeProvider } from "@/providers/OfflineModeProvider";
import { getSubtitlesForItem } from "@/utils/atoms/downloadedSubtitles";
import { useSettings } from "@/utils/atoms/settings";
import { getDefaultPlaySettings } from "@/utils/jellyfin/getDefaultPlaySettings";
import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import {
getMpvAudioId,
@@ -563,6 +564,31 @@ export default function page() {
],
);
/** Prepare metadata for iOS native media controls (Control Center, Lock Screen) */
const nowPlayingMetadata = useMemo(() => {
if (!item || !api) return undefined;
const artworkUri = getPrimaryImageUrl({
api,
item,
quality: 90,
width: 500,
});
return {
title: item.Name || "",
artist:
item.Type === "Episode"
? item.SeriesName || ""
: item.AlbumArtist || "",
albumTitle:
item.Type === "Episode" && item.SeasonName
? item.SeasonName
: undefined,
artworkUri: artworkUri || undefined,
};
}, [item, api]);
/** Build video source config for MPV */
const videoSource = useMemo<MpvVideoSource | undefined>(() => {
if (!stream?.url) return undefined;
@@ -1218,6 +1244,7 @@ export default function page() {
ref={videoRef}
source={videoSource}
style={{ width: "100%", height: "100%" }}
nowPlayingMetadata={nowPlayingMetadata}
onProgress={onProgress}
onPlaybackStateChange={onPlaybackStateChanged}
onLoad={() => setIsVideoLoaded(true)}