chore: Apply linting rules and add git hok (#611)

Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com>
This commit is contained in:
lostb1t
2025-03-16 18:01:12 +01:00
committed by GitHub
parent 2688e1b981
commit 92513e234f
268 changed files with 9197 additions and 8394 deletions

View File

@@ -4,7 +4,7 @@ import {
} from "@/packages/expo-screen-orientation";
function orientationToOrientationLock(
orientation: Orientation
orientation: Orientation,
): OrientationLock {
switch (orientation) {
case Orientation.PORTRAIT_UP:

View File

@@ -4,17 +4,20 @@ import {
MediaStatus,
} from "@/utils/jellyseerr/server/constants/media";
import {
hasPermission,
Permission,
hasPermission,
} from "@/utils/jellyseerr/server/lib/permissions";
import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
import type {
MovieResult,
TvResult,
} from "@/utils/jellyseerr/server/models/Search";
import { useMemo } from "react";
import MediaRequest from "../jellyseerr/server/entity/MediaRequest";
import { MovieDetails } from "../jellyseerr/server/models/Movie";
import { TvDetails } from "../jellyseerr/server/models/Tv";
import type MediaRequest from "../jellyseerr/server/entity/MediaRequest";
import type { MovieDetails } from "../jellyseerr/server/models/Movie";
import type { TvDetails } from "../jellyseerr/server/models/Tv";
export const useJellyseerrCanRequest = (
item?: MovieResult | TvResult | MovieDetails | TvDetails
item?: MovieResult | TvResult | MovieDetails | TvDetails,
) => {
const { jellyseerrUser } = useJellyseerr();
@@ -25,7 +28,7 @@ export const useJellyseerrCanRequest = (
item?.mediaInfo?.requests?.some(
(r: MediaRequest) =>
r.status == MediaRequestStatus.PENDING ||
r.status == MediaRequestStatus.APPROVED
r.status == MediaRequestStatus.APPROVED,
) ||
item.mediaInfo?.status === MediaStatus.AVAILABLE ||
item.mediaInfo?.status === MediaStatus.BLACKLISTED ||
@@ -42,26 +45,21 @@ export const useJellyseerrCanRequest = (
: Permission.REQUEST_TV,
],
jellyseerrUser.permissions,
{ type: "or" }
{ type: "or" },
);
return userHasPermission && !canNotRequest;
}, [item, jellyseerrUser]);
const hasAdvancedRequestPermission = useMemo(() => {
if (!jellyseerrUser) return false;
if (!jellyseerrUser) return false;
return hasPermission(
[
Permission.REQUEST_ADVANCED,
Permission.MANAGE_REQUESTS
],
jellyseerrUser.permissions,
{type: 'or'}
)
},
[jellyseerrUser]
);
return hasPermission(
[Permission.REQUEST_ADVANCED, Permission.MANAGE_REQUESTS],
jellyseerrUser.permissions,
{ type: "or" },
);
}, [jellyseerrUser]);
return [canRequest, hasAdvancedRequestPermission];
};

View File

@@ -93,7 +93,7 @@ export const sortByPreferenceAtom = atomWithStorage<SortPreference>(
removeItem: (key) => {
storage.delete(key);
},
}
},
);
export const sortOrderPreferenceAtom = atomWithStorage<SortOrderPreference>(
@@ -110,19 +110,19 @@ export const sortOrderPreferenceAtom = atomWithStorage<SortOrderPreference>(
removeItem: (key) => {
storage.delete(key);
},
}
},
);
export const getSortByPreference = (
libraryId: string,
preferences: SortPreference
preferences: SortPreference,
) => {
return preferences?.[libraryId] || null;
};
export const getSortOrderPreference = (
libraryId: string,
preferences: SortOrderPreference
preferences: SortOrderPreference,
) => {
return preferences?.[libraryId] || null;
};

View File

@@ -2,5 +2,5 @@ import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { atom } from "jotai";
export const orientationAtom = atom<number>(
ScreenOrientation.OrientationLock.PORTRAIT_UP
ScreenOrientation.OrientationLock.PORTRAIT_UP,
);

View File

