From 2240952b8f09eee26e708a8ea20ba3fd079c569f Mon Sep 17 00:00:00 2001 From: Chewbacca Date: Mon, 3 Apr 2023 09:51:22 -0400 Subject: [PATCH] Add animation to AuthorizeRejectButton comp --- .../components/authorize-reject-buttons.tsx | 83 ++++++++++++++----- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/app/soapbox/components/authorize-reject-buttons.tsx b/app/soapbox/components/authorize-reject-buttons.tsx index 9edd44189..a785c31ea 100644 --- a/app/soapbox/components/authorize-reject-buttons.tsx +++ b/app/soapbox/components/authorize-reject-buttons.tsx @@ -14,6 +14,23 @@ interface IAuthorizeRejectButtons { 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', @@ -21,6 +38,9 @@ const AuthorizeRejectButtons: React.FC = ({ onAuthorize action: () => Promise | unknown, ): void { if (state === present) { + if (interval.current) { + clearInterval(interval.current); + } if (timeout.current) { clearTimeout(timeout.current); } @@ -37,6 +57,7 @@ const AuthorizeRejectButtons: React.FC = ({ onAuthorize if (typeof countdown === 'number') { setState(present); timeout.current = setTimeout(doAction, countdown); + startProgressInterval(); } else { doAction(); } @@ -46,11 +67,28 @@ const AuthorizeRejectButtons: React.FC = ({ onAuthorize 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); + } }; }, []); @@ -72,6 +110,7 @@ const AuthorizeRejectButtons: React.FC = ({ onAuthorize action={handleReject} isLoading={state === 'rejecting'} disabled={state === 'authorizing'} + style={renderStyle('rejecting')} /> = ({ onAuthorize action={handleAuthorize} isLoading={state === 'authorizing'} disabled={state === 'rejecting'} + style={renderStyle('authorizing')} /> ); @@ -105,33 +145,34 @@ interface IAuthorizeRejectButton { action(): void isLoading?: boolean disabled?: boolean + style: React.CSSProperties } -const AuthorizeRejectButton: React.FC = ({ theme, icon, action, isLoading, disabled }) => { +const AuthorizeRejectButton: React.FC = ({ theme, icon, action, isLoading, style, disabled }) => { return (
- - {(isLoading) && ( -
+ - )} +
); };