mirror of
https://github.com/anultravioletaurora/Jellify.git
synced 2025-12-30 10:20:00 -06:00
Building out front end to start wiring everything up
This commit is contained in:
15
App.tsx
15
App.tsx
@@ -14,7 +14,6 @@ import {
|
||||
Colors,
|
||||
} from 'react-native/Libraries/NewAppScreen';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import { usePlayer } from './player/queries';
|
||||
import Login from './components/Login/component';
|
||||
import Player from './components/Player/component';
|
||||
@@ -60,9 +59,6 @@ function App(): React.JSX.Element {
|
||||
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
|
||||
};
|
||||
|
||||
|
||||
const RootStack = createStackNavigator();
|
||||
|
||||
return (
|
||||
<NavigationContainer>
|
||||
<SafeAreaView style={backgroundStyle}>
|
||||
@@ -70,14 +66,9 @@ const RootStack = createStackNavigator();
|
||||
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
|
||||
backgroundColor={backgroundStyle.backgroundColor}
|
||||
/>
|
||||
<RootStack.Navigator>
|
||||
<RootStack.Group>
|
||||
<RootStack.Screen name="Jellify" component={Jellify} />
|
||||
</RootStack.Group>
|
||||
<RootStack.Group screenOptions={{ presentation: 'modal' }}>
|
||||
<RootStack.Screen name="Player" component={Player} />
|
||||
</RootStack.Group>
|
||||
</RootStack.Navigator>
|
||||
isAuthenticated ? (
|
||||
<Jellify />
|
||||
) ? <Login />
|
||||
</SafeAreaView>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
12
api/mutators/auth.ts
Normal file
12
api/mutators/auth.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { usePublicApi } from "../queries";
|
||||
import { useServerUrl } from "../queries/storage";
|
||||
import { JellyfinCredentials } from "../types/jellyfin-credentials";
|
||||
import { MutationKeys } from "../../enums/mutation-keys";
|
||||
|
||||
export const authenticateWithCredentials = useMutation({
|
||||
mutationKey: [MutationKeys.AuthenticationWithCredentials],
|
||||
mutationFn: (credentials: JellyfinCredentials) => {
|
||||
return usePublicApi(useServerUrl.data!).data!.authenticateUserByName(credentials.username, credentials.password!);
|
||||
},
|
||||
})
|
||||
@@ -27,6 +27,6 @@ export const serverUrl = useMutation({
|
||||
export const credentials = useMutation({
|
||||
mutationKey: [MutationKeys.Credentials],
|
||||
mutationFn: (credentials: JellyfinCredentials) => {
|
||||
return Keychain.setInternetCredentials(useServerUrl.data!, credentials.username, credentials.accessToken);
|
||||
return Keychain.setInternetCredentials(useServerUrl.data!, credentials.username, credentials.accessToken!);
|
||||
},
|
||||
});
|
||||
@@ -18,6 +18,13 @@ export const client : Jellyfin = new Jellyfin({
|
||||
}
|
||||
});
|
||||
|
||||
export const usePublicApi = (serverUrl: string) => useQuery({
|
||||
queryKey: [QueryKeys.PublicApi, serverUrl],
|
||||
queryFn: ({ queryKey }) => {
|
||||
return client.createApi(serverUrl);
|
||||
}
|
||||
})
|
||||
|
||||
export const useApi = useQuery({
|
||||
queryKey: [QueryKeys.Api],
|
||||
queryFn: () => {
|
||||
|
||||
11
api/queries/public.ts
Normal file
11
api/queries/public.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { QueryKeys } from "../../enums/query-keys";
|
||||
import { usePublicApi } from "../queries";
|
||||
import { getSystemApi } from "@jellyfin/sdk/lib/utils/api/system-api";
|
||||
|
||||
export const usePublicSystemInfo = (serverUrl: string) => useQuery({
|
||||
queryKey: [QueryKeys.PublicSystemInfo, serverUrl],
|
||||
queryFn: ({ queryKey }) => {
|
||||
return getSystemApi(usePublicApi(queryKey[1]).data!).getPublicSystemInfo()
|
||||
}
|
||||
});
|
||||
@@ -1,10 +1,12 @@
|
||||
|
||||
export class JellyfinCredentials {
|
||||
username: string;
|
||||
accessToken: string;
|
||||
password?: string | undefined;
|
||||
accessToken?: string | undefined;
|
||||
|
||||
constructor(username: string, accessToken: string) {
|
||||
constructor(username: string, password?: string | undefined, accessToken?: string | undefined) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,22 @@
|
||||
import { createStackNavigator } from "@react-navigation/stack";
|
||||
import { Text } from "react-native";
|
||||
import SignIn from "./helpers/sign-in";
|
||||
|
||||
|
||||
export default function Login(): React.JSX.Element {
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
return (
|
||||
<Text></Text>
|
||||
<Stack.Screen
|
||||
name="SignIn"
|
||||
component={SignIn}
|
||||
options={{
|
||||
title: 'Welcome to Jellify',
|
||||
// When logging out, a pop animation feels intuitive
|
||||
// You can remove this if you want the default 'push' animation
|
||||
animationTypeForReplace: 'pop',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
0
components/Login/helpers/quick-connect.tsx
Normal file
0
components/Login/helpers/quick-connect.tsx
Normal file
0
components/Login/helpers/server-address.tsx
Normal file
0
components/Login/helpers/server-address.tsx
Normal file
30
components/Login/helpers/server-authentication.tsx
Normal file
30
components/Login/helpers/server-authentication.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import { View, TextInput, Button } from "react-native";
|
||||
import { authenticateWithCredentials } from "../../../api/mutators/auth";
|
||||
|
||||
|
||||
export default function ServerAuthentication(): React.JSX.Element {
|
||||
const [username, setUsername] = React.useState('');
|
||||
const [password, setPassword] = React.useState('');
|
||||
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
placeholder="Username"
|
||||
value={username}
|
||||
onChangeText={setUsername}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Password"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
/>
|
||||
<Button title="Sign in" onPress={() => signInHandler(username, password)} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function signInHandler(username: string, password: string) {
|
||||
return authenticateWithCredentials.mutate({username, password})
|
||||
}
|
||||
0
components/Login/helpers/server-library.tsx
Normal file
0
components/Login/helpers/server-library.tsx
Normal file
8
components/Login/helpers/sign-in.tsx
Normal file
8
components/Login/helpers/sign-in.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Text } from "react-native";
|
||||
|
||||
export default function SignIn(): React.JSX.Element {
|
||||
|
||||
return (
|
||||
<Text></Text>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,19 @@
|
||||
import { createStackNavigator } from "@react-navigation/stack";
|
||||
import { Text } from "react-native";
|
||||
import Player from "./Player/component";
|
||||
|
||||
export default function Jellify(): React.JSX.Element {
|
||||
|
||||
const RootStack = createStackNavigator();
|
||||
|
||||
return (
|
||||
<Text></Text>
|
||||
<RootStack.Navigator>
|
||||
<RootStack.Group>
|
||||
<RootStack.Screen name="Jellify" component={Jellify} />
|
||||
</RootStack.Group>
|
||||
<RootStack.Group screenOptions={{ presentation: 'modal' }}>
|
||||
<RootStack.Screen name="Player" component={Player} />
|
||||
</RootStack.Group>
|
||||
</RootStack.Navigator>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export enum MutationKeys {
|
||||
AuthenticationWithCredentials = "AUTH_WITH_CREDS",
|
||||
AccessToken = "ACCESS_TOKEN",
|
||||
Credentials = "CREDENTIALS",
|
||||
ServerUrl = "SERVER_URL"
|
||||
ServerUrl = "SERVER_URL",
|
||||
}
|
||||
@@ -17,4 +17,6 @@ export enum QueryKeys {
|
||||
ReportPlaybackStarted = "REPORT_PLAYBACK_STARTED",
|
||||
ReportPlaybackStopped = "REPORT_PLAYBACK_STOPPED",
|
||||
ServerUrl = "SERVER_URL",
|
||||
PublicSystemInfo = "PublicSystemInfo",
|
||||
PublicApi = "PublicApi",
|
||||
}
|
||||
Reference in New Issue
Block a user