@@ -7,9 +7,9 @@ interface ThemeColors {
export const calculateTextColor = (backgroundColor: string): string => {
// Convert hex to RGB
const r = parseInt(backgroundColor.slice(1, 3), 16);
const g = parseInt(backgroundColor.slice(3, 5), 16);
const b = parseInt(backgroundColor.slice(5, 7), 16);
const r = Number.parseInt(backgroundColor.slice(1, 3), 16);
const g = Number.parseInt(backgroundColor.slice(3, 5), 16);
const b = Number.parseInt(backgroundColor.slice(5, 7), 16);
// Calculate perceived brightness
// Using the formula: (R * 299 + G * 587 + B * 114) / 1000
@@ -47,9 +47,9 @@ const calculateRelativeLuminance = (rgb: number[]): number => {
};
export const isCloseToBlack = (color: string): boolean => {
const r = parseInt(color.slice(1, 3), 16);
const g = parseInt(color.slice(3, 5), 16);
const b = parseInt(color.slice(5, 7), 16);
const r = Number.parseInt(color.slice(1, 3), 16);
const g = Number.parseInt(color.slice(3, 5), 16);
const b = Number.parseInt(color.slice(5, 7), 16);
// Check if the color is very dark (close to black)
return r < 20 && g < 20 && b < 20;

View File

@@ -1,9 +1,9 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { processesAtom } from "@/providers/DownloadProvider";
import { useSettings } from "@/utils/atoms/settings";
import type { JobStatus } from "@/utils/optimize-server";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { atom, useAtom } from "jotai";
import { useEffect } from "react";
import {JobStatus} from "@/utils/optimize-server";
import {processesAtom} from "@/providers/DownloadProvider";
import {useSettings} from "@/utils/atoms/settings";
export interface Job {
id: string;
@@ -24,7 +24,7 @@ export const queueActions = {
processJob: async (
queue: Job[],
setQueue: (update: Job[]) => void,
setProcessing: (processing: boolean) => void
setProcessing: (processing: boolean) => void,
) => {
const [job, ...rest] = queue;
@@ -45,7 +45,7 @@ export const queueActions = {
},
clear: (
setQueue: (update: Job[]) => void,
setProcessing: (processing: boolean) => void
setProcessing: (processing: boolean) => void,
) => {
setQueue([]);
setProcessing(false);
@@ -59,7 +59,12 @@ export const useJobProcessor = () => {
const [settings] = useSettings();
useEffect(() => {
if (!running && queue.length > 0 && settings && processes.length < settings?.remuxConcurrentLimit) {
if (
!running &&
queue.length > 0 &&
settings &&
processes.length < settings?.remuxConcurrentLimit
) {
console.info("Processing queue", queue);
queueActions.processJob(queue, setQueue, setRunning);
}

View File

@@ -1,20 +1,20 @@
import { BITRATES, type Bitrate } from "@/components/BitrateSelector";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { apiAtom } from "@/providers/JellyfinProvider";
import { Video } from "@/utils/jellyseerr/server/models/Movie";
import { writeInfoLog } from "@/utils/log";
import {
type BaseItemKind,
type CultureDto,
type ItemFilter,
type ItemSortBy,
type SortOrder,
SubtitlePlaybackMode,
} from "@jellyfin/sdk/lib/generated-client";
import { atom, useAtom, useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo } from "react";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { storage } from "../mmkv";
import { Platform } from "react-native";
import {
CultureDto,
SubtitlePlaybackMode,
ItemSortBy,
SortOrder,
BaseItemKind,
ItemFilter,
} from "@jellyfin/sdk/lib/generated-client";
import { Bitrate, BITRATES } from "@/components/BitrateSelector";
import { apiAtom } from "@/providers/JellyfinProvider";
import { writeInfoLog } from "@/utils/log";
import { Video } from "@/utils/jellyseerr/server/models/Movie";
import { storage } from "../mmkv";
const STREAMYFIN_PLUGIN_ID = "1e9e5d386e6746158719e98a5c34f004";
const STREAMYFIN_PLUGIN_SETTINGS = "STREAMYFIN_PLUGIN_SETTINGS";
@@ -26,17 +26,30 @@ export type DownloadOption = {
value: DownloadQuality;
};
export const ScreenOrientationEnum: Record<ScreenOrientation.OrientationLock, string> = {
[ScreenOrientation.OrientationLock.DEFAULT]: "home.settings.other.orientations.DEFAULT",
[ScreenOrientation.OrientationLock.ALL]: "home.settings.other.orientations.ALL",
[ScreenOrientation.OrientationLock.PORTRAIT]: "home.settings.other.orientations.PORTRAIT",
[ScreenOrientation.OrientationLock.PORTRAIT_UP]: "home.settings.other.orientations.PORTRAIT_UP",
[ScreenOrientation.OrientationLock.PORTRAIT_DOWN]: "home.settings.other.orientations.PORTRAIT_DOWN",
[ScreenOrientation.OrientationLock.LANDSCAPE]: "home.settings.other.orientations.LANDSCAPE",
[ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: "home.settings.other.orientations.LANDSCAPE_LEFT",
[ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: "home.settings.other.orientations.LANDSCAPE_RIGHT",
[ScreenOrientation.OrientationLock.OTHER]: "home.settings.other.orientations.OTHER",
[ScreenOrientation.OrientationLock.UNKNOWN]: "home.settings.other.orientations.UNKNOWN",
export const ScreenOrientationEnum: Record<
ScreenOrientation.OrientationLock,
string
> = {
[ScreenOrientation.OrientationLock.DEFAULT]:
"home.settings.other.orientations.DEFAULT",
[ScreenOrientation.OrientationLock.ALL]:
"home.settings.other.orientations.ALL",
[ScreenOrientation.OrientationLock.PORTRAIT]:
"home.settings.other.orientations.PORTRAIT",
[ScreenOrientation.OrientationLock.PORTRAIT_UP]:
"home.settings.other.orientations.PORTRAIT_UP",
[ScreenOrientation.OrientationLock.PORTRAIT_DOWN]:
"home.settings.other.orientations.PORTRAIT_DOWN",
[ScreenOrientation.OrientationLock.LANDSCAPE]:
"home.settings.other.orientations.LANDSCAPE",
[ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]:
"home.settings.other.orientations.LANDSCAPE_LEFT",
[ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]:
"home.settings.other.orientations.LANDSCAPE_RIGHT",
[ScreenOrientation.OrientationLock.OTHER]:
"home.settings.other.orientations.OTHER",
[ScreenOrientation.OrientationLock.UNKNOWN]:
"home.settings.other.orientations.UNKNOWN",
};
export const DownloadOptions: DownloadOption[] = [
@@ -102,8 +115,8 @@ export type HomeSectionNextUpResolver = {
export enum VideoPlayer {
// NATIVE, //todo: changes will make this a lot more easier to implement if we want. delete if not wanted
VLC_3,
VLC_4,
VLC_3 = 0,
VLC_4 = 1,
}
export type Settings = {
@@ -201,7 +214,8 @@ const defaultValues: Settings = {
const loadSettings = (): Partial<Settings> => {
try {
const jsonValue = storage.getString("settings");
const loadedValues: Partial<Settings> = jsonValue != null ? JSON.parse(jsonValue) : {};
const loadedValues: Partial<Settings> =
jsonValue != null ? JSON.parse(jsonValue) : {};
return loadedValues;
} catch (error) {
@@ -223,7 +237,9 @@ const saveSettings = (settings: Settings) => {
};
export const settingsAtom = atom<Partial<Settings> | null>(null);
export const pluginSettingsAtom = atom(storage.get<PluginLockableSettings>(STREAMYFIN_PLUGIN_SETTINGS));
export const pluginSettingsAtom = atom(
storage.get<PluginLockableSettings>(STREAMYFIN_PLUGIN_SETTINGS),
);
export const useSettings = () => {
const api = useAtomValue(apiAtom);
@@ -242,7 +258,7 @@ export const useSettings = () => {
storage.setAny(STREAMYFIN_PLUGIN_SETTINGS, settings);
_setPluginSettings(settings);
},
[_setPluginSettings]
[_setPluginSettings],
);
const refreshStreamyfinPluginSettings = useCallback(async () => {
@@ -252,7 +268,7 @@ export const useSettings = () => {
writeInfoLog(`Got remote settings: ${data?.settings}`);
return data?.settings;
},
(err) => undefined
(err) => undefined,
);
setPluginSettings(settings);
return settings;
@@ -260,11 +276,17 @@ export const useSettings = () => {
const updateSettings = (update: Partial<Settings>) => {
if (!_settings) return;
const hasChanges = Object.entries(update).some(([key, value]) => _settings[key as keyof Settings] !== value);
const hasChanges = Object.entries(update).some(
([key, value]) => _settings[key as keyof Settings] !== value,
);
if (hasChanges) {
// Merge default settings, current settings, and updates to ensure all required properties exist
const newSettings = { ...defaultValues, ..._settings, ...update } as Settings;
const newSettings = {
...defaultValues,
..._settings,
...update,
} as Settings;
setSettings(newSettings);
saveSettings(newSettings);
}
@@ -275,24 +297,33 @@ export const useSettings = () => {
// use user settings first and fallback on admin setting if required.
const settings: Settings = useMemo(() => {
let unlockedPluginDefaults = {} as Settings;
const overrideSettings = Object.entries(pluginSettings || {}).reduce((acc, [key, setting]) => {
if (setting) {
const { value, locked } = setting;
const overrideSettings = Object.entries(pluginSettings || {}).reduce(
(acc, [key, setting]) => {
if (setting) {
const { value, locked } = setting;
// Make sure we override default settings with plugin settings when they are not locked.
// Admin decided what users defaults should be and grants them the ability to change them too.
if (locked === false && value && _settings?.[key as keyof Settings] !== value) {
unlockedPluginDefaults = Object.assign(unlockedPluginDefaults, {
[key as keyof Settings]: value,
// Make sure we override default settings with plugin settings when they are not locked.
// Admin decided what users defaults should be and grants them the ability to change them too.
if (
locked === false &&
value &&
_settings?.[key as keyof Settings] !== value
) {
unlockedPluginDefaults = Object.assign(unlockedPluginDefaults, {
[key as keyof Settings]: value,
});
}
acc = Object.assign(acc, {
[key]: locked
? value
: (_settings?.[key as keyof Settings] ?? value),
});
}
acc = Object.assign(acc, {
[key]: locked ? value : _settings?.[key as keyof Settings] ?? value,
});
}
return acc;
}, {} as Settings);
return acc;
},
{} as Settings,
);
return {
...defaultValues,
@@ -301,5 +332,11 @@ export const useSettings = () => {
};
}, [_settings, pluginSettings]);
return [settings, updateSettings, pluginSettings, setPluginSettings, refreshStreamyfinPluginSettings] as const;
return [
settings,
updateSettings,
pluginSettings,
setPluginSettings,
refreshStreamyfinPluginSettings,
] as const;
};

View File

@@ -25,8 +25,7 @@ export async function unregisterBackgroundFetchAsync() {
}
}
export const BACKGROUND_FETCH_TASK_SESSIONS =
"background-fetch-sessions";
export const BACKGROUND_FETCH_TASK_SESSIONS = "background-fetch-sessions";
export async function registerBackgroundFetchAsyncSessions() {
try {
@@ -47,4 +46,4 @@ export async function unregisterBackgroundFetchAsyncSessions() {
} catch (error) {
console.log("Error unregistering background fetch task", error);
}
}
}

View File

@@ -3,6 +3,8 @@ export const formatBitrate = (bitrate?: number | null) => {
const sizes = ["bps", "Kbps", "Mbps", "Gbps", "Tbps"];
if (bitrate === 0) return "0 bps";
const i = parseInt(Math.floor(Math.log(bitrate) / Math.log(1000)).toString());
const i = Number.parseInt(
Math.floor(Math.log(bitrate) / Math.log(1000)).toString(),
);
return Math.round((bitrate / Math.pow(1000, i)) * 100) / 100 + " " + sizes[i];
};

View File

@@ -20,7 +20,7 @@ import {
readonly Folders: "folders";
*/
export const colletionTypeToItemType = (
collectionType?: CollectionType | null
collectionType?: CollectionType | null,
): BaseItemKind | undefined => {
if (!collectionType) return undefined;

View File

@@ -13,7 +13,7 @@ export const getOrSetDeviceId = () => {
};
export const getDeviceId = () => {
let deviceId = storage.getString("deviceId");
const deviceId = storage.getString("deviceId");
return deviceId || null;
};

View File

@@ -2,7 +2,7 @@ import useImageStorage from "@/hooks/useImageStorage";
import { apiAtom } from "@/providers/JellyfinProvider";
import { getPrimaryImageUrlById } from "@/utils/jellyfin/image/getPrimaryImageUrlById";
import { storage } from "@/utils/mmkv";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { useAtom } from "jotai";
const useDownloadHelper = () => {
@@ -19,7 +19,7 @@ const useDownloadHelper = () => {
console.log(`Saving primary image for series: ${item.SeriesId}`);
await saveImage(
item.SeriesId,
getPrimaryImageUrlById({ api, id: item.SeriesId })
getPrimaryImageUrlById({ api, id: item.SeriesId }),
);
console.log(`Primary image saved for series: ${item.SeriesId}`);
} else {

View File

@@ -14,7 +14,7 @@ class EventBus {
off<T = void>(event: string, callback: Listener<T>): void {
if (!this.listeners[event]) return;
this.listeners[event] = this.listeners[event].filter(
(fn) => fn !== callback
(fn) => fn !== callback,
);
}

View File

@@ -1,6 +1,6 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { ImageSource } from "expo-image";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { ImageSource } from "expo-image";
interface Props {
item: BaseItemDto;

View File

@@ -11,7 +11,7 @@ export interface SubtitleTrack {
}
export async function parseM3U8ForSubtitles(
url: string
url: string,
): Promise<SubtitleTrack[]> {
try {
const response = await axios.get(url, { responseType: "text" });

View File

@@ -1,10 +1,10 @@
// utils/getDefaultPlaySettings.ts
import { BITRATES } from "@/components/BitrateSelector";
import {
import type {
BaseItemDto,
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client";
import { Settings, useSettings } from "../atoms/settings";
import { type Settings, useSettings } from "../atoms/settings";
import {
AudioStreamRanker,
StreamRanker,
@@ -34,7 +34,7 @@ export function getDefaultPlaySettings(
item: BaseItemDto,
settings: Settings,
previousIndexes?: previousIndexes,
previousSource?: MediaSourceInfo
previousSource?: MediaSourceInfo,
): PlaySettings {
if (item.Type === "Program") {
return {
@@ -53,14 +53,14 @@ export function getDefaultPlaySettings(
// 2. Get default or preferred audio
const defaultAudioIndex = mediaSource?.DefaultAudioStreamIndex;
const preferedAudioIndex = mediaSource?.MediaStreams?.find(
(x) => x.Type === "Audio" && x.Language === settings?.defaultAudioLanguage
(x) => x.Type === "Audio" && x.Language === settings?.defaultAudioLanguage,
)?.Index;
const firstAudioIndex = mediaSource?.MediaStreams?.find(
(x) => x.Type === "Audio"
(x) => x.Type === "Audio",
)?.Index;
// We prefer the previous track over the default track.
let trackOptions: TrackOptions = {
const trackOptions: TrackOptions = {
DefaultAudioStreamIndex: defaultAudioIndex ?? -1,
DefaultSubtitleStreamIndex: mediaSource?.DefaultSubtitleStreamIndex ?? -1,
};
@@ -74,7 +74,7 @@ export function getDefaultPlaySettings(
previousIndexes.subtitleIndex,
previousSource,
mediaStreams,
trackOptions
trackOptions,
);
}
}
@@ -87,7 +87,7 @@ export function getDefaultPlaySettings(
previousIndexes.audioIndex,
previousSource,
mediaStreams,
trackOptions
trackOptions,
);
}
}

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getPrimaryImageUrl } from "./getPrimaryImageUrl";
/**

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
/**
* Retrieves the primary image URL for a given item.

View File

@@ -1,6 +1,6 @@
import { Api } from "@jellyfin/sdk";
import type { Api } from "@jellyfin/sdk";
import {
BaseItemDto,
type BaseItemDto,
BaseItemPerson,
} from "@jellyfin/sdk/lib/generated-client/models";
import { isBaseItemDto } from "../jellyfin";

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import {
import type { Api } from "@jellyfin/sdk";
import type {
BaseItemDto,
BaseItemPerson,
} from "@jellyfin/sdk/lib/generated-client/models";

View File

@@ -1,4 +1,4 @@
import { Api } from "@jellyfin/sdk";
import type { Api } from "@jellyfin/sdk";
/**
* Retrieves the primary image URL for a given item.

View File

@@ -1,6 +1,6 @@
import { Api } from "@jellyfin/sdk";
import type { Api } from "@jellyfin/sdk";
import {
BaseItemDto,
type BaseItemDto,
BaseItemPerson,
} from "@jellyfin/sdk/lib/generated-client/models";
import { isBaseItemDto } from "../jellyfin";

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
/**
* Generates the authorization headers for Jellyfin API requests.

View File

@@ -1,4 +1,4 @@
import { Api } from "@jellyfin/sdk";
import type { Api } from "@jellyfin/sdk";
import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api";
/**

View File

@@ -1,6 +1,6 @@
import native from "@/utils/profiles/native";
import { Api } from "@jellyfin/sdk";
import {
import type { Api } from "@jellyfin/sdk";
import type {
BaseItemDto,
MediaSourceInfo,
PlaybackInfoResponse,
@@ -63,7 +63,7 @@ export const getStreamUrl = async ({
data: {
deviceProfile,
},
}
},
);
const transcodeUrl = res0.data.MediaSources?.[0].TranscodingUrl;
sessionId = res0.data.PlaySessionId || null;
@@ -95,7 +95,7 @@ export const getStreamUrl = async ({
audioStreamIndex,
subtitleStreamIndex,
},
}
},
);
if (res2.status !== 200) {
@@ -105,7 +105,7 @@ export const getStreamUrl = async ({
sessionId = res2.data.PlaySessionId || null;
mediaSource = res2.data.MediaSources?.find(
(source: MediaSourceInfo) => source.Id === mediaSourceId
(source: MediaSourceInfo) => source.Id === mediaSourceId,
);
if (item.MediaType === "Video") {

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { AxiosError } from "axios";
import type { Api } from "@jellyfin/sdk";
import type { AxiosError } from "axios";
interface MarkAsNotPlayedParams {
api: Api | null | undefined;

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getPlaystateApi } from "@jellyfin/sdk/lib/utils/api";
interface MarkAsPlayedParams {
@@ -14,7 +14,11 @@ interface MarkAsPlayedParams {
* @param params - The parameters for marking an item as played∏
* @returns A promise that resolves to true if the operation was successful, false otherwise
*/
export const markAsPlayed = async ({ api, item, userId }: MarkAsPlayedParams): Promise<boolean> => {
export const markAsPlayed = async ({
api,
item,
userId,
}: MarkAsPlayedParams): Promise<boolean> => {
if (!api || !item?.Id || !userId || !item.RunTimeTicks) {
console.error("Invalid parameters for markAsPlayed");
return false;

View File

@@ -1,17 +1,17 @@
import { Api } from "@jellyfin/sdk";
import { getAuthHeaders } from "../jellyfin";
import { postCapabilities } from "../session/capabilities";
import { Settings } from "@/utils/atoms/settings";
import { getOrSetDeviceId } from "@/providers/JellyfinProvider";
import type { Settings } from "@/utils/atoms/settings";
import ios from "@/utils/profiles/ios";
import native from "@/utils/profiles/native";
import old from "@/utils/profiles/old";
import type { Api } from "@jellyfin/sdk";
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client";
import {
getMediaInfoApi,
getPlaystateApi,
getSessionApi,
} from "@jellyfin/sdk/lib/utils/api";
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client";
import { getOrSetDeviceId } from "@/providers/JellyfinProvider";
import ios from "@/utils/profiles/ios";
import native from "@/utils/profiles/native";
import old from "@/utils/profiles/old";
import { getAuthHeaders } from "../jellyfin";
import { postCapabilities } from "../session/capabilities";
interface ReportPlaybackProgressParams {
api?: Api | null;

View File

@@ -1,7 +1,7 @@
import { Settings } from "@/utils/atoms/settings";
import type { Settings } from "@/utils/atoms/settings";
import native from "@/utils/profiles/native";
import { Api } from "@jellyfin/sdk";
import { AxiosError, AxiosResponse } from "axios";
import type { Api } from "@jellyfin/sdk";
import type { AxiosError, AxiosResponse } from "axios";
import { getAuthHeaders } from "../jellyfin";
interface PostCapabilitiesParams {
@@ -47,7 +47,7 @@ export const postCapabilities = async ({
},
{
headers: getAuthHeaders(api),
}
},
);
return d;
} catch (error: any | AxiosError) {

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { AxiosError } from "axios";
import { getAuthHeaders } from "../jellyfin";

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api";
/**

View File

@@ -1,5 +1,5 @@
import { Api } from "@jellyfin/sdk";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api";
/**

View File

@@ -1,7 +1,8 @@
import { atomWithStorage, createJSONStorage } from "jotai/utils";
import { storage } from "./mmkv";
import { useQuery } from "@tanstack/react-query";
import React, { createContext, useContext } from "react";
import { atomWithStorage, createJSONStorage } from "jotai/utils";
import type React from "react";
import { createContext, useContext } from "react";
import { storage } from "./mmkv";
type LogLevel = "INFO" | "WARN" | "ERROR";
@@ -20,10 +21,10 @@ const mmkvStorage = createJSONStorage(() => ({
const logsAtom = atomWithStorage("logs", [], mmkvStorage);
const LogContext = createContext<ReturnType<typeof useLogProvider> | null>(
null
null,
);
const DownloadContext = createContext<ReturnType<typeof useLogProvider> | null>(
null
null,
);
function useLogProvider() {

View File

@@ -1,12 +1,12 @@
import { itemRouter } from "@/components/common/TouchableItemRouter";
import {
import { DownloadedItem } from "@/providers/DownloadProvider";
import type {
BaseItemDto,
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client";
import axios from "axios";
import { writeToLog } from "./log";
import { DownloadedItem } from "@/providers/DownloadProvider";
import { MMKV } from "react-native-mmkv";
import { writeToLog } from "./log";
interface IJobInput {
deviceId?: string | null;
@@ -63,7 +63,7 @@ export async function getAllJobsByDeviceId({
console.error(
statusResponse.status,
statusResponse.data,
statusResponse.statusText
statusResponse.statusText,
);
throw new Error("Failed to fetch job status");
}
@@ -172,7 +172,7 @@ export async function getStatistics({
export function saveDownloadItemInfoToDiskTmp(
item: BaseItemDto,
mediaSource: MediaSourceInfo,
url: string
url: string,
): boolean {
try {
const storage = new MMKV();

View File

@@ -1,4 +1,4 @@
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client/models";
import type { DeviceProfile } from "@jellyfin/sdk/lib/generated-client/models";
export const chromecast: DeviceProfile = {
Name: "Chromecast Video Profile",

View File

@@ -1,4 +1,4 @@
import { DeviceProfile } from "@jellyfin/sdk/lib/generated-client/models";
import type { DeviceProfile } from "@jellyfin/sdk/lib/generated-client/models";
export const chromecasth265: DeviceProfile = {
Name: "Chromecast Video Profile",

View File

@@ -1,3 +1,3 @@
import { createStore } from 'jotai';
import { createStore } from "jotai";
export const store = createStore();

View File

@@ -1,4 +1,4 @@
import {
import type {
MediaSourceInfo,
MediaStream,
} from "@jellyfin/sdk/lib/generated-client";
@@ -10,14 +10,14 @@ abstract class StreamRankerStrategy {
prevIndex: number,
prevSource: MediaSourceInfo,
mediaStreams: MediaStream[],
trackOptions: any
trackOptions: any,
): void;
protected rank(
prevIndex: number,
prevSource: MediaSourceInfo,
mediaStreams: MediaStream[],
trackOptions: any
trackOptions: any,
): void {
if (prevIndex == -1) {
console.debug(`AutoSet Subtitle - No Stream Set`);
@@ -41,7 +41,7 @@ abstract class StreamRankerStrategy {
}
console.debug(
`AutoSet ${this.streamType} - Previous was ${prevStream.Index} - ${prevStream.DisplayTitle}`
`AutoSet ${this.streamType} - Previous was ${prevStream.Index} - ${prevStream.DisplayTitle}`,
);
let prevRelIndex = 0;
@@ -74,7 +74,7 @@ abstract class StreamRankerStrategy {
score += 2;
console.debug(
`AutoSet ${this.streamType} - Score ${score} for ${stream.Index} - ${stream.DisplayTitle}`
`AutoSet ${this.streamType} - Score ${score} for ${stream.Index} - ${stream.DisplayTitle}`,
);
if (score > bestStreamScore && score >= 3) {
bestStreamScore = score;
@@ -86,12 +86,12 @@ abstract class StreamRankerStrategy {
if (bestStreamIndex != null) {
console.debug(
`AutoSet ${this.streamType} - Using ${bestStreamIndex} score ${bestStreamScore}.`
`AutoSet ${this.streamType} - Using ${bestStreamIndex} score ${bestStreamScore}.`,
);
trackOptions[`Default${this.streamType}StreamIndex`] = bestStreamIndex;
} else {
console.debug(
`AutoSet ${this.streamType} - Threshold not met. Using default.`
`AutoSet ${this.streamType} - Threshold not met. Using default.`,
);
}
}
@@ -104,7 +104,7 @@ class SubtitleStreamRanker extends StreamRankerStrategy {
prevIndex: number,
prevSource: MediaSourceInfo,
mediaStreams: MediaStream[],
trackOptions: any
trackOptions: any,
): void {
super.rank(prevIndex, prevSource, mediaStreams, trackOptions);
}
@@ -117,7 +117,7 @@ class AudioStreamRanker extends StreamRankerStrategy {
prevIndex: number,
prevSource: MediaSourceInfo,
mediaStreams: MediaStream[],
trackOptions: any
trackOptions: any,
): void {
super.rank(prevIndex, prevSource, mediaStreams, trackOptions);
}
@@ -138,7 +138,7 @@ class StreamRanker {
prevIndex: number,
prevSource: MediaSourceInfo,
mediaStreams: MediaStream[],
trackOptions: any
trackOptions: any,
) {
this.strategy.rankStream(prevIndex, prevSource, mediaStreams, trackOptions);
}

View File

@@ -1,7 +1,7 @@
/*
* Truncate a text longer than a certain length
*/
export const tc = (text: string | null | undefined, length: number = 20) => {
export const tc = (text: string | null | undefined, length = 20) => {
if (!text) return "";
return text.length > length ? text.substr(0, length) + "..." : text;
};

View File

@@ -6,7 +6,7 @@
* @returns A string formatted as "Xh Ym" where X is hours and Y is minutes.
*/
export const runtimeTicksToMinutes = (
ticks: number | null | undefined
ticks: number | null | undefined,
): string => {
if (!ticks) return "0h 0m";
@@ -21,7 +21,7 @@ export const runtimeTicksToMinutes = (
};
export const runtimeTicksToSeconds = (
ticks: number | null | undefined
ticks: number | null | undefined,
): string => {
if (!ticks) return "0h 0m";
@@ -39,7 +39,7 @@ export const runtimeTicksToSeconds = (
// t: ms
export const formatTimeString = (
t: number | null | undefined,
unit: "s" | "ms" | "tick" = "ms"
unit: "s" | "ms" | "tick" = "ms",
): string => {
if (t === null || t === undefined) return "0:00";

View File

@@ -1,9 +1,9 @@
import { useFocusEffect } from "@react-navigation/core";
import {
QueryKey,
type QueryKey,
type UseQueryOptions,
type UseQueryResult,
useQuery,
UseQueryOptions,
UseQueryResult,
} from "@tanstack/react-query";
import { useCallback } from "react";
@@ -11,9 +11,9 @@ export function useReactNavigationQuery<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
TQueryKey extends QueryKey = QueryKey,
>(
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
): UseQueryResult<TData, TError> {
const useQueryReturn = useQuery(options);
@@ -25,7 +25,7 @@ export function useReactNavigationQuery<
options.enabled !== false
)
useQueryReturn.refetch();
}, [options.enabled, options.refetchOnWindowFocus])
}, [options.enabled, options.refetchOnWindowFocus]),
);
return useQueryReturn;