mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
Add session refresh handler
This commit is contained in:
@@ -5,7 +5,7 @@ import { useFocusTrap } from '@mantine/hooks';
|
||||
import { jellyfinApi } from '/@/api/jellyfin.api';
|
||||
import { navidromeApi } from '/@/api/navidrome.api';
|
||||
import { subsonicApi } from '/@/api/subsonic.api';
|
||||
import type { AuthResponse } from '/@/api/types';
|
||||
import type { AuthenticationResponse } from '/@/api/types';
|
||||
import { ServerType } from '/@/types';
|
||||
import { Button, PasswordInput, TextInput, SegmentedControl, toast } from '/@/components';
|
||||
import { useAuthStoreActions } from '/@/store';
|
||||
@@ -56,10 +56,9 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const data: AuthResponse = await authFunction({
|
||||
const data: AuthenticationResponse = await authFunction(values.url, {
|
||||
legacy: values.legacyAuth,
|
||||
password: values.password,
|
||||
url: values.url,
|
||||
username: values.username,
|
||||
});
|
||||
|
||||
@@ -70,6 +69,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
|
||||
ndCredential: data.ndCredential,
|
||||
type: values.type,
|
||||
url: values.url,
|
||||
userId: data.userId,
|
||||
username: data.username,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Checkbox, Stack, Group } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { closeAllModals } from '@mantine/modals';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import { RiInformationLine } from 'react-icons/ri';
|
||||
import { ServerType } from '/@/types';
|
||||
@@ -10,9 +11,10 @@ import { useAuthStoreActions } from '/@/store';
|
||||
import { jellyfinApi } from '/@/api/jellyfin.api';
|
||||
import { navidromeApi } from '/@/api/navidrome.api';
|
||||
import { subsonicApi } from '/@/api/subsonic.api';
|
||||
import type { AuthResponse } from '/@/api/types';
|
||||
import type { AuthenticationResponse } from '/@/api/types';
|
||||
|
||||
interface EditServerFormProps {
|
||||
isUpdate?: boolean;
|
||||
onCancel: () => void;
|
||||
server: ServerListItem;
|
||||
}
|
||||
@@ -23,8 +25,8 @@ const AUTH_FUNCTIONS = {
|
||||
[ServerType.SUBSONIC]: subsonicApi.authenticate,
|
||||
};
|
||||
|
||||
export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
|
||||
const { updateServer } = useAuthStoreActions();
|
||||
export const EditServerForm = ({ isUpdate, server, onCancel }: EditServerFormProps) => {
|
||||
const { updateServer, setCurrentServer } = useAuthStoreActions();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const form = useForm({
|
||||
@@ -52,14 +54,13 @@ export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const data: AuthResponse = await authFunction({
|
||||
const data: AuthenticationResponse = await authFunction(values.url, {
|
||||
legacy: values.legacyAuth,
|
||||
password: values.password,
|
||||
url: values.url,
|
||||
username: values.username,
|
||||
});
|
||||
|
||||
updateServer(server.id, {
|
||||
const serverItem = {
|
||||
credential: data.credential,
|
||||
id: nanoid(),
|
||||
name: values.name,
|
||||
@@ -67,7 +68,10 @@ export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
|
||||
type: values.type,
|
||||
url: values.url,
|
||||
username: data.username,
|
||||
});
|
||||
};
|
||||
|
||||
updateServer(server.id, serverItem);
|
||||
setCurrentServer(serverItem);
|
||||
|
||||
toast.success({ message: 'Server updated' });
|
||||
} catch (err: any) {
|
||||
@@ -76,6 +80,7 @@ export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
if (isUpdate) closeAllModals();
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,46 +1,41 @@
|
||||
import { Group } from '@mantine/core';
|
||||
import { openModal } from '@mantine/modals';
|
||||
import { openModal, closeAllModals } from '@mantine/modals';
|
||||
import {
|
||||
RiMenu3Fill,
|
||||
RiSearch2Line,
|
||||
RiSettings2Fill,
|
||||
RiSettings2Line,
|
||||
RiEdit2Line,
|
||||
RiLockLine,
|
||||
} from 'react-icons/ri';
|
||||
import { JFAlbumListSort } from '/@/api/jellyfin.types';
|
||||
import { NDAlbumListSort } from '/@/api/navidrome.types';
|
||||
import { SortOrder } from '/@/api/types';
|
||||
import { Button, DropdownMenu, Text } from '/@/components';
|
||||
import { ServerList } from '/@/features/servers';
|
||||
import { Settings } from '/@/features/settings';
|
||||
import type { ServerListItem } from '/@/store';
|
||||
import { useAppStore } from '/@/store';
|
||||
import { useAppStoreActions } from '/@/store';
|
||||
import { useAuthStoreActions, useCurrentServer, useServerList } from '/@/store';
|
||||
import { ServerType } from '/@/types';
|
||||
import { EditServerForm } from '/@/features/servers/components/edit-server-form';
|
||||
|
||||
export const AppMenu = () => {
|
||||
const currentServer = useCurrentServer();
|
||||
const serverList = useServerList();
|
||||
const { setCurrentServer } = useAuthStoreActions();
|
||||
const { setPage } = useAppStoreActions();
|
||||
|
||||
const handleSetCurrentServer = (server: ServerListItem) => {
|
||||
setCurrentServer(server);
|
||||
};
|
||||
|
||||
const sortBy =
|
||||
server.type === ServerType.NAVIDROME ? NDAlbumListSort.NAME : JFAlbumListSort.NAME;
|
||||
|
||||
// Reset filter when switching servers
|
||||
setPage('albums', {
|
||||
list: {
|
||||
...useAppStore.getState().albums.list,
|
||||
filter: {
|
||||
...useAppStore.getState().albums.list.filter,
|
||||
sortBy,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
},
|
||||
const handleCredentialsModal = (server: ServerListItem) => {
|
||||
openModal({
|
||||
children: server && (
|
||||
<EditServerForm
|
||||
isUpdate
|
||||
server={server}
|
||||
onCancel={closeAllModals}
|
||||
/>
|
||||
),
|
||||
size: 'sm',
|
||||
title: `Update session for "${server.name}"`,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -86,11 +81,26 @@ export const AppMenu = () => {
|
||||
<DropdownMenu.Dropdown>
|
||||
<DropdownMenu.Label>Select a server</DropdownMenu.Label>
|
||||
{serverList.map((s) => {
|
||||
const isNavidromeExpired = s.type === ServerType.NAVIDROME && !s.ndCredential;
|
||||
const isJellyfinExpired = false;
|
||||
const isSessionExpired = isNavidromeExpired || isJellyfinExpired;
|
||||
|
||||
return (
|
||||
<DropdownMenu.Item
|
||||
key={`server-${s.id}`}
|
||||
$isActive={s.id === currentServer?.id}
|
||||
onClick={() => handleSetCurrentServer(s)}
|
||||
icon={
|
||||
isSessionExpired && (
|
||||
<RiLockLine
|
||||
color="var(--danger-color)"
|
||||
size={12}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
if (!isSessionExpired) return handleSetCurrentServer(s);
|
||||
handleCredentialsModal(s);
|
||||
}}
|
||||
>
|
||||
<Group>{s.name}</Group>
|
||||
</DropdownMenu.Item>
|
||||
|
||||
@@ -3,7 +3,11 @@ import { nanoid } from 'nanoid/non-secure';
|
||||
import create from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { ServerType } from '../types';
|
||||
import { JFAlbumListSort } from '/@/api/jellyfin.types';
|
||||
import { NDAlbumListSort } from '/@/api/navidrome.types';
|
||||
import { SortOrder } from '/@/api/types';
|
||||
import { useAppStore } from '/@/store/app.store';
|
||||
import { ServerType } from '/@/types';
|
||||
|
||||
export type ServerListItem = {
|
||||
credential: string;
|
||||
@@ -12,6 +16,7 @@ export type ServerListItem = {
|
||||
ndCredential?: string;
|
||||
type: ServerType;
|
||||
url: string;
|
||||
userId: string | null;
|
||||
username: string;
|
||||
};
|
||||
|
||||
@@ -25,7 +30,7 @@ export interface AuthSlice extends AuthState {
|
||||
actions: {
|
||||
addServer: (args: ServerListItem) => void;
|
||||
deleteServer: (id: string) => void;
|
||||
setCurrentServer: (server: ServerListItem) => void;
|
||||
setCurrentServer: (server: ServerListItem | null) => void;
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => void;
|
||||
};
|
||||
}
|
||||
@@ -48,12 +53,32 @@ export const useAuthStore = create<AuthSlice>()(
|
||||
}
|
||||
});
|
||||
},
|
||||
setCurrentServer: (server) => set({ currentServer: server }),
|
||||
setCurrentServer: (server) => {
|
||||
set((state) => {
|
||||
state.currentServer = server;
|
||||
|
||||
if (server) {
|
||||
useAppStore.getState().actions.setPage('albums', {
|
||||
list: {
|
||||
...useAppStore.getState().albums.list,
|
||||
filter: {
|
||||
...useAppStore.getState().albums.list.filter,
|
||||
sortBy:
|
||||
server.type === ServerType.NAVIDROME
|
||||
? NDAlbumListSort.NAME
|
||||
: JFAlbumListSort.NAME,
|
||||
sortOrder: SortOrder.ASC,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
updateServer: (id: string, args: Partial<ServerListItem>) => {
|
||||
set((state) => {
|
||||
const server = state.serverList.find((server) => server.id === id);
|
||||
if (server) {
|
||||
Object.assign(server, args);
|
||||
Object.assign(server, { ...server, ...args });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user