diff --git a/app.json b/app.json
index dc399d04..7b40fa03 100644
--- a/app.json
+++ b/app.json
@@ -63,12 +63,6 @@
}
}
],
- [
- "expo-screen-orientation",
- {
- "initialOrientation": "DEFAULT"
- }
- ],
[
"expo-sensors",
{
diff --git a/app/(auth)/(tabs)/(custom-links)/_layout.tsx b/app/(auth)/(tabs)/(custom-links)/_layout.tsx
deleted file mode 100644
index ed0529d4..00000000
--- a/app/(auth)/(tabs)/(custom-links)/_layout.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import {Stack} from "expo-router";
-import { Platform } from "react-native";
-
-export default function CustomMenuLayout() {
- return (
-
-
-
- );
-}
diff --git a/app/(auth)/(tabs)/(custom-links)/index.tsx b/app/(auth)/(tabs)/(custom-links)/index.tsx
deleted file mode 100644
index 76b10fb8..00000000
--- a/app/(auth)/(tabs)/(custom-links)/index.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import {FlatList, TouchableOpacity, View} from "react-native";
-import {useSafeAreaInsets} from "react-native-safe-area-context";
-import React, {useCallback, useEffect, useState} from "react";
-import {useAtom} from "jotai/index";
-import {apiAtom} from "@/providers/JellyfinProvider";
-import {ListItem} from "@/components/ListItem";
-import * as WebBrowser from 'expo-web-browser';
-import Ionicons from '@expo/vector-icons/Ionicons';
-import {Text} from "@/components/common/Text";
-
-export interface MenuLink {
- name: string,
- url: string,
- icon: string
-}
-
-export default function menuLinks() {
- const [api] = useAtom(apiAtom);
- const insets = useSafeAreaInsets()
- const [menuLinks, setMenuLinks] = useState([])
-
- const getMenuLinks = useCallback(async () => {
- try {
- const response = await api?.axiosInstance.get(api?.basePath + "/web/config.json")
- const config = response?.data;
-
- if (!config && !config.hasOwnProperty("menuLinks")) {
- console.error("Menu links not found");
- return;
- }
-
- setMenuLinks(config?.menuLinks as MenuLink[])
- } catch (error) {
- console.error("Failed to retrieve config:", error);
- }
- },
- [api]
- )
-
- useEffect(() => { getMenuLinks() }, []);
- return (
- (
- WebBrowser.openBrowserAsync(item.url) }>
- }
- />
-
- )
- }
- ItemSeparatorComponent={() => (
-
- )}
- ListEmptyComponent={
-
- No links
-
- }
- />
- );
-}
\ No newline at end of file
diff --git a/app/(auth)/(tabs)/(home)/settings.tsx b/app/(auth)/(tabs)/(home)/settings.tsx
index 72b362b3..e19001c5 100644
--- a/app/(auth)/(tabs)/(home)/settings.tsx
+++ b/app/(auth)/(tabs)/(home)/settings.tsx
@@ -7,7 +7,6 @@ import { clearLogs, useLog } from "@/utils/log";
import { getQuickConnectApi } from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
import * as FileSystem from "expo-file-system";
-import * as Haptics from "expo-haptics";
import { useAtom } from "jotai";
import { Alert, ScrollView, View } from "react-native";
import * as Progress from "react-native-progress";
@@ -35,16 +34,11 @@ export default function settings() {
userId: user?.Id,
});
if (res.status === 200) {
- Haptics.notificationAsync(
- Haptics.NotificationFeedbackType.Success
- );
Alert.alert("Success", "Quick connect authorized");
} else {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
Alert.alert("Error", "Invalid code");
}
} catch (e) {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
Alert.alert("Error", "Invalid code");
}
}
diff --git a/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx b/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx
index 4c2b72ae..63351a59 100644
--- a/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search)/collections/[collectionId].tsx
@@ -29,7 +29,6 @@ import {
import { FlashList } from "@shopify/flash-list";
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import { useLocalSearchParams, useNavigation } from "expo-router";
-import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { FlatList, View } from "react-native";
@@ -41,10 +40,6 @@ const page: React.FC = () => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const navigation = useNavigation();
- const [orientation, setOrientation] = useState(
- ScreenOrientation.Orientation.PORTRAIT_UP
- );
-
const [selectedGenres, setSelectedGenres] = useAtom(genreFilterAtom);
const [selectedYears, setSelectedYears] = useAtom(yearFilterAtom);
const [selectedTags, setSelectedTags] = useAtom(tagsFilterAtom);
@@ -174,8 +169,7 @@ const page: React.FC = () => {
key={item.Id}
style={{
width: "100%",
- marginBottom:
- orientation === ScreenOrientation.Orientation.PORTRAIT_UP ? 4 : 16,
+ marginBottom: 16,
}}
item={item}
>
@@ -389,9 +383,7 @@ const page: React.FC = () => {
renderItem={renderItem}
keyExtractor={keyExtractor}
estimatedItemSize={255}
- numColumns={
- orientation === ScreenOrientation.Orientation.PORTRAIT_UP ? 3 : 5
- }
+ numColumns={5}
onEndReached={() => {
if (hasNextPage) {
fetchNextPage();
diff --git a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
index bd0df182..0d69348c 100644
--- a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
+++ b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
@@ -1,6 +1,5 @@
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import { useLocalSearchParams, useNavigation } from "expo-router";
-import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useCallback, useEffect, useMemo } from "react";
import { FlatList, useWindowDimensions, View } from "react-native";
@@ -12,7 +11,6 @@ import { ResetFiltersButton } from "@/components/filters/ResetFiltersButton";
import { ItemCardText } from "@/components/ItemCardText";
import { Loader } from "@/components/Loader";
import { ItemPoster } from "@/components/posters/ItemPoster";
-import { useOrientation } from "@/hooks/useOrientation";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import {
genreFilterAtom,
@@ -61,8 +59,6 @@ const Page = () => {
sortOrderPreferenceAtom
);
- const { orientation } = useOrientation();
-
useEffect(() => {
const sop = getSortOrderPreference(libraryId, sortOrderPreference);
if (sop) {
@@ -241,14 +237,7 @@ const Page = () => {
>
diff --git a/app/(auth)/player/direct-player.tsx b/app/(auth)/player/direct-player.tsx
index 22670cf0..0acbff13 100644
--- a/app/(auth)/player/direct-player.tsx
+++ b/app/(auth)/player/direct-player.tsx
@@ -2,8 +2,6 @@ import { BITRATES } from "@/components/BitrateSelector";
import { Text } from "@/components/common/Text";
import { Loader } from "@/components/Loader";
import { Controls } from "@/components/video-player/controls/Controls";
-import { useOrientation } from "@/hooks/useOrientation";
-import { useOrientationSettings } from "@/hooks/useOrientationSettings";
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
import { useWebSocket } from "@/hooks/useWebsockets";
import { VlcPlayerView } from "@/modules/vlc-player";
@@ -26,7 +24,6 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "expo-haptics";
import { useFocusEffect, useGlobalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
import React, {
@@ -59,7 +56,6 @@ export default function page() {
const setShowControls = useCallback((show: boolean) => {
_setShowControls(show);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}, []);
const {
@@ -142,7 +138,6 @@ export default function page() {
const togglePlay = useCallback(async () => {
if (!api) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
if (isPlaying) {
await videoRef.current?.pause();
@@ -254,9 +249,6 @@ export default function page() {
[item?.Id, isPlaying, api, isPlaybackStopped, audioIndex, subtitleIndex]
);
- useOrientation();
- useOrientationSettings();
-
useWebSocket({
isPlaying: isPlaying,
togglePlay: togglePlay,
diff --git a/app/(auth)/player/music-player.tsx b/app/(auth)/player/music-player.tsx
index 13aa4ecc..cdef5a8e 100644
--- a/app/(auth)/player/music-player.tsx
+++ b/app/(auth)/player/music-player.tsx
@@ -1,8 +1,6 @@
import { Text } from "@/components/common/Text";
import { Loader } from "@/components/Loader";
import { Controls } from "@/components/video-player/controls/Controls";
-import { useOrientation } from "@/hooks/useOrientation";
-import { useOrientationSettings } from "@/hooks/useOrientationSettings";
import { useWebSocket } from "@/hooks/useWebsockets";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
@@ -17,7 +15,6 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "expo-haptics";
import { Image } from "expo-image";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
@@ -124,7 +121,6 @@ export default function page() {
const togglePlay = useCallback(
async (ticks: number) => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
if (isPlaying) {
videoRef.current?.pause();
await getPlaystateApi(api!).onPlaybackProgress({
@@ -261,9 +257,6 @@ export default function page() {
}, [play, stop])
);
- useOrientation();
- useOrientationSettings();
-
useWebSocket({
isPlaying: isPlaying,
pauseVideo: pause,
diff --git a/app/(auth)/player/transcoding-player.tsx b/app/(auth)/player/transcoding-player.tsx
index 2191e441..6dd88eb2 100644
--- a/app/(auth)/player/transcoding-player.tsx
+++ b/app/(auth)/player/transcoding-player.tsx
@@ -1,8 +1,6 @@
import { Text } from "@/components/common/Text";
import { Loader } from "@/components/Loader";
import { Controls } from "@/components/video-player/controls/Controls";
-import { useOrientation } from "@/hooks/useOrientation";
-import { useOrientationSettings } from "@/hooks/useOrientationSettings";
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
import { useWebSocket } from "@/hooks/useWebsockets";
import { TrackInfo } from "@/modules/vlc-player";
@@ -20,7 +18,6 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "expo-haptics";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
import React, {
@@ -58,7 +55,6 @@ const Player = () => {
const setShowControls = useCallback((show: boolean) => {
_setShowControls(show);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}, []);
const progress = useSharedValue(0);
@@ -167,7 +163,6 @@ const Player = () => {
const videoSource = useVideoSource(item, api, poster, stream?.url);
const togglePlay = useCallback(async () => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
if (isPlaying) {
videoRef.current?.pause();
await getPlaystateApi(api!).onPlaybackProgress({
@@ -299,9 +294,6 @@ const Player = () => {
]
);
- useOrientation();
- useOrientationSettings();
-
useWebSocket({
isPlaying: isPlaying,
togglePlay: togglePlay,
diff --git a/bun.lockb b/bun.lockb
index fd8896ee..f0112a99 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/components/Button.tsx b/components/Button.tsx
index 1a73ad01..0a46b7ee 100644
--- a/components/Button.tsx
+++ b/components/Button.tsx
@@ -1,4 +1,3 @@
-import * as Haptics from "expo-haptics";
import React, { PropsWithChildren, ReactNode, useMemo } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { Loader } from "./Loader";
@@ -54,7 +53,6 @@ export const Button: React.FC> = ({
onPress={() => {
if (!loading && !disabled && onPress) {
onPress();
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}
}}
disabled={disabled || loading}
diff --git a/components/ItemContent.tsx b/components/ItemContent.tsx
index a1d82b83..e4c5e820 100644
--- a/components/ItemContent.tsx
+++ b/components/ItemContent.tsx
@@ -12,7 +12,6 @@ import { CurrentSeries } from "@/components/series/CurrentSeries";
import { SeasonEpisodesCarousel } from "@/components/series/SeasonEpisodesCarousel";
import useDefaultPlaySettings from "@/hooks/useDefaultPlaySettings";
import { useImageColors } from "@/hooks/useImageColors";
-import { useOrientation } from "@/hooks/useOrientation";
import { apiAtom } from "@/providers/JellyfinProvider";
import { SubtitleHelper } from "@/utils/SubtitleHelper";
import { useSettings } from "@/utils/atoms/settings";
@@ -23,7 +22,6 @@ import {
} from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { useNavigation } from "expo-router";
-import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useEffect, useMemo, useState } from "react";
import { View } from "react-native";
@@ -44,7 +42,6 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
({ item }) => {
const [api] = useAtom(apiAtom);
const [settings] = useSettings();
- const { orientation } = useOrientation();
const navigation = useNavigation();
const insets = useSafeAreaInsets();
useImageColors({ item });
@@ -94,11 +91,9 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
}, [item]);
useEffect(() => {
- if (orientation !== ScreenOrientation.OrientationLock.PORTRAIT_UP)
- setHeaderHeight(230);
- else if (item.Type === "Movie") setHeaderHeight(500);
+ if (item.Type === "Movie") setHeaderHeight(500);
else setHeaderHeight(350);
- }, [item.Type, orientation]);
+ }, [item.Type]);
const logoUrl = useMemo(() => getLogoImageUrlById({ api, item }), [item]);
diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx
index d0c2c227..3804b031 100644
--- a/components/PlayButton.tsx
+++ b/components/PlayButton.tsx
@@ -5,7 +5,6 @@ import { runtimeTicksToMinutes } from "@/utils/time";
import { useActionSheet } from "@expo/react-native-action-sheet";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
-import * as Haptics from "expo-haptics";
import { useRouter } from "expo-router";
import { useAtom, useAtomValue } from "jotai";
import { useCallback, useEffect } from "react";
@@ -66,8 +65,6 @@ export const PlayButton: React.FC = ({
const onPress = useCallback(async () => {
if (!item) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
const queryParams = new URLSearchParams({
itemId: item.Id!,
audioIndex: selectedOptions.audioIndex?.toString() ?? "",
diff --git a/components/RoundButton.tsx b/components/RoundButton.tsx
index 7bcecdcb..d78eaf48 100644
--- a/components/RoundButton.tsx
+++ b/components/RoundButton.tsx
@@ -6,7 +6,6 @@ import {
TouchableOpacity,
TouchableOpacityProps,
} from "react-native";
-import * as Haptics from "expo-haptics";
interface Props extends TouchableOpacityProps {
onPress?: () => void;
@@ -32,7 +31,6 @@ export const RoundButton: React.FC> = ({
const handlePress = () => {
if (hapticFeedback) {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}
onPress?.();
};
diff --git a/components/common/JellyseerrItemRouter.tsx b/components/common/JellyseerrItemRouter.tsx
index 90f9c336..cadc9cf7 100644
--- a/components/common/JellyseerrItemRouter.tsx
+++ b/components/common/JellyseerrItemRouter.tsx
@@ -1,11 +1,13 @@
-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 { useRouter, useSegments } from "expo-router";
+import React, { PropsWithChildren, useCallback, useMemo } from "react";
+import { TouchableOpacity, TouchableOpacityProps } from "react-native";
+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";
interface Props extends TouchableOpacityProps {
result: MovieResult | TvResult;
@@ -26,78 +28,49 @@ export const TouchableJellyseerrRouter: React.FC> = ({
}) => {
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 (
<>
-
-
- {
- // @ts-ignore
- router.push({pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`, params: {...result, mediaTitle, releaseYear, canRequest, posterSrc}});
- }}
- {...props}
- >
- {children}
-
-
-
- Actions
- {canRequest && result.mediaType === MediaType.MOVIE && (
- {
- if (autoApprove) {
- request()
- }
- }}
- shouldDismissMenuOnSelect
- >
- Request
-
-
- )}
-
-
+ {
+ // @ts-ignore
+ router.push({
+ pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`,
+ params: {
+ ...result,
+ mediaTitle,
+ releaseYear,
+ canRequest,
+ posterSrc,
+ },
+ });
+ }}
+ {...props}
+ >
+ {children}
+
>
);
};
diff --git a/components/common/TouchableItemRouter.tsx b/components/common/TouchableItemRouter.tsx
index d50c88bf..a58ce6b3 100644
--- a/components/common/TouchableItemRouter.tsx
+++ b/components/common/TouchableItemRouter.tsx
@@ -1,6 +1,5 @@
import { useMarkAsPlayed } from "@/hooks/useMarkAsPlayed";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import * as Haptics from "expo-haptics";
import { useRouter, useSegments } from "expo-router";
import { PropsWithChildren } from "react";
import { TouchableOpacity, TouchableOpacityProps } from "react-native";
@@ -68,78 +67,15 @@ export const TouchableItemRouter: React.FC> = ({
if (from === "(home)" || from === "(search)" || from === "(libraries)")
return (
-
-
- {
- const url = itemRouter(item, from);
- // @ts-ignore
- router.push(url);
- }}
- {...props}
- >
- {children}
-
-
-
- Actions
- {
- markAsPlayedStatus(true);
- }}
- shouldDismissMenuOnSelect
- >
-
- Mark as watched
-
-
-
- {
- markAsPlayedStatus(false);
- }}
- shouldDismissMenuOnSelect
- destructive
- >
-
- Mark as not watched
-
-
-
-
-
+ {
+ const url = itemRouter(item, from);
+ // @ts-ignore
+ router.push(url);
+ }}
+ {...props}
+ >
+ {children}
+
);
};
diff --git a/components/home/LargeMovieCarousel.tsx b/components/home/LargeMovieCarousel.tsx
index 11676b88..37a0cda2 100644
--- a/components/home/LargeMovieCarousel.tsx
+++ b/components/home/LargeMovieCarousel.tsx
@@ -22,7 +22,6 @@ import { itemRouter, TouchableItemRouter } from "../common/TouchableItemRouter";
import { Loader } from "../Loader";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import { useRouter, useSegments } from "expo-router";
-import * as Haptics from "expo-haptics";
interface Props extends ViewProps {}
@@ -147,7 +146,6 @@ const RenderItem: React.FC<{ item: BaseItemDto }> = ({ item }) => {
const handleRoute = useCallback(() => {
if (!from) return;
const url = itemRouter(item, from);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
// @ts-ignore
if (url) router.push(url);
}, [item, from]);
diff --git a/components/settings/SettingToggles.tsx b/components/settings/SettingToggles.tsx
index 4368ff15..d828f6d9 100644
--- a/components/settings/SettingToggles.tsx
+++ b/components/settings/SettingToggles.tsx
@@ -1,8 +1,7 @@
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { ScreenOrientationEnum, useSettings } from "@/utils/atoms/settings";
+import { useSettings } from "@/utils/atoms/settings";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
import { useQuery, useQueryClient } from "@tanstack/react-query";
-import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useState } from "react";
import {
@@ -98,113 +97,6 @@ export const SettingToggles: React.FC = ({ ...props }) => {
/>
-
-
- Video orientation
-
- Set the full screen video player orientation.
-
-
-
-
-
-
- {ScreenOrientationEnum[settings.defaultVideoOrientation]}
-
-
-
-
- Orientation
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.DEFAULT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.DEFAULT
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.PORTRAIT_UP,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.PORTRAIT_UP
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.LANDSCAPE_LEFT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.LANDSCAPE_LEFT
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT
- ]
- }
-
-
-
-
-
-
Safe area in controls
@@ -377,31 +269,6 @@ export const SettingToggles: React.FC = ({ ...props }) => {
)}
-
-
-
- Show Custom Menu Links
-
- Show custom menu links defined inside your Jellyfin web
- config.json file
-
-
- Linking.openURL(
- "https://jellyfin.org/docs/general/clients/web-config/#custom-menu-links"
- )
- }
- >
- More info
-
-
-
- updateSettings({ showCustomMenuLinks: value })
- }
- />
-
diff --git a/components/video-player/controls/Controls.tsx b/components/video-player/controls/Controls.tsx
index 4110a7e5..5b17b184 100644
--- a/components/video-player/controls/Controls.tsx
+++ b/components/video-player/controls/Controls.tsx
@@ -29,7 +29,6 @@ import {
BaseItemDto,
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client";
-import * as Haptics from "expo-haptics";
import { Image } from "expo-image";
import { useLocalSearchParams, useRouter } from "expo-router";
import { useAtom } from "jotai";
@@ -159,8 +158,6 @@ export const Controls: React.FC = ({
const goToPreviousItem = useCallback(() => {
if (!previousItem || !settings) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
const previousIndexes: previousIndexes = {
subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
audioIndex: audioIndex ? parseInt(audioIndex) : undefined,
@@ -197,8 +194,6 @@ export const Controls: React.FC = ({
const goToNextItem = useCallback(() => {
if (!nextItem || !settings) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
const previousIndexes: previousIndexes = {
subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
audioIndex: audioIndex ? parseInt(audioIndex) : undefined,
@@ -325,7 +320,7 @@ export const Controls: React.FC = ({
const handleSkipBackward = useCallback(async () => {
if (!settings?.rewindSkipTime) return;
wasPlayingRef.current = isPlaying;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+
try {
const curr = progress.value;
if (curr !== undefined) {
@@ -343,7 +338,7 @@ export const Controls: React.FC = ({
const handleSkipForward = useCallback(async () => {
if (!settings?.forwardSkipTime) return;
wasPlayingRef.current = isPlaying;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+
try {
const curr = progress.value;
if (curr !== undefined) {
@@ -360,7 +355,6 @@ export const Controls: React.FC = ({
const toggleIgnoreSafeAreas = useCallback(() => {
setIgnoreSafeAreas((prev) => !prev);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}, []);
const memoizedRenderBubble = useCallback(() => {
@@ -439,8 +433,6 @@ export const Controls: React.FC = ({
const gotoItem = await getItemById(api, itemId);
if (!settings || !gotoItem) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
const previousIndexes: previousIndexes = {
subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
audioIndex: audioIndex ? parseInt(audioIndex) : undefined,
@@ -588,7 +580,6 @@ export const Controls: React.FC = ({
)}
{
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
router.back();
}}
className="aspect-square flex flex-col bg-neutral-800/90 rounded-xl items-center justify-center p-2"
diff --git a/hooks/useCreditSkipper.ts b/hooks/useCreditSkipper.ts
index 1430e7c9..5f7a8b34 100644
--- a/hooks/useCreditSkipper.ts
+++ b/hooks/useCreditSkipper.ts
@@ -5,7 +5,6 @@ import { apiAtom } from "@/providers/JellyfinProvider";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { writeToLog } from "@/utils/log";
import { msToSeconds, secondsToMs } from "@/utils/time";
-import * as Haptics from "expo-haptics";
interface CreditTimestamps {
Introduction: {
@@ -79,7 +78,6 @@ export const useCreditSkipper = (
if (!creditTimestamps) return;
console.log(`Skipping credits to ${creditTimestamps.Credits.End}`);
try {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
wrappedSeek(creditTimestamps.Credits.End);
setTimeout(() => {
play();
diff --git a/hooks/useIntroSkipper.ts b/hooks/useIntroSkipper.ts
index 15aaff05..214f4a5a 100644
--- a/hooks/useIntroSkipper.ts
+++ b/hooks/useIntroSkipper.ts
@@ -5,7 +5,6 @@ import { apiAtom } from "@/providers/JellyfinProvider";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { writeToLog } from "@/utils/log";
import { msToSeconds, secondsToMs } from "@/utils/time";
-import * as Haptics from "expo-haptics";
interface IntroTimestamps {
EpisodeId: string;
@@ -78,7 +77,6 @@ export const useIntroSkipper = (
const skipIntro = useCallback(() => {
if (!introTimestamps) return;
try {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
wrappedSeek(introTimestamps.IntroEnd);
setTimeout(() => {
play();
diff --git a/hooks/useMarkAsPlayed.ts b/hooks/useMarkAsPlayed.ts
index ff039cc8..e1b28fe7 100644
--- a/hooks/useMarkAsPlayed.ts
+++ b/hooks/useMarkAsPlayed.ts
@@ -3,7 +3,6 @@ import { markAsNotPlayed } from "@/utils/jellyfin/playstate/markAsNotPlayed";
import { markAsPlayed } from "@/utils/jellyfin/playstate/markAsPlayed";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { useQueryClient } from "@tanstack/react-query";
-import * as Haptics from "expo-haptics";
import { useAtom } from "jotai";
export const useMarkAsPlayed = (item: BaseItemDto) => {
@@ -29,8 +28,6 @@ export const useMarkAsPlayed = (item: BaseItemDto) => {
};
const markAsPlayedStatus = async (played: boolean) => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
// Optimistic update
queryClient.setQueryData(
["item", item.Id],
diff --git a/hooks/useOrientation.ts b/hooks/useOrientation.ts
deleted file mode 100644
index 1ecb31ac..00000000
--- a/hooks/useOrientation.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import orientationToOrientationLock from "@/utils/OrientationLockConverter";
-import * as ScreenOrientation from "expo-screen-orientation";
-import { useEffect, useState } from "react";
-
-export const useOrientation = () => {
- const [orientation, setOrientation] = useState(
- ScreenOrientation.OrientationLock.UNKNOWN
- );
-
- useEffect(() => {
- const orientationSubscription =
- ScreenOrientation.addOrientationChangeListener((event) => {
- setOrientation(
- orientationToOrientationLock(event.orientationInfo.orientation)
- );
- });
-
- ScreenOrientation.getOrientationAsync().then((orientation) => {
- setOrientation(orientationToOrientationLock(orientation));
- });
-
- return () => {
- orientationSubscription.remove();
- };
- }, []);
-
- return { orientation, setOrientation };
-};
diff --git a/hooks/useOrientationSettings.ts b/hooks/useOrientationSettings.ts
deleted file mode 100644
index 85b8a113..00000000
--- a/hooks/useOrientationSettings.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useSettings } from "@/utils/atoms/settings";
-import * as ScreenOrientation from "expo-screen-orientation";
-import { useEffect } from "react";
-
-export const useOrientationSettings = () => {
- const [settings] = useSettings();
-
- useEffect(() => {
- if (settings?.autoRotate) {
- // Don't need to do anything
- } else if (settings?.defaultVideoOrientation) {
- ScreenOrientation.lockAsync(settings.defaultVideoOrientation);
- }
-
- return () => {
- if (settings?.autoRotate) {
- ScreenOrientation.unlockAsync();
- } else {
- ScreenOrientation.lockAsync(
- ScreenOrientation.OrientationLock.PORTRAIT_UP
- );
- }
- };
- }, [settings]);
-};
diff --git a/package.json b/package.json
index 952a50f8..9fee217b 100644
--- a/package.json
+++ b/package.json
@@ -45,20 +45,17 @@
"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-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-updates": "~0.25.27",
- "expo-web-browser": "~13.0.3",
"ffmpeg-kit-react-native": "^6.0.2",
"install": "^0.13.0",
"jotai": "^2.10.1",
@@ -66,7 +63,7 @@
"nativewind": "^2.0.11",
"react": "18.2.0",
"react-dom": "18.2.0",
- "react-native": "npm:react-native-tvos@latest",
+ "react-native": "npm:react-native-tvos@0.74.5-0",
"react-native-awesome-slider": "^2.5.6",
"react-native-bottom-tabs": "0.7.1",
"react-native-circular-progress": "^1.4.1",
@@ -76,7 +73,6 @@
"react-native-gesture-handler": "~2.16.1",
"react-native-get-random-values": "^1.11.0",
"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",
diff --git a/utils/OrientationLockConverter.ts b/utils/OrientationLockConverter.ts
deleted file mode 100644
index 748ffcc6..00000000
--- a/utils/OrientationLockConverter.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Orientation, OrientationLock } from "expo-screen-orientation";
-
-function orientationToOrientationLock(
- orientation: Orientation
-): OrientationLock {
- switch (orientation) {
- case Orientation.PORTRAIT_UP:
- return OrientationLock.PORTRAIT_UP;
- case Orientation.PORTRAIT_DOWN:
- return OrientationLock.PORTRAIT_DOWN;
- case Orientation.LANDSCAPE_LEFT:
- return OrientationLock.LANDSCAPE_LEFT;
- case Orientation.LANDSCAPE_RIGHT:
- return OrientationLock.LANDSCAPE_RIGHT;
- case Orientation.UNKNOWN:
- default:
- return OrientationLock.DEFAULT;
- }
-}
-
-export default orientationToOrientationLock;
diff --git a/utils/atoms/orientation.ts b/utils/atoms/orientation.ts
deleted file mode 100644
index e4680fe3..00000000
--- a/utils/atoms/orientation.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as ScreenOrientation from "expo-screen-orientation";
-import { atom } from "jotai";
-
-export const orientationAtom = atom(
- ScreenOrientation.OrientationLock.PORTRAIT_UP
-);
diff --git a/utils/atoms/settings.ts b/utils/atoms/settings.ts
index f38cee36..a7e77921 100644
--- a/utils/atoms/settings.ts
+++ b/utils/atoms/settings.ts
@@ -1,6 +1,5 @@
import { atom, useAtom } from "jotai";
import { useEffect } from "react";
-import * as ScreenOrientation from "expo-screen-orientation";
import { storage } from "../mmkv";
import { Platform } from "react-native";
import {
@@ -8,22 +7,6 @@ import {
SubtitlePlaybackMode,
} from "@jellyfin/sdk/lib/generated-client";
-export const ScreenOrientationEnum: Record<
- ScreenOrientation.OrientationLock,
- string
-> = {
- [ScreenOrientation.OrientationLock.DEFAULT]: "Default",
- [ScreenOrientation.OrientationLock.ALL]: "All",
- [ScreenOrientation.OrientationLock.PORTRAIT]: "Portrait",
- [ScreenOrientation.OrientationLock.PORTRAIT_UP]: "Portrait Up",
- [ScreenOrientation.OrientationLock.PORTRAIT_DOWN]: "Portrait Down",
- [ScreenOrientation.OrientationLock.LANDSCAPE]: "Landscape",
- [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: "Landscape Left",
- [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: "Landscape Right",
- [ScreenOrientation.OrientationLock.OTHER]: "Other",
- [ScreenOrientation.OrientationLock.UNKNOWN]: "Unknown",
-};
-
export type LibraryOptions = {
display: "row" | "list";
cardStyle: "compact" | "detailed";
@@ -54,7 +37,6 @@ export type Settings = {
subtitleMode: SubtitlePlaybackMode;
rememberSubtitleSelections: boolean;
showHomeTitles: boolean;
- defaultVideoOrientation: ScreenOrientation.OrientationLock;
forwardSkipTime: number;
rewindSkipTime: number;
optimizedVersionsServerUrl?: string | null;
@@ -89,7 +71,6 @@ const loadSettings = (): Settings => {
subtitleMode: SubtitlePlaybackMode.Default,
rememberSubtitleSelections: true,
showHomeTitles: true,
- defaultVideoOrientation: ScreenOrientation.OrientationLock.DEFAULT,
forwardSkipTime: 30,
rewindSkipTime: 10,
optimizedVersionsServerUrl: null,