mirror of https://git.sr.ht/~ashkeel/strimertul
196 lines
5.7 KiB
TypeScript
196 lines
5.7 KiB
TypeScript
import { useState } from 'react';
|
|
import { Trans, useTranslation } from 'react-i18next';
|
|
import { useModule, useStatus } from '~/lib/react';
|
|
import { useAppDispatch } from '~/store';
|
|
import apiReducer, { modules } from '~/store/api/reducer';
|
|
import { checkTwitchKeys } from '~/lib/twitch';
|
|
import BrowserLink from '../../../components/BrowserLink';
|
|
import DefinitionTable from '../../../components/DefinitionTable';
|
|
import RevealLink from '../../../components/utils/RevealLink';
|
|
import SaveButton from '../../../components/forms/SaveButton';
|
|
import {
|
|
Button,
|
|
ButtonGroup,
|
|
Field,
|
|
InputBox,
|
|
Label,
|
|
PasswordInputBox,
|
|
SectionHeader,
|
|
styled,
|
|
TextBlock,
|
|
} from '../../../theme';
|
|
import AlertContent from '../../../components/AlertContent';
|
|
import { Alert } from '../../../theme/alert';
|
|
|
|
const StepList = styled('ul', {
|
|
lineHeight: '1.5',
|
|
listStyleType: 'none',
|
|
listStylePosition: 'outside',
|
|
});
|
|
const Step = styled('li', {
|
|
marginBottom: '0.5rem',
|
|
paddingLeft: '1rem',
|
|
'&::marker': {
|
|
color: '$teal11',
|
|
content: '▧',
|
|
display: 'inline-block',
|
|
marginLeft: '-0.5rem',
|
|
},
|
|
});
|
|
|
|
type TestResult = { open: boolean; error?: Error };
|
|
|
|
export default function TwitchAPISettings() {
|
|
const { t } = useTranslation();
|
|
const [httpConfig] = useModule(modules.httpConfig);
|
|
const [twitchConfig, setTwitchConfig, loadStatus] = useModule(
|
|
modules.twitchConfig,
|
|
);
|
|
const status = useStatus(loadStatus.save);
|
|
const dispatch = useAppDispatch();
|
|
const [revealClientSecret, setRevealClientSecret] = useState(false);
|
|
const [testing, setTesting] = useState(false);
|
|
const [testResult, setTestResult] = useState<TestResult>({
|
|
open: false,
|
|
});
|
|
|
|
const checkCredentials = async () => {
|
|
setTesting(true);
|
|
if (twitchConfig) {
|
|
try {
|
|
await checkTwitchKeys(
|
|
twitchConfig.api_client_id,
|
|
twitchConfig.api_client_secret,
|
|
);
|
|
setTestResult({ open: true });
|
|
} catch (e: unknown) {
|
|
setTestResult({ open: true, error: e as Error });
|
|
}
|
|
}
|
|
setTesting(false);
|
|
};
|
|
|
|
return (
|
|
<form
|
|
onSubmit={(ev) => {
|
|
void dispatch(setTwitchConfig(twitchConfig));
|
|
ev.preventDefault();
|
|
}}
|
|
>
|
|
<SectionHeader spacing={'none'}>
|
|
{t('pages.twitch-settings.api-subheader')}
|
|
</SectionHeader>
|
|
<TextBlock>{t('pages.twitch-settings.apiguide-1')}</TextBlock>
|
|
<StepList>
|
|
<Step>
|
|
<Trans i18nKey="pages.twitch-settings.apiguide-2">
|
|
{' '}
|
|
<BrowserLink href="https://dev.twitch.tv/console/apps/create">
|
|
https://dev.twitch.tv/console/apps/create
|
|
</BrowserLink>
|
|
</Trans>
|
|
</Step>
|
|
<Step>
|
|
{t('pages.twitch-settings.apiguide-3')}
|
|
|
|
<DefinitionTable
|
|
entries={{
|
|
[t('pages.twitch-settings.app-oauth-redirect-url')]: `http://${
|
|
httpConfig?.bind.indexOf(':') > 0
|
|
? httpConfig.bind
|
|
: `localhost${httpConfig?.bind ?? ':4337'}`
|
|
}/twitch/callback`,
|
|
[t('pages.twitch-settings.app-category')]: 'Broadcasting Suite',
|
|
}}
|
|
/>
|
|
</Step>
|
|
<Step>
|
|
<Trans i18nKey="pages.twitch-settings.apiguide-4">
|
|
{'str1 '}
|
|
<b>str2</b>
|
|
</Trans>
|
|
</Step>
|
|
</StepList>
|
|
<Field size="fullWidth" css={{ marginTop: '2rem' }}>
|
|
<Label htmlFor="clientid">
|
|
{t('pages.twitch-settings.app-client-id')}
|
|
</Label>
|
|
<InputBox
|
|
type="text"
|
|
id="clientid"
|
|
placeholder={t('pages.twitch-settings.app-client-id')}
|
|
required={true}
|
|
value={twitchConfig?.api_client_id ?? ''}
|
|
onChange={(ev) =>
|
|
dispatch(
|
|
apiReducer.actions.twitchConfigChanged({
|
|
...twitchConfig,
|
|
api_client_id: ev.target.value,
|
|
}),
|
|
)
|
|
}
|
|
/>
|
|
</Field>
|
|
|
|
<Field size="fullWidth">
|
|
<Label htmlFor="clientsecret">
|
|
{t('pages.twitch-settings.app-client-secret')}
|
|
<RevealLink
|
|
value={revealClientSecret}
|
|
setter={setRevealClientSecret}
|
|
/>
|
|
</Label>
|
|
<PasswordInputBox
|
|
reveal={revealClientSecret}
|
|
id="clientsecret"
|
|
placeholder={t('pages.twitch-settings.app-client-secret')}
|
|
required={true}
|
|
value={twitchConfig?.api_client_secret ?? ''}
|
|
onChange={(ev) =>
|
|
dispatch(
|
|
apiReducer.actions.twitchConfigChanged({
|
|
...twitchConfig,
|
|
api_client_secret: ev.target.value,
|
|
}),
|
|
)
|
|
}
|
|
/>
|
|
</Field>
|
|
<ButtonGroup>
|
|
<SaveButton status={status} />
|
|
<Button
|
|
type="button"
|
|
onClick={() => {
|
|
void checkCredentials();
|
|
}}
|
|
disabled={testing}
|
|
>
|
|
{t('pages.twitch-settings.test-button')}
|
|
</Button>
|
|
</ButtonGroup>
|
|
<Alert
|
|
defaultOpen={false}
|
|
open={testResult.open}
|
|
onOpenChange={(val: boolean) => {
|
|
setTestResult({ ...testResult, open: val });
|
|
}}
|
|
>
|
|
<AlertContent
|
|
variation={testResult.error ? 'danger' : 'default'}
|
|
description={
|
|
testResult.error
|
|
? t('pages.twitch-settings.test-failed', {
|
|
error: testResult.error.message,
|
|
})
|
|
: t('pages.twitch-settings.test-succeeded')
|
|
}
|
|
actionText={t('form-actions.ok')}
|
|
onAction={() => {
|
|
setTestResult({ ...testResult, open: false });
|
|
}}
|
|
/>
|
|
</Alert>
|
|
</form>
|
|
);
|
|
}
|