1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-20 02:00:49 +00:00
strimertul/frontend/src/ui/pages/TwitchSettings.tsx
2022-01-11 11:59:48 +01:00

375 lines
11 KiB
TypeScript

import { CheckIcon } from '@radix-ui/react-icons';
import React from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useModule, useStatus } from '../../lib/react-utils';
import apiReducer, { modules } from '../../store/api/reducer';
import DefinitionTable from '../components/DefinitionTable';
import SaveButton from '../components/utils/SaveButton';
import {
Checkbox,
CheckboxIndicator,
Field,
FieldNote,
FlexRow,
InputBox,
Label,
PageContainer,
PageHeader,
PageTitle,
SectionHeader,
styled,
TabButton,
TabContainer,
TabContent,
TabList,
TextBlock,
} from '../theme';
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',
},
});
function TwitchBotSettings() {
const [botConfig, setBotConfig, loadStatus] = useModule(
modules.twitchBotConfig,
);
const [twitchConfig, setTwitchConfig] = useModule(modules.twitchConfig);
const status = useStatus(loadStatus.save);
const dispatch = useDispatch();
const { t } = useTranslation();
const active = twitchConfig?.enable_bot ?? false;
return (
<form
onSubmit={(ev) => {
dispatch(setTwitchConfig(twitchConfig));
dispatch(setBotConfig(botConfig));
ev.preventDefault();
}}
>
<TextBlock>{t('pages.twitch-settings.bot-settings-copy')}</TextBlock>
<Field>
<FlexRow spacing={1}>
<Checkbox
checked={active}
onCheckedChange={(ev) =>
dispatch(
apiReducer.actions.twitchConfigChanged({
...twitchConfig,
enable_bot: !!ev,
}),
)
}
id="enable-bot"
>
<CheckboxIndicator>{active && <CheckIcon />}</CheckboxIndicator>
</Checkbox>
<Label htmlFor="enable-bot">
{t('pages.twitch-settings.enable-bot')}
</Label>
</FlexRow>
</Field>
<Field size="fullWidth">
<Label htmlFor="bot-channel">
{t('pages.twitch-settings.bot-channel')}
</Label>
<InputBox
type="text"
id="bot-channel"
required={active}
disabled={!active || status?.type === 'pending'}
value={botConfig?.channel ?? ''}
onChange={(ev) =>
dispatch(
apiReducer.actions.twitchBotConfigChanged({
...botConfig,
channel: ev.target.value,
}),
)
}
/>
</Field>
<SectionHeader>
{t('pages.twitch-settings.bot-info-header')}
</SectionHeader>
<Field size="fullWidth">
<Label htmlFor="bot-username">
{t('pages.twitch-settings.bot-username')}
</Label>
<InputBox
type="text"
id="bot-username"
required={active}
disabled={!active || status?.type === 'pending'}
value={botConfig?.username ?? ''}
onChange={(ev) =>
dispatch(
apiReducer.actions.twitchBotConfigChanged({
...botConfig,
username: ev.target.value,
}),
)
}
/>
</Field>
<Field size="fullWidth">
<Label htmlFor="bot-oauth">
{t('pages.twitch-settings.bot-oauth')}
</Label>
<InputBox
type="password"
id="bot-oauth"
required={active}
disabled={!active || status?.type === 'pending'}
value={botConfig?.oauth ?? ''}
onChange={(ev) =>
dispatch(
apiReducer.actions.twitchBotConfigChanged({
...botConfig,
oauth: ev.target.value,
}),
)
}
/>
<FieldNote>
<Trans i18nKey="pages.twitch-settings.bot-oauth-note">
{' '}
<a href="https://twitchapps.com/tmi/">
https://twitchapps.com/tmi/
</a>
</Trans>
</FieldNote>
</Field>
<SectionHeader>
{t('pages.twitch-settings.bot-chat-header')}
</SectionHeader>
<TextBlock>{t('pages.twitch-settings.bot-chat-history-desc')}</TextBlock>
<Field>
<FlexRow spacing={1}>
<Checkbox
disabled={!active || status?.type === 'pending'}
checked={botConfig?.chat_keys ?? false}
onCheckedChange={(ev) =>
dispatch(
apiReducer.actions.twitchBotConfigChanged({
...botConfig,
chat_keys: !!ev,
}),
)
}
id="bot-chat-keys"
>
<CheckboxIndicator>{active && <CheckIcon />}</CheckboxIndicator>
</Checkbox>
<Label htmlFor="bot-chat-keys">
{t('pages.twitch-settings.bot-chat-keys')}
</Label>
</FlexRow>
</Field>
<Field size="vertical">
<Label htmlFor="bot-chat-history">
{t('pages.twitch-settings.bot-chat-history')}
</Label>
<FlexRow
css={{
justifyContent: 'flex-start',
gap: '0.8rem',
backgroundColor: '$gray6',
borderRadius: '5px',
paddingRight: '0.8rem',
}}
>
<InputBox
type="number"
id="bot-chat-history"
required={active}
disabled={!active || status?.type === 'pending'}
value={botConfig?.chat_history ?? ''}
css={{
appearance: 'textfield',
width: '4rem',
textAlign: 'center',
}}
onChange={(ev) =>
dispatch(
apiReducer.actions.twitchBotConfigChanged({
...botConfig,
chat_history: ev.target.value,
}),
)
}
/>
{t('pages.twitch-settings.bot-chat-history-suffix')}
</FlexRow>
</Field>
<SaveButton status={status} />
</form>
);
}
function TwitchAPISettings() {
const { t } = useTranslation();
const [httpConfig] = useModule(modules.httpConfig);
const [twitchConfig, setTwitchConfig, loadStatus] = useModule(
modules.twitchConfig,
);
const status = useStatus(loadStatus.save);
const dispatch = useDispatch();
return (
<form
onSubmit={(ev) => {
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">
{' '}
<a href="https://dev.twitch.tv/console/apps/create">
https://dev.twitch.tv/console/apps/create
</a>
</Trans>
</Step>
<Step>
{t('pages.twitch-settings.apiguide-3')}
<DefinitionTable
entries={{
'OAuth Redirect URLs': `http://${
httpConfig?.bind.indexOf(':') > 0
? httpConfig.bind
: `localhost${httpConfig?.bind ?? ':4337'}`
}/oauth`,
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')}
</Label>
<InputBox
type="password"
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>
<SaveButton status={status} />
</form>
);
}
export default function TwitchSettingsPage(): React.ReactElement {
const { t } = useTranslation();
const [twitchConfig, setTwitchConfig] = useModule(modules.twitchConfig);
const dispatch = useDispatch();
const active = twitchConfig?.enabled ?? false;
return (
<PageContainer>
<PageHeader>
<PageTitle>{t('pages.twitch-settings.title')}</PageTitle>
<TextBlock>{t('pages.twitch-settings.subtitle')}</TextBlock>
<Field css={{ paddingTop: '1rem' }}>
<FlexRow spacing={1}>
<Checkbox
checked={active}
onCheckedChange={(ev) =>
dispatch(
setTwitchConfig({
...twitchConfig,
enabled: !!ev,
}),
)
}
id="enable"
>
<CheckboxIndicator>{active && <CheckIcon />}</CheckboxIndicator>
</Checkbox>
<Label htmlFor="enable">{t('pages.twitch-settings.enable')}</Label>
</FlexRow>
</Field>
</PageHeader>
<div style={{ display: active ? '' : 'none' }}>
<TabContainer defaultValue="api-config">
<TabList>
<TabButton value="api-config">
{t('pages.twitch-settings.api-configuration')}
</TabButton>
<TabButton value="bot-settings">
{t('pages.twitch-settings.bot-settings')}
</TabButton>
</TabList>
<TabContent value="api-config">
<TwitchAPISettings />
</TabContent>
<TabContent value="bot-settings">
<TwitchBotSettings />
</TabContent>
</TabContainer>
</div>
</PageContainer>
);
}