This commit is contained in:
Fredrik Burmester
2025-01-03 11:42:18 +01:00
parent 62b00837ec
commit f92fee4158
8 changed files with 8361 additions and 229 deletions

View File

@@ -130,6 +130,7 @@
},
"updates": {
"url": "https://u.expo.dev/e79219d1-797f-4fbe-9fa1-cfd360690a68"
}
},
"newArchEnabled": false
}
}

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,10 +0,0 @@
import * as React from 'react';
import renderer from 'react-test-renderer';
import { ThemedText } from '../ThemedText';
it(`renders correctly`, () => {
const tree = renderer.create(<ThemedText>Snapshot test!</ThemedText>).toJSON();
expect(tree).toMatchSnapshot();
});

View File

@@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Text
style={
[
{
"color": "#11181C",
},
{
"fontSize": 16,
"lineHeight": 24,
},
undefined,
undefined,
undefined,
undefined,
undefined,
]
}
>
Snapshot test!
</Text>
`;

View File

@@ -1,11 +1,12 @@
import {useRouter, useSegments} from "expo-router";
import React, {PropsWithChildren, useCallback, useMemo} from "react";
import {TouchableOpacity, TouchableOpacityProps} from "react-native";
import * as ContextMenu from "zeego/context-menu";
import {MovieResult, TvResult} from "@/utils/jellyseerr/server/models/Search";
import {useJellyseerr} from "@/hooks/useJellyseerr";
import {hasPermission, Permission} from "@/utils/jellyseerr/server/lib/permissions";
import {MediaType} from "@/utils/jellyseerr/server/constants/media";
import { useJellyseerr } from "@/hooks/useJellyseerr";
import {
hasPermission,
Permission,
} from "@/utils/jellyseerr/server/lib/permissions";
import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
import { useRouter, useSegments } from "expo-router";
import React, { PropsWithChildren, useCallback, useMemo } from "react";
import { TouchableOpacity, TouchableOpacityProps } from "react-native";
interface Props extends TouchableOpacityProps {
result: MovieResult | TvResult;
@@ -26,78 +27,49 @@ export const TouchableJellyseerrRouter: React.FC<PropsWithChildren<Props>> = ({
}) => {
const router = useRouter();
const segments = useSegments();
const {jellyseerrApi, jellyseerrUser, requestMedia} = useJellyseerr()
const { jellyseerrApi, jellyseerrUser, requestMedia } = useJellyseerr();
const from = segments[2];
const autoApprove = useMemo(() => {
return jellyseerrUser && hasPermission(
Permission.AUTO_APPROVE,
jellyseerrUser.permissions,
{type: 'or'}
)
}, [jellyseerrApi, jellyseerrUser])
return (
jellyseerrUser &&
hasPermission(Permission.AUTO_APPROVE, jellyseerrUser.permissions, {
type: "or",
})
);
}, [jellyseerrApi, jellyseerrUser]);
const request = useCallback(() =>
const request = useCallback(
() =>
requestMedia(mediaTitle, {
mediaId: result.id,
mediaType: result.mediaType
}
),
mediaType: result.mediaType,
}),
[jellyseerrApi, result]
)
);
if (from === "(home)" || from === "(search)" || from === "(libraries)")
return (
<>
<ContextMenu.Root>
<ContextMenu.Trigger>
<TouchableOpacity
onPress={() => {
// @ts-ignore
router.push({pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`, params: {...result, mediaTitle, releaseYear, canRequest, posterSrc}});
}}
{...props}
>
{children}
</TouchableOpacity>
</ContextMenu.Trigger>
<ContextMenu.Content
avoidCollisions
alignOffset={0}
collisionPadding={0}
loop={false}
key={"content"}
>
<ContextMenu.Label key="label-1">Actions</ContextMenu.Label>
{canRequest && result.mediaType === MediaType.MOVIE && (
<ContextMenu.Item
key="item-1"
onSelect={() => {
if (autoApprove) {
request()
}
}}
shouldDismissMenuOnSelect
>
<ContextMenu.ItemTitle key="item-1-title">Request</ContextMenu.ItemTitle>
<ContextMenu.ItemIcon
ios={{
name: "arrow.down.to.line",
pointSize: 18,
weight: "semibold",
scale: "medium",
hierarchicalColor: {
dark: "purple",
light: "purple",
},
}}
androidIconName="download"
/>
</ContextMenu.Item>
)}
</ContextMenu.Content>
</ContextMenu.Root>
<TouchableOpacity
onPress={() => {
router.push({
pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`,
params: {
...result,
mediaTitle,
releaseYear,
// @ts-expect-error
canRequest,
posterSrc,
},
});
}}
{...props}
>
{children}
</TouchableOpacity>
</>
);
};

View File

@@ -6,7 +6,6 @@ import {
import { useRouter, useSegments } from "expo-router";
import { PropsWithChildren } from "react";
import { TouchableOpacity, TouchableOpacityProps } from "react-native";
import * as ContextMenu from "zeego/context-menu";
interface Props extends TouchableOpacityProps {
item: BaseItemDto;
@@ -16,8 +15,6 @@ export const itemRouter = (
item: BaseItemDto | BaseItemPerson,
from: string
) => {
console.log(item.Type, item?.CollectionType);
if ("CollectionType" in item && item.CollectionType === "livetv") {
return `/(auth)/(tabs)/${from}/livetv`;
}
@@ -80,78 +77,15 @@ export const TouchableItemRouter: React.FC<PropsWithChildren<Props>> = ({
from === "(favorites)"
)
return (
<ContextMenu.Root>
<ContextMenu.Trigger>
<TouchableOpacity
onPress={() => {
const url = itemRouter(item, from);
// @ts-ignore
router.push(url);
}}
{...props}
>
{children}
</TouchableOpacity>
</ContextMenu.Trigger>
<ContextMenu.Content
avoidCollisions
alignOffset={0}
collisionPadding={0}
loop={false}
key={"content"}
>
<ContextMenu.Label key="label-1">Actions</ContextMenu.Label>
<ContextMenu.Item
key="item-1"
onSelect={() => {
markAsPlayedStatus(true);
}}
shouldDismissMenuOnSelect
>
<ContextMenu.ItemTitle key="item-1-title">
Mark as watched
</ContextMenu.ItemTitle>
<ContextMenu.ItemIcon
ios={{
name: "checkmark.circle", // Changed to "checkmark.circle" which represents "watched"
pointSize: 18,
weight: "semibold",
scale: "medium",
hierarchicalColor: {
dark: "green", // Changed to green for "watched"
light: "green",
},
}}
androidIconName="checkmark-circle"
></ContextMenu.ItemIcon>
</ContextMenu.Item>
<ContextMenu.Item
key="item-2"
onSelect={() => {
markAsPlayedStatus(false);
}}
shouldDismissMenuOnSelect
destructive
>
<ContextMenu.ItemTitle key="item-2-title">
Mark as not watched
</ContextMenu.ItemTitle>
<ContextMenu.ItemIcon
ios={{
name: "eye.slash", // Changed to "eye.slash" which represents "not watched"
pointSize: 18, // Adjusted for better visibility
weight: "semibold",
scale: "medium",
hierarchicalColor: {
dark: "red", // Changed to red for "not watched"
light: "red",
},
// Removed paletteColors as it's not necessary in this case
}}
androidIconName="eye-slash"
></ContextMenu.ItemIcon>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
<TouchableOpacity
onPress={() => {
const url = itemRouter(item, from);
// @ts-ignore
router.push(url);
}}
{...props}
>
{children}
</TouchableOpacity>
);
};

View File

@@ -9,13 +9,9 @@
"android": "bun run submodule-reload && expo run:android",
"ios": "bun run submodule-reload && expo run:ios",
"web": "bun run submodule-reload && expo start --web",
"test": "jest --watchAll",
"lint": "expo lint",
"postinstall": "patch-package"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@bottom-tabs/react-navigation": "^0.7.1",
"@config-plugins/ffmpeg-kit-react-native": "^8.0.0",
@@ -26,71 +22,69 @@
"@jellyfin/sdk": "^0.11.0",
"@kesha-antonov/react-native-background-downloader": "^3.2.1",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/netinfo": "11.3.1",
"@react-native-community/netinfo": "11.4.1",
"@react-native-menu/menu": "^1.1.6",
"@react-navigation/material-top-tabs": "^6.6.14",
"@react-navigation/native": "^6.1.18",
"@shopify/flash-list": "1.6.4",
"@react-navigation/native": "^7.0.14",
"@shopify/flash-list": "1.7.1",
"@tanstack/react-query": "^5.59.20",
"@types/lodash": "^4.17.13",
"@types/react-native-vector-icons": "^6.4.18",
"@types/uuid": "^10.0.0",
"add": "^2.0.6",
"axios": "^1.7.7",
"expo": "~51.0.39",
"expo-asset": "~10.0.10",
"expo-background-fetch": "~12.0.1",
"expo-blur": "~13.0.2",
"expo-brightness": "~12.0.1",
"expo-build-properties": "~0.12.5",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.29",
"expo-device": "~6.0.2",
"expo-font": "~12.0.10",
"expo-haptics": "~13.0.1",
"expo-image": "~1.13.0",
"expo-keep-awake": "~13.0.2",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-network": "~6.0.1",
"expo-notifications": "~0.28.19",
"expo-router": "~3.5.24",
"expo-screen-orientation": "~7.0.5",
"expo-sensors": "~13.0.9",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "^3.0.7",
"expo-task-manager": "~11.8.2",
"expo-updates": "~0.25.27",
"expo-web-browser": "~13.0.3",
"expo": "52",
"expo-asset": "~11.0.1",
"expo-background-fetch": "~13.0.3",
"expo-blur": "~14.0.1",
"expo-brightness": "~13.0.2",
"expo-build-properties": "~0.13.1",
"expo-constants": "~17.0.3",
"expo-dev-client": "~5.0.8",
"expo-device": "~7.0.1",
"expo-font": "~13.0.2",
"expo-haptics": "~14.0.0",
"expo-image": "~2.0.3",
"expo-keep-awake": "~14.0.1",
"expo-linear-gradient": "~14.0.1",
"expo-linking": "~7.0.3",
"expo-network": "~7.0.4",
"expo-notifications": "~0.29.11",
"expo-router": "~4.0.15",
"expo-screen-orientation": "~8.0.2",
"expo-sensors": "~14.0.1",
"expo-splash-screen": "~0.29.18",
"expo-status-bar": "~2.0.0",
"expo-system-ui": "~4.0.6",
"expo-task-manager": "~12.0.3",
"expo-updates": "~0.26.10",
"expo-web-browser": "~14.0.1",
"ffmpeg-kit-react-native": "^6.0.2",
"install": "^0.13.0",
"jotai": "^2.10.1",
"lodash": "^4.17.21",
"nativewind": "^2.0.11",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.74.5",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.5",
"react-native-awesome-slider": "^2.5.6",
"react-native-bottom-tabs": "0.7.1",
"react-native-circular-progress": "^1.4.1",
"react-native-compressor": "^1.9.0",
"react-native-device-info": "^14.0.1",
"react-native-edge-to-edge": "^1.1.1",
"react-native-gesture-handler": "~2.16.1",
"react-native-gesture-handler": "~2.20.2",
"react-native-get-random-values": "^1.11.0",
"react-native-google-cast": "^4.8.3",
"react-native-image-colors": "^2.4.0",
"react-native-ios-context-menu": "^2.5.2",
"react-native-ios-utilities": "^4.5.1",
"react-native-mmkv": "^2.12.2",
"react-native-pager-view": "6.3.0",
"react-native-mmkv": "^3.0.1",
"react-native-pager-view": "6.5.1",
"react-native-progress": "^5.0.1",
"react-native-reanimated": "~3.10.1",
"react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "4.0.0-canary.22",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-svg": "15.2.0",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0",
"react-native-svg": "15.8.0",
"react-native-tab-view": "^3.5.2",
"react-native-uitextview": "^1.4.0",
"react-native-url-polyfill": "^2.0.0",
@@ -98,7 +92,7 @@
"react-native-video": "^6.7.0",
"react-native-volume-manager": "^1.10.0",
"react-native-web": "~0.19.13",
"react-native-webview": "13.8.6",
"react-native-webview": "13.12.5",
"react-native-youtube-iframe": "^2.3.0",
"sonner-native": "^0.14.2",
"tailwindcss": "3.3.2",
@@ -109,11 +103,8 @@
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@types/jest": "^29.5.14",
"@types/react": "~18.2.79",
"@types/react": "~18.3.12",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~51.0.4",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"react-test-renderer": "18.2.0",

8268
yarn.lock Normal file

File diff suppressed because it is too large Load Diff