fix: tv playback (#820)

Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
Signed-off-by: lancechant <13349722+lancechant@users.noreply.github.com>
Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com>
Co-authored-by: Uruk <contact@uruk.dev>
Co-authored-by: Gauvain <68083474+Gauvino@users.noreply.github.com>
This commit is contained in:
lance chant
2025-08-07 10:12:40 +02:00
committed by GitHub
parent 89fd7f0e34
commit 89b34eddc1
68 changed files with 1412 additions and 1786 deletions

View File

@@ -16,34 +16,46 @@ export type HapticFeedbackType =
export const useHaptic = (feedbackType: HapticFeedbackType = "selection") => {
const [settings] = useSettings();
const isTv = Platform.isTV;
const isDisabled =
isTv ||
!Haptics ||
settings?.disableHapticFeedback ||
Platform.OS === "web";
const createHapticHandler = useCallback(
(type: typeof Haptics.ImpactFeedbackStyle) => {
return Platform.OS === "web" || Platform.isTV
? () => {}
: () => Haptics.impactAsync(type);
if (!Haptics || !type) return () => {};
return () => Haptics.impactAsync(type);
},
[],
);
const createNotificationFeedback = useCallback(
(type: typeof Haptics.NotificationFeedbackType) => {
return Platform.OS === "web" || Platform.isTV
? () => {}
: () => Haptics.notificationAsync(type);
if (!Haptics || !type) return () => {};
return () => Haptics.notificationAsync(type);
},
[],
);
const hapticHandlers = useMemo(
() => ({
const hapticHandlers = useMemo(() => {
if (!Haptics) {
return {
light: () => {},
medium: () => {},
heavy: () => {},
selection: () => {},
success: () => {},
warning: () => {},
error: () => {},
};
}
return {
light: createHapticHandler(Haptics.ImpactFeedbackStyle.Light),
medium: createHapticHandler(Haptics.ImpactFeedbackStyle.Medium),
heavy: createHapticHandler(Haptics.ImpactFeedbackStyle.Heavy),
selection:
Platform.OS === "web" || Platform.isTV
? () => {}
: Haptics.selectionAsync,
selection: Haptics.selectionAsync,
success: createNotificationFeedback(
Haptics.NotificationFeedbackType.Success,
),
@@ -51,16 +63,11 @@ export const useHaptic = (feedbackType: HapticFeedbackType = "selection") => {
Haptics.NotificationFeedbackType.Warning,
),
error: createNotificationFeedback(Haptics.NotificationFeedbackType.Error),
}),
[createHapticHandler, createNotificationFeedback],
);
if (isTv) {
return () => {};
}
};
}, [createHapticHandler, createNotificationFeedback]);
if (settings?.disableHapticFeedback) {
return () => {};
}
return hapticHandlers[feedbackType];
return isDisabled ? () => {} : hapticHandlers[feedbackType];
};

View File

@@ -2,6 +2,7 @@ import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { useAtom, useAtomValue } from "jotai";
import { useEffect, useMemo } from "react";
import { Platform } from "react-native";
import { getColors, ImageColorsResult } from "react-native-image-colors";
import { apiAtom } from "@/providers/JellyfinProvider";
import {
adjustToNearBlack,
@@ -12,9 +13,6 @@ import {
import { getItemImage } from "@/utils/getItemImage";
import { storage } from "@/utils/mmkv";
// import { getColors } from "react-native-image-colors";
const Colors = !Platform.isTV ? require("react-native-image-colors") : null;
/**
* Custom hook to extract and manage image colors for a given item.
*
@@ -65,48 +63,45 @@ export const useImageColors = ({
return;
}
Colors.getColors(source.uri, {
// Extract colors from the image
getColors(source.uri, {
fallback: "#fff",
cache: false,
})
.then(
(colors: {
platform: string;
dominant: string;
vibrant: string;
detail: string;
primary: string;
}) => {
let primary = "#fff";
let text = "#000";
let backup = "#fff";
.then((colors: ImageColorsResult) => {
let primary = "#fff";
let text = "#000";
let backup = "#fff";
if (colors.platform === "android") {
primary = colors.dominant;
backup = colors.vibrant;
} else if (colors.platform === "ios") {
primary = colors.detail;
backup = colors.primary;
}
// Select the appropriate color based on the platform
if (colors.platform === "android") {
primary = colors.dominant;
backup = colors.vibrant;
} else if (colors.platform === "ios") {
primary = colors.detail;
backup = colors.primary;
}
if (primary && isCloseToBlack(primary)) {
if (backup && !isCloseToBlack(backup)) primary = backup;
primary = adjustToNearBlack(primary);
}
// Adjust the primary color if it's too close to black
if (primary && isCloseToBlack(primary)) {
if (backup && !isCloseToBlack(backup)) primary = backup;
primary = adjustToNearBlack(primary);
}
if (primary) text = calculateTextColor(primary);
// Calculate the text color based on the primary color
if (primary) text = calculateTextColor(primary);
setPrimaryColor({
primary,
text,
});
setPrimaryColor({
primary,
text,
});
if (source.uri && primary) {
storage.set(`${source.uri}-primary`, primary);
storage.set(`${source.uri}-text`, text);
}
},
)
// Cache the colors in storage
if (source.uri && primary) {
storage.set(`${source.uri}-primary`, primary);
storage.set(`${source.uri}-text`, text);
}
})
.catch((error: any) => {
console.error("Error getting colors", error);
});

View File

@@ -14,12 +14,6 @@ interface TrickplayData {
ThumbnailCount?: number;
}
interface TrickplayInfo {
resolution: string;
aspectRatio: number;
data: TrickplayData;
}
interface TrickplayUrl {
x: number;
y: number;