forked from Ninjalama/streamyfin_mirror
fix: separate item and show bar state
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import {
|
||||
currentlyPlayingItemAtom,
|
||||
playingAtom,
|
||||
showCurrentlyPlayingBarAtom,
|
||||
} from "@/utils/atoms/playState";
|
||||
import { Api, Jellyfin } from "@jellyfin/sdk";
|
||||
import { UserDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { isLoaded } from "expo-font";
|
||||
import { router, useSegments } from "expo-router";
|
||||
import { atom, useAtom } from "jotai";
|
||||
import React, {
|
||||
@@ -21,6 +25,7 @@ interface Server {
|
||||
|
||||
export const apiAtom = atom<Api | null>(null);
|
||||
export const userAtom = atom<UserDto | null>(null);
|
||||
export const wsAtom = atom<WebSocket | null>(null);
|
||||
|
||||
interface JellyfinContextValue {
|
||||
discoverServers: (url: string) => Promise<Server[]>;
|
||||
@@ -31,7 +36,7 @@ interface JellyfinContextValue {
|
||||
}
|
||||
|
||||
const JellyfinContext = createContext<JellyfinContextValue | undefined>(
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
const getOrSetDeviceId = async () => {
|
||||
@@ -49,6 +54,15 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [jellyfin, setJellyfin] = useState<Jellyfin | undefined>(undefined);
|
||||
const [deviceId, setDeviceId] = useState<string | undefined>(undefined);
|
||||
const [isConnected, setIsConnected] = useState<boolean>(false);
|
||||
const [playing, setPlaying] = useAtom(playingAtom);
|
||||
const [currentlyPlaying, setCurrentlyPlaying] = useAtom(
|
||||
currentlyPlayingItemAtom
|
||||
);
|
||||
const [showCurrentlyPlayingBar, setShowCurrentlyPlayingBar] = useAtom(
|
||||
showCurrentlyPlayingBarAtom
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@@ -56,19 +70,85 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
setJellyfin(
|
||||
() =>
|
||||
new Jellyfin({
|
||||
clientInfo: { name: "Streamyfin", version: "0.6.1" },
|
||||
clientInfo: { name: "Streamyfin", version: "0.6.2" },
|
||||
deviceInfo: { name: Platform.OS === "ios" ? "iOS" : "Android", id },
|
||||
}),
|
||||
})
|
||||
);
|
||||
setDeviceId(id);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const [api, setApi] = useAtom(apiAtom);
|
||||
const [user, setUser] = useAtom(userAtom);
|
||||
const [ws, setWs] = useAtom(wsAtom);
|
||||
|
||||
useEffect(() => {
|
||||
if (!deviceId || !api) return;
|
||||
|
||||
const url = `wss://${api?.basePath
|
||||
.replace("https://", "")
|
||||
.replace("http://", "")}/socket?api_key=${
|
||||
api?.accessToken
|
||||
}&deviceId=${deviceId}`;
|
||||
|
||||
console.log("WS", url);
|
||||
|
||||
const newWebSocket = new WebSocket(url);
|
||||
|
||||
let keepAliveInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
newWebSocket.onopen = () => {
|
||||
setIsConnected(true);
|
||||
// Start sending "KeepAlive" message every 30 seconds
|
||||
keepAliveInterval = setInterval(() => {
|
||||
if (newWebSocket.readyState === WebSocket.OPEN) {
|
||||
newWebSocket.send(JSON.stringify({ MessageType: "KeepAlive" }));
|
||||
console.log("KeepAlive message sent");
|
||||
}
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
newWebSocket.onmessage = (e) => {
|
||||
const json = JSON.parse(e.data);
|
||||
const command = json?.Data?.Command;
|
||||
|
||||
// On PlayPause
|
||||
if (command === "PlayPause") {
|
||||
console.log("Command ~ PlayPause");
|
||||
setPlaying((state) => !state);
|
||||
} else if (command === "Stop") {
|
||||
console.log("Command ~ Stop");
|
||||
setPlaying(false);
|
||||
setShowCurrentlyPlayingBar(false);
|
||||
}
|
||||
};
|
||||
|
||||
newWebSocket.onerror = (e) => {
|
||||
console.error("WebSocket error:", e);
|
||||
setIsConnected(false);
|
||||
};
|
||||
|
||||
newWebSocket.onclose = (e) => {
|
||||
console.log("WebSocket connection closed:", e.reason);
|
||||
if (keepAliveInterval) {
|
||||
clearInterval(keepAliveInterval);
|
||||
}
|
||||
};
|
||||
|
||||
setWs(newWebSocket);
|
||||
|
||||
return () => {
|
||||
if (keepAliveInterval) {
|
||||
clearInterval(keepAliveInterval);
|
||||
}
|
||||
newWebSocket.close();
|
||||
};
|
||||
}, [api, deviceId]);
|
||||
|
||||
const discoverServers = async (url: string): Promise<Server[]> => {
|
||||
const servers =
|
||||
await jellyfin?.discovery.getRecommendedServerCandidates(url);
|
||||
const servers = await jellyfin?.discovery.getRecommendedServerCandidates(
|
||||
url
|
||||
);
|
||||
return servers?.map((server) => ({ address: server.address })) || [];
|
||||
};
|
||||
|
||||
@@ -144,7 +224,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
const token = await AsyncStorage.getItem("token");
|
||||
const serverUrl = await AsyncStorage.getItem("serverUrl");
|
||||
const user = JSON.parse(
|
||||
(await AsyncStorage.getItem("user")) as string,
|
||||
(await AsyncStorage.getItem("user")) as string
|
||||
) as UserDto;
|
||||
|
||||
if (serverUrl && token && user.Id && jellyfin) {
|
||||
|
||||
Reference in New Issue
Block a user