1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge pull request #4777 from thornbill/migrate-quick-connect

Migrate quick connect page to react
This commit is contained in:
Bill Thornton 2023-09-18 23:41:02 -04:00 committed by GitHub
commit f14a61c8c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 214 additions and 89 deletions

View file

@ -9,6 +9,8 @@ import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import AppLayout from './AppLayout';
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes';
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes';
import { REDIRECTS } from 'apps/stable/routes/_redirects';
import { toRedirectRoute } from 'components/router/Redirect';
const ExperimentalApp = () => {
return (
@ -38,7 +40,7 @@ const ExperimentalApp = () => {
</Route>
{/* Redirects for old paths */}
<Route path='serveractivity.html' element={<Navigate replace to='/dashboard/activity' />} />
{REDIRECTS.map(toRedirectRoute)}
</Route>
</Routes>
);

View file

@ -140,7 +140,7 @@ const AppUserMenu: FC<AppUserMenuProps> = ({
<Divider />
<MenuItem
component={Link}
to='/mypreferencesquickconnect.html'
to='/quickconnect'
onClick={onMenuClose}
>
<ListItemIcon>

View file

@ -1,6 +1,7 @@
import { AsyncRoute, AsyncRouteType } from '../../../../components/router/AsyncRoute';
export const ASYNC_USER_ROUTES: AsyncRoute[] = [
{ path: 'quickconnect', page: 'quickConnect' },
{ path: 'search.html', page: 'search' },
{ path: 'userprofile.html', page: 'user/userprofile' },
{ path: 'home.html', page: 'home', type: AsyncRouteType.Experimental },

View file

@ -49,12 +49,6 @@ export const LEGACY_USER_ROUTES: LegacyRoute[] = [
controller: 'user/home/index',
view: 'user/home/index.html'
}
}, {
path: 'mypreferencesquickconnect.html',
pageProps: {
controller: 'user/quickConnect/index',
view: 'user/quickConnect/index.html'
}
}, {
path: 'mypreferencesplayback.html',
pageProps: {

View file

@ -10,6 +10,8 @@ import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes';
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes';
import { REDIRECTS } from './routes/_redirects';
import { toRedirectRoute } from 'components/router/Redirect';
const Layout = () => (
<>
@ -53,7 +55,7 @@ const StableApp = () => (
<Route path='*' element={null} />
{/* Redirects for old paths */}
<Route path='/serveractivity.html' element={<Navigate replace to='/dashboard/activity' />} />
{REDIRECTS.map(toRedirectRoute)}
</Route>
</Routes>
);

View file

@ -0,0 +1,6 @@
import type { Redirect } from 'components/router/Redirect';
export const REDIRECTS: Redirect[] = [
{ from: 'mypreferencesquickconnect.html', to: '/quickconnect' },
{ from: 'serveractivity.html', to: '/dashboard/activity' }
];

View file

@ -1,6 +1,7 @@
import { AsyncRoute } from '../../../../components/router/AsyncRoute';
export const ASYNC_USER_ROUTES: AsyncRoute[] = [
{ path: 'quickconnect', page: 'quickConnect' },
{ path: 'search.html', page: 'search' },
{ path: 'userprofile.html', page: 'user/userprofile' }
];

View file

@ -49,12 +49,6 @@ export const LEGACY_USER_ROUTES: LegacyRoute[] = [
controller: 'user/home/index',
view: 'user/home/index.html'
}
}, {
path: 'mypreferencesquickconnect.html',
pageProps: {
controller: 'user/quickConnect/index',
view: 'user/quickConnect/index.html'
}
}, {
path: 'mypreferencesplayback.html',
pageProps: {

View file

@ -0,0 +1,116 @@
import { getQuickConnectApi } from '@jellyfin/sdk/lib/utils/api/quick-connect-api';
import React, { FC, FormEvent, useCallback, useMemo, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import Page from 'components/Page';
import globalize from 'scripts/globalize';
import InputElement from 'elements/InputElement';
import ButtonElement from 'elements/ButtonElement';
import { useApi } from 'hooks/useApi';
import './quickConnect.scss';
const QuickConnectPage: FC = () => {
const { api, user } = useApi();
const [ searchParams ] = useSearchParams();
// eslint-disable-next-line react-hooks/exhaustive-deps
const initialValue = useMemo(() => searchParams.get('code') ?? '', []);
const [ code, setCode ] = useState(initialValue);
const [ error, setError ] = useState<string>();
const [ success, setSuccess ] = useState(false);
const onCodeChange = useCallback((value: string) => {
setCode(value);
}, []);
const onSubmitCode = useCallback((e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setError(undefined);
const form = e.currentTarget;
if (!form.checkValidity()) {
setError('QuickConnectInvalidCode');
return;
}
if (!api) {
console.error('[QuickConnect] cannot authorize, missing api instance');
setError('UnknownError');
return;
}
const userId = searchParams.get('userId') ?? user?.Id;
const normalizedCode = code.replace(/\s/g, '');
console.log('[QuickConnect] authorizing code %s as user %s', normalizedCode, userId);
getQuickConnectApi(api)
.authorizeQuickConnect({
code: normalizedCode,
userId
})
.then(() => {
setSuccess(true);
})
.catch(() => {
setError('QuickConnectAuthorizeFail');
});
}, [api, code, searchParams, user?.Id]);
return (
<Page
id='quickConnectPreferencesPage'
title={globalize.translate('QuickConnect')}
className='mainAnimatedPage libraryPage userPreferencesPage noSecondaryNavPage'
>
<div className='padded-left padded-right padded-bottom-page'>
<form onSubmit={onSubmitCode}>
<div className='verticalSection'>
<h2 className='sectionTitle'>
{globalize.translate('QuickConnect')}
</h2>
<div>
{globalize.translate('QuickConnectDescription')}
</div>
<br />
{error && (
<div className='quickConnectError'>
{globalize.translate(error)}
</div>
)}
{success ? (
<div style={{ textAlign: 'center' }}>
<p>
{globalize.translate('QuickConnectAuthorizeSuccess')}
</p>
<Link to='/home.html' className='button-link emby-button'>
{globalize.translate('GoHome')}
</Link>
</div>
) : (
<>
<InputElement
containerClassName='inputContainer'
initialValue={initialValue}
onChange={onCodeChange}
id='txtQuickConnectCode'
label='LabelQuickConnectCode'
type='text'
options="inputmode='numeric' pattern='[0-9\s]*' minlength='6' required autocomplete='off'"
/>
<ButtonElement
type='submit'
className='raised button-submit block'
title={globalize.translate('Authorize')}
/>
</>
)}
</div>
</form>
</div>
</Page>
);
};
export default QuickConnectPage;

View file

@ -0,0 +1,7 @@
.quickConnectError {
border-radius: 0.2em;
background-color: #160b0b;
color: #f4c7c3;
padding: 0.7em 0.5em;
margin-bottom: 1em;
}