import { PlusIcon } from '@radix-ui/react-icons';
import { TFunction } from 'i18next';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useModule } from '~/lib/react';
import { useAppDispatch } from '~/store';
import { modules } from '~/store/api/reducer';
import { TwitchChatTimer } from '~/store/api/types';
import AlertContent from '../components/AlertContent';
import DialogContent from '../components/DialogContent';
import Interval from '../components/forms/Interval';
import { hours, minutes } from '../components/forms/units';
import MultiInput from '../components/forms/MultiInput';
import {
Button,
Dialog,
DialogActions,
DialogClose,
Field,
FlexRow,
InputBox,
Label,
MultiButton,
NoneText,
PageContainer,
PageHeader,
PageTitle,
styled,
TextBlock,
} from '../theme';
import { Alert, AlertTrigger } from '../theme/alert';
const TimerList = styled('div', { marginTop: '1rem' });
const TimerItemContainer = styled('article', {
backgroundColor: '$gray3',
margin: '0.5rem 0',
padding: '0.5rem',
borderLeft: '5px solid $teal8',
borderRadius: '0.25rem',
borderBottom: '1px solid $gray4',
transition: 'all 50ms',
'&:hover': {
backgroundColor: '$gray3',
},
variants: {
status: {
enabled: {},
disabled: {
borderLeftColor: '$red7',
backgroundColor: '$gray3',
color: '$gray10',
},
},
},
});
const TimerHeader = styled('header', {
display: 'flex',
gap: '0.5rem',
alignItems: 'center',
marginBottom: '0.4rem',
});
const TimerName = styled('span', {
color: '$teal10',
fontWeight: 'bold',
variants: {
status: {
enabled: {},
disabled: {
color: '$gray10',
},
},
},
});
const TimerDescription = styled('span', {
flex: 1,
});
const TimerActions = styled('div', {
display: 'flex',
alignItems: 'center',
gap: '0.25rem',
});
const TimerText = styled('div', {
fontFamily: 'Space Mono',
fontSize: '10pt',
margin: '0 -0.5rem',
marginTop: '0',
marginBottom: '0.3rem',
padding: '0.5rem',
backgroundColor: '$gray4',
lineHeight: '1.2rem',
'&:last-child': {
marginBottom: '-0.5rem',
},
});
function humanTime(t: TFunction<'translation'>, secs: number): string {
const mins = Math.floor(secs / 60);
const hrs = Math.floor(mins / 60);
if (hrs > 0) {
return t('time.x-hours', { time: hrs });
}
if (mins > 0) {
return t('time.x-minutes', { time: mins });
}
return t('time.x-seconds', { time: secs });
}
interface TimerItemProps {
name: string;
item: TwitchChatTimer;
onToggle?: () => void;
onEdit?: () => void;
onDelete?: () => void;
}
function TimerItem({
name,
item,
onToggle,
onEdit,
onDelete,
}: TimerItemProps): React.ReactElement {
const { t } = useTranslation();
return (
{name}
(
{t('pages.bottimers.timer-parameters', {
time: humanTime(t, item.minimum_delay),
messages: item.minimum_chat_activity,
interval: humanTime(t, 300),
})}
)
(onDelete ? onDelete() : null)}
/>
{item.messages?.map((message, index) => (
{message}
))}
);
}
type DialogPrompt =
| { kind: 'new' }
| { kind: 'edit'; name: string; item: TwitchChatTimer };
function TimerDialog({
kind,
name,
item,
onSubmit,
}: {
kind: 'new' | 'edit';
name?: string;
item?: TwitchChatTimer;
onSubmit?: (name: string, item: TwitchChatTimer) => void;
}) {
const [timerConfig] = useModule(modules.twitchChatTimers);
const [timerName, setName] = useState(name ?? '');
const [messages, setMessages] = useState(item?.messages ?? ['']);
const [minDelay, setMinDelay] = useState(item?.minimum_delay ?? 300);
const [minActivity, setMinActivity] = useState(
item?.minimum_chat_activity ?? 5,
);
const { t } = useTranslation();
return (
);
}
export default function TwitchChatTimersPage(): React.ReactElement {
const [timerConfig, setTimerConfig] = useModule(modules.twitchChatTimers);
const [filter, setFilter] = useState('');
const [activeDialog, setActiveDialog] = useState(null);
const { t } = useTranslation();
const dispatch = useAppDispatch();
const filterLC = filter.toLowerCase();
const setTimer = (newName: string, data: TwitchChatTimer): void => {
switch (activeDialog.kind) {
case 'new':
void dispatch(
setTimerConfig({
...timerConfig,
timers: {
...timerConfig.timers,
[newName]: {
...data,
enabled: true,
},
},
}),
);
break;
case 'edit': {
const oldName = activeDialog.name;
void dispatch(
setTimerConfig({
...timerConfig,
timers: {
...timerConfig.timers,
[oldName]: undefined,
[newName]: data,
},
}),
);
break;
}
}
setActiveDialog(null);
};
const deleteTimer = (cmd: string): void => {
void dispatch(
setTimerConfig({
...timerConfig,
timers: {
...timerConfig.timers,
[cmd]: undefined,
},
}),
);
};
const toggleTimer = (cmd: string): void => {
void dispatch(
setTimerConfig({
...timerConfig,
timers: {
...timerConfig.timers,
[cmd]: {
...timerConfig.timers[cmd],
enabled: !timerConfig.timers[cmd].enabled,
},
},
}),
);
};
return (
{t('pages.bottimers.title')}
{t('pages.bottimers.desc')}
setFilter(e.target.value)}
/>
{timerConfig?.timers ? (
Object.keys(timerConfig?.timers ?? {})
?.filter((cmd) => cmd.toLowerCase().includes(filterLC))
.sort()
.map((cmd) => (
toggleTimer(cmd)}
onEdit={() =>
setActiveDialog({
kind: 'edit',
name: cmd,
item: timerConfig.timers[cmd],
})
}
onDelete={() => deleteTimer(cmd)}
/>
))
) : (
{t('pages.bottimers.no-timers')}
)}
);
}