Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
0361d9bcc2 chore(deps): Update dependency @biomejs/biome to v2.4.14 2026-05-04 19:44:11 +00:00
6 changed files with 37 additions and 86 deletions

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"$schema": "https://biomejs.dev/schemas/2.4.14/schema.json",
"files": {
"includes": [
"**/*",

View File

@@ -96,7 +96,7 @@
},
"devDependencies": {
"@babel/core": "7.28.6",
"@biomejs/biome": "2.3.11",
"@biomejs/biome": "2.4.14",
"@react-native-community/cli": "20.1.1",
"@react-native-tvos/config-tv": "0.1.4",
"@types/jest": "29.5.14",
@@ -308,23 +308,23 @@
"@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="],
"@biomejs/biome": ["@biomejs/biome@2.3.11", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.11", "@biomejs/cli-darwin-x64": "2.3.11", "@biomejs/cli-linux-arm64": "2.3.11", "@biomejs/cli-linux-arm64-musl": "2.3.11", "@biomejs/cli-linux-x64": "2.3.11", "@biomejs/cli-linux-x64-musl": "2.3.11", "@biomejs/cli-win32-arm64": "2.3.11", "@biomejs/cli-win32-x64": "2.3.11" }, "bin": { "biome": "bin/biome" } }, "sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ=="],
"@biomejs/biome": ["@biomejs/biome@2.4.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.14", "@biomejs/cli-darwin-x64": "2.4.14", "@biomejs/cli-linux-arm64": "2.4.14", "@biomejs/cli-linux-arm64-musl": "2.4.14", "@biomejs/cli-linux-x64": "2.4.14", "@biomejs/cli-linux-x64-musl": "2.4.14", "@biomejs/cli-win32-arm64": "2.4.14", "@biomejs/cli-win32-x64": "2.4.14" }, "bin": { "biome": "bin/biome" } }, "sha512-TmAvxOEgrpLypzVGJ8FulIZnlyA9TxrO1hyqYrCz9r+bwma9xXxuLA5IuYnj55XQneFx460KjRbx6SWGLkg3bQ=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XvgoE9XOawUOQPdmvs4J7wPhi/DLwSCGks3AlPJDmh34O0awRTqCED1HRcRDdpf1Zrp4us4MGOOdIxNpbqNF5Q=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-jE7hKBCFhOx3uUh+ZkWBfOHxAcILPfhFplNkuID/eZeSTLHzfZzoZxW8fbqY9xXRnPi7jGNAf1iPVR+0yWsM/Q=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-2TELhZnW5RSLL063l9rc5xLpA0ZIw0Ccwy/0q384rvNAgFw3yI76bd59547yxowdQr5MNPET/xDLrLuvgSeeWQ=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-/z+6gqAqqUQTHazwStxSXKHg9b8UvqBmDFRp+c4wYbq2KXhELQDon9EoC9RpmQ8JWkqQx/lIUy/cs+MhzDZp6A=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.14", "", { "os": "linux", "cpu": "x64" }, "sha512-zHrlQZDBDUz4OLAraYpWKcnLS6HOewBFWYOzY91d1ZjdqZwibOyb6BEu6WuWLugyo0P3riCmsbV9UqV1cSXwQg=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.14", "", { "os": "linux", "cpu": "x64" }, "sha512-R6BWgJdQOwW9ulJatuTVrQkjnODjqHZkKNOqb1sz++3Noe5LYd0i3PchnOBUCYAPHoPWHhjJqbdZlHEu0hpjdA=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-M3EH5hqOI/F/FUA2u4xcLoUgmxd218mvuj/6JL7Hv2toQvr2/AdOvKSpGkoRuWFCtQPVa+ZqkEV3Q5xBA9+XSA=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.11", "", { "os": "win32", "cpu": "x64" }, "sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.14", "", { "os": "win32", "cpu": "x64" }, "sha512-WL0EG5qE+EAKomGXbf2g6VnSKJhTL3tXC0QRzWRwA5VpjxNYa6H4P7ZWfymbGE4IhZZQi1KXQ2R0YjwInmz2fA=="],
"@bottom-tabs/react-navigation": ["@bottom-tabs/react-navigation@1.1.0", "", { "dependencies": { "color": "^5.0.0" }, "peerDependencies": { "@react-navigation/native": ">=7", "react": "*", "react-native": "*", "react-native-bottom-tabs": "*" } }, "sha512-+4YppCodABcSNIgJiq95QUQ+3ClVBG+rLG3WmYI0+/nbxqKbCz6luFBep4KFOj98Iplj1JY2Ki6ix8CcOZVQ/Q=="],
@@ -1696,7 +1696,7 @@
"react-native-text-ticker": ["react-native-text-ticker@1.15.0", "", {}, "sha512-d/uK+PIOhsYMy1r8h825iq/nADiHsabz3WMbRJSnkpQYn+K9aykUAXRRhu8ZbTAzk4CgnUWajJEFxS5ZDygsdg=="],
"react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#003afd0", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-003afd0"],
"react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#003afd0", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-003afd0", "sha512-HR7BaMDMBhQ4xAy5XeQEkT0fBosWw2x9+X2QOD4buocxuX03D770LaRKm5rgQ/qDzchr92KW7+d8fISI14fRLA=="],
"react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="],

View File

