2025-05-18 14:03:18 -07:00
|
|
|
import { closeAllModals, openModal } from '@mantine/modals';
|
2023-02-08 14:42:13 -08:00
|
|
|
import isElectron from 'is-electron';
|
2023-10-30 19:22:45 -07:00
|
|
|
import { useTranslation } from 'react-i18next';
|
2023-01-03 02:13:40 -08:00
|
|
|
import { useNavigate } from 'react-router';
|
2023-03-30 03:01:31 -07:00
|
|
|
import { Link } from 'react-router-dom';
|
2025-05-18 14:03:18 -07:00
|
|
|
|
|
|
|
|
import packageJson from '../../../../../package.json';
|
|
|
|
|
|
2022-12-19 15:59:14 -08:00
|
|
|
import { ServerList } from '/@/renderer/features/servers';
|
|
|
|
|
import { EditServerForm } from '/@/renderer/features/servers/components/edit-server-form';
|
2023-01-03 02:13:40 -08:00
|
|
|
import { AppRoute } from '/@/renderer/router/routes';
|
2023-05-10 18:20:04 -07:00
|
|
|
import {
|
2025-05-18 14:03:18 -07:00
|
|
|
useAppStoreActions,
|
|
|
|
|
useAuthStoreActions,
|
2023-07-01 19:10:05 -07:00
|
|
|
useCurrentServer,
|
|
|
|
|
useServerList,
|
|
|
|
|
useSidebarStore,
|
2023-05-10 18:20:04 -07:00
|
|
|
} from '/@/renderer/store';
|
2025-06-24 00:04:36 -07:00
|
|
|
import { DropdownMenu } from '/@/shared/components/dropdown-menu/dropdown-menu';
|
|
|
|
|
import { Icon } from '/@/shared/components/icon/icon';
|
2025-05-20 19:23:36 -07:00
|
|
|
import { ServerListItem, ServerType } from '/@/shared/types/domain-types';
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2025-05-18 14:03:18 -07:00
|
|
|
const browser = isElectron() ? window.api.browser : null;
|
|
|
|
|
const localSettings = isElectron() ? window.api.localSettings : null;
|
2023-02-08 14:42:13 -08:00
|
|
|
|
2022-12-19 15:59:14 -08:00
|
|
|
export const AppMenu = () => {
|
2023-10-30 19:22:45 -07:00
|
|
|
const { t } = useTranslation();
|
2023-07-01 19:10:05 -07:00
|
|
|
const navigate = useNavigate();
|
|
|
|
|
const currentServer = useCurrentServer();
|
|
|
|
|
const serverList = useServerList();
|
|
|
|
|
const { setCurrentServer } = useAuthStoreActions();
|
|
|
|
|
const { collapsed } = useSidebarStore();
|
|
|
|
|
const { setSideBar } = useAppStoreActions();
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleSetCurrentServer = (server: ServerListItem) => {
|
|
|
|
|
navigate(AppRoute.HOME);
|
|
|
|
|
setCurrentServer(server);
|
|
|
|
|
};
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleCredentialsModal = async (server: ServerListItem) => {
|
2025-05-18 14:03:18 -07:00
|
|
|
let password: null | string = null;
|
2023-06-13 17:52:51 +00:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
try {
|
|
|
|
|
if (localSettings && server.savePassword) {
|
|
|
|
|
password = await localSettings.passwordGet(server.id);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
openModal({
|
|
|
|
|
children: server && (
|
|
|
|
|
<EditServerForm
|
|
|
|
|
isUpdate
|
2025-05-18 14:03:18 -07:00
|
|
|
onCancel={closeAllModals}
|
2023-07-01 19:10:05 -07:00
|
|
|
password={password}
|
|
|
|
|
server={server}
|
|
|
|
|
/>
|
|
|
|
|
),
|
|
|
|
|
size: 'sm',
|
|
|
|
|
title: `Update session for "${server.name}"`,
|
|
|
|
|
});
|
|
|
|
|
};
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleManageServersModal = () => {
|
|
|
|
|
openModal({
|
|
|
|
|
children: <ServerList />,
|
2024-09-26 12:42:41 +08:00
|
|
|
title: t('page.manageServers.title', { postProcess: 'titleCase' }),
|
2023-07-01 19:10:05 -07:00
|
|
|
});
|
|
|
|
|
};
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleBrowserDevTools = () => {
|
|
|
|
|
browser?.devtools();
|
|
|
|
|
};
|
2023-02-08 14:42:13 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleCollapseSidebar = () => {
|
|
|
|
|
setSideBar({ collapsed: true });
|
|
|
|
|
};
|
2023-05-10 18:20:04 -07:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const handleExpandSidebar = () => {
|
|
|
|
|
setSideBar({ collapsed: false });
|
|
|
|
|
};
|
2023-05-10 18:20:04 -07:00
|
|
|
|
2023-09-22 18:04:15 -07:00
|
|
|
const handleQuit = () => {
|
2023-09-27 02:37:03 -07:00
|
|
|
browser?.quit();
|
2023-09-22 18:04:15 -07:00
|
|
|
};
|
2023-02-08 14:42:13 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="arrowLeftS" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={() => navigate(-1)}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.goBack', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="arrowRightS" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={() => navigate(1)}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.goForward', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
{collapsed ? (
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="panelRightOpen" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={handleExpandSidebar}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.expandSidebar', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
) : (
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="panelRightClose" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={handleCollapseSidebar}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.collapseSidebar', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
)}
|
|
|
|
|
<DropdownMenu.Divider />
|
|
|
|
|
<DropdownMenu.Item
|
|
|
|
|
component={Link}
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="settings" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
to={AppRoute.SETTINGS}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.settings', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="edit" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={handleManageServersModal}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.manageServers', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
2023-05-14 02:01:37 -07:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
<DropdownMenu.Divider />
|
2023-10-30 19:22:45 -07:00
|
|
|
<DropdownMenu.Label>
|
|
|
|
|
{t('page.appMenu.selectServer', { postProcess: 'sentenceCase' })}
|
|
|
|
|
</DropdownMenu.Label>
|
2023-07-01 19:10:05 -07:00
|
|
|
{Object.keys(serverList).map((serverId) => {
|
|
|
|
|
const server = serverList[serverId];
|
|
|
|
|
const isNavidromeExpired =
|
|
|
|
|
server.type === ServerType.NAVIDROME && !server.ndCredential;
|
2023-08-24 18:17:20 -07:00
|
|
|
const isJellyfinExpired = server.type === ServerType.JELLYFIN && !server.credential;
|
2023-07-01 19:10:05 -07:00
|
|
|
const isSessionExpired = isNavidromeExpired || isJellyfinExpired;
|
2023-05-14 02:01:37 -07:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
return (
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
key={`server-${server.id}`}
|
|
|
|
|
leftSection={
|
2023-07-01 19:10:05 -07:00
|
|
|
isSessionExpired ? (
|
2025-06-24 00:04:36 -07:00
|
|
|
<Icon
|
|
|
|
|
fill="error"
|
|
|
|
|
icon="lock"
|
|
|
|
|
/>
|
2023-07-01 19:10:05 -07:00
|
|
|
) : (
|
2025-06-24 00:04:36 -07:00
|
|
|
<Icon
|
|
|
|
|
color={server.id === currentServer?.id ? 'primary' : undefined}
|
|
|
|
|
icon="server"
|
|
|
|
|
/>
|
2023-07-01 19:10:05 -07:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
if (!isSessionExpired) return handleSetCurrentServer(server);
|
|
|
|
|
return handleCredentialsModal(server);
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-06-24 00:04:36 -07:00
|
|
|
{server.name}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
<DropdownMenu.Divider />
|
|
|
|
|
<DropdownMenu.Item
|
|
|
|
|
component="a"
|
|
|
|
|
href="https://github.com/jeffvli/feishin/releases"
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="brandGitHub" />}
|
|
|
|
|
rightSection={<Icon icon="externalLink" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
target="_blank"
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.version', {
|
|
|
|
|
postProcess: 'sentenceCase',
|
|
|
|
|
version: packageJson.version,
|
|
|
|
|
})}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
2023-09-22 18:04:15 -07:00
|
|
|
{isElectron() && (
|
2023-07-01 19:10:05 -07:00
|
|
|
<>
|
|
|
|
|
<DropdownMenu.Divider />
|
|
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="appWindow" />}
|
2023-07-01 19:10:05 -07:00
|
|
|
onClick={handleBrowserDevTools}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.openBrowserDevtools', { postProcess: 'sentenceCase' })}
|
2023-07-01 19:10:05 -07:00
|
|
|
</DropdownMenu.Item>
|
2023-09-22 18:04:15 -07:00
|
|
|
<DropdownMenu.Item
|
2025-06-24 00:04:36 -07:00
|
|
|
leftSection={<Icon icon="x" />}
|
2023-09-22 18:04:15 -07:00
|
|
|
onClick={handleQuit}
|
|
|
|
|
>
|
2023-10-30 19:22:45 -07:00
|
|
|
{t('page.appMenu.quit', { postProcess: 'sentenceCase' })}
|
2023-09-22 18:04:15 -07:00
|
|
|
</DropdownMenu.Item>
|
2023-07-01 19:10:05 -07:00
|
|
|
</>
|
|
|
|
|
)}
|
2023-02-08 14:42:13 -08:00
|
|
|
</>
|
2023-07-01 19:10:05 -07:00
|
|
|
);
|
2022-12-19 15:59:14 -08:00
|
|
|
};
|