import clsx from 'clsx'; import React, { useEffect, useRef, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { HStack, IconButton, Text } from 'soapbox/components/ui'; interface IAuthorizeRejectButtons { onAuthorize(): Promise | unknown; onReject(): Promise | unknown; countdown?: number; } /** Buttons to approve or reject a pending item, usually an account. */ const AuthorizeRejectButtons: React.FC = ({ onAuthorize, onReject, countdown }) => { const [state, setState] = useState<'authorizing' | 'rejecting' | 'authorized' | 'rejected' | 'pending'>('pending'); const timeout = useRef(); const interval = useRef>(); const [progress, setProgress] = useState(0); const startProgressInterval = () => { let startValue = 1; interval.current = setInterval(() => { startValue++; const newValue = startValue * 3.6; // get to 360 (deg) setProgress(newValue); if (newValue >= 360) { clearInterval(interval.current as NodeJS.Timeout); setProgress(0); } }, (countdown as number) / 100); }; function handleAction( present: 'authorizing' | 'rejecting', past: 'authorized' | 'rejected', action: () => Promise | unknown, ): void { if (state === present) { if (interval.current) { clearInterval(interval.current); } if (timeout.current) { clearTimeout(timeout.current); } setState('pending'); } else { const doAction = async () => { try { await action(); setState(past); } catch (e) { if (e) console.error(e); } }; if (typeof countdown === 'number') { setState(present); timeout.current = setTimeout(doAction, countdown); startProgressInterval(); } else { doAction(); } } } const handleAuthorize = async () => handleAction('authorizing', 'authorized', onAuthorize); const handleReject = async () => handleAction('rejecting', 'rejected', onReject); const renderStyle = (selectedState: typeof state) => { if (state === 'authorizing' && selectedState === 'authorizing') { return { background: `conic-gradient(rgb(var(--color-primary-500)) ${progress}deg, rgb(var(--color-primary-500) / 0.1) 0deg)`, }; } else if (state === 'rejecting' && selectedState === 'rejecting') { return { background: `conic-gradient(rgb(var(--color-danger-600)) ${progress}deg, rgb(var(--color-danger-600) / 0.1) 0deg)`, }; } return {}; }; useEffect(() => { return () => { if (timeout.current) { clearTimeout(timeout.current); } if (interval.current) { clearInterval(interval.current); } }; }, []); switch (state) { case 'authorized': return ( } /> ); case 'rejected': return ( } /> ); default: return ( ); } }; interface IActionEmblem { text: React.ReactNode; } const ActionEmblem: React.FC = ({ text }) => { return (
{text}
); }; interface IAuthorizeRejectButton { theme: 'primary' | 'danger'; icon: string; action(): void; isLoading?: boolean; disabled?: boolean; style: React.CSSProperties; } const AuthorizeRejectButton: React.FC = ({ theme, icon, action, isLoading, style, disabled }) => { return (
); }; export { AuthorizeRejectButtons };