@@ -204,10 +204,7 @@ export const OtherSettings: React.FC = () => {
}
/>
</ListItem>
<ListItem
title={t("home.settings.other.max_auto_play_episode_count")}
disabled={pluginSettings?.maxAutoPlayEpisodeCount?.locked}
>
<ListItem title={t("home.settings.other.max_auto_play_episode_count")}>
<PlatformDropdown
groups={autoPlayEpisodeOptions}
trigger={

View File

@@ -229,10 +229,7 @@ export const PlaybackControlsSettings: React.FC = () => {
<ListItem
title={t("home.settings.other.max_auto_play_episode_count")}
disabled={
!settings.autoPlayNextEpisode ||
pluginSettings?.maxAutoPlayEpisodeCount?.locked
}
disabled={!settings.autoPlayNextEpisode}
>
<PlatformDropdown
groups={autoPlayEpisodeOptions}

View File

@@ -116,7 +116,7 @@
},
"devDependencies": {
"@babel/core": "7.28.6",
"@biomejs/biome": "2.3.11",
"@biomejs/biome": "2.4.14",
"@react-native-community/cli": "20.1.1",
"@react-native-tvos/config-tv": "0.1.4",
"@types/jest": "29.5.14",

View File

@@ -6,7 +6,6 @@ import {
type SortOrder,
SubtitlePlaybackMode,
} from "@jellyfin/sdk/lib/generated-client";
import { t } from "i18next";
import { atom, useAtom, useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo } from "react";
import { BITRATES, type Bitrate } from "@/components/BitrateSelector";
@@ -122,46 +121,6 @@ export interface MaxAutoPlayEpisodeCount {
value: number;
}
/**
* The plugin may send object-typed settings as plain primitives.
* Resolve to the proper option object from the available choices.
*/
const normalizePluginValue = (
settingsKey: keyof Settings,
value: unknown,
): unknown => {
if (typeof value !== "object" || value === null) {
const defaultVal = defaultValues[settingsKey];
if (
typeof defaultVal === "object" &&
defaultVal !== null &&
"key" in defaultVal &&
"value" in defaultVal
) {
// defaultBitrate needs a lookup because its keys are human-readable
// (e.g. "8 Mb/s") that can't be derived from the raw value (e.g. 8000000).
// Other { key, value } settings like maxAutoPlayEpisodeCount work with
// the fallback because their keys are just String(value) (e.g. "5").
if (settingsKey === "defaultBitrate") {
const match = BITRATES.find(
(b) => b.key === value || b.value === value,
);
if (match) return match;
}
// maxAutoPlayEpisodeCount: 0 is invalid (breaks autoplay), clamp to -1
// -1 key must match the translated dropdown label so the UI shows "Disabled"
if (
settingsKey === "maxAutoPlayEpisodeCount" &&
(value === 0 || value === -1)
) {
return { key: t("home.settings.other.disabled"), value: -1 };
}
return { key: String(value), value };
}
}
return value;
};
export type HomeSectionLatestResolver = {
parentId?: string;
limit?: number;
@@ -403,7 +362,7 @@ export const useSettings = () => {
);
const refreshStreamyfinPluginSettings = useCallback(
async (_forceOverride = false) => {
async (forceOverride = false) => {
if (!api) {
return;
}
@@ -416,17 +375,20 @@ export const useSettings = () => {
);
setPluginSettings(newPluginSettings);
// Apply locked plugin values to settings (unlocked values are handled
// by the settings memo, which respects user customizations)
// Apply plugin values to settings
if (newPluginSettings && _settings) {
const updates: Partial<Settings> = {};
for (const [key, setting] of Object.entries(newPluginSettings)) {
if (setting?.locked) {
if (setting && !setting.locked && setting.value !== undefined) {
const settingsKey = key as keyof Settings;
(updates as any)[settingsKey] = normalizePluginValue(
settingsKey,
setting.value,
);
// Apply if forceOverride is true, or if user hasn't explicitly set this value
if (
forceOverride ||
_settings[settingsKey] === undefined ||
_settings[settingsKey] === ""
) {
(updates as any)[settingsKey] = setting.value;
}
}
}
@@ -478,31 +440,26 @@ export const useSettings = () => {
// If admin sets locked to false but provides a value,
// use user settings first and fallback on admin setting if required.
const settings: Settings = useMemo(() => {
const _unlockedPluginDefaults: Partial<Settings> = {};
const unlockedPluginDefaults: Partial<Settings> = {};
const overrideSettings = Object.entries(pluginSettings ?? {}).reduce<
Partial<Settings>
>((acc, [key, setting]) => {
if (setting) {
let { value } = setting;
const { locked } = setting;
const { value, locked } = setting;
const settingsKey = key as keyof Settings;
// Normalize object-typed settings from plugin (plain primitive → { key, value })
value = normalizePluginValue(settingsKey, value);
// For unlocked settings: use plugin value unless user explicitly
// customized (their saved value differs from the default)
const userVal = _settings?.[settingsKey];
const defaultVal = defaultValues[settingsKey];
const userCustomized =
userVal !== undefined &&
JSON.stringify(userVal) !== JSON.stringify(defaultVal);
// Make sure we override default settings with plugin settings when they are not locked.
if (
!locked &&
value !== undefined &&
_settings?.[settingsKey] !== value
) {
(unlockedPluginDefaults as any)[settingsKey] = value;
}
(acc as any)[settingsKey] = locked
? value
: userCustomized
? userVal
: value;
: (_settings?.[settingsKey] ?? value);
}
return acc;
}, {});