From 67debcd265f9c4f964d00cdfdd4190fc13b77e0e Mon Sep 17 00:00:00 2001 From: Hanif Dwy Putra S Date: Fri, 12 Aug 2022 12:45:33 +0000 Subject: [PATCH] feat(web): reconstruct Signed-off-by: Hanif Dwy Putra S --- apps/web/components/FormInput.tsx | 112 +++++++++++++++++++++--------- apps/web/components/Video.tsx | 81 +++++++-------------- apps/web/pages/index.tsx | 2 +- 3 files changed, 106 insertions(+), 89 deletions(-) diff --git a/apps/web/components/FormInput.tsx b/apps/web/components/FormInput.tsx index 012c27c..b61962a 100644 --- a/apps/web/components/FormInput.tsx +++ b/apps/web/components/FormInput.tsx @@ -23,6 +23,13 @@ export type ExtractedInfoWithProvider = ExtractedInfo & { _url: string; }; +interface StateData { + submitted: boolean; + error?: string | Error; + url: string; + wasSubmit: boolean; +} + const fetcher: Fetcher = (...args) => fetch(...args).then((r) => r.json()); @@ -31,18 +38,22 @@ const fetcher: Fetcher = (...args) => * @return {JSX.Element} */ export const FormInputComponent = (): JSX.Element => { - const [url, setUrl] = React.useState(''); - const [error, setError] = React.useState(); - const [submitted, setSubmit] = React.useState(false); + const [state, setState] = React.useState({ + submitted: false, + error: undefined, + url: '', + wasSubmit: false, + }); + const {data, mutate} = useSWR( - submitted && - (!error || !(error as string).length) && - /^http(s?)(:\/\/)([a-z]+\.)*tiktok\.com\/(.+)$/gi.test(url) + (state.submitted || state.wasSubmit) && + (!state.error || !(state.error as string).length) && + /^http(s?)(:\/\/)([a-z]+\.)*tiktok\.com\/(.+)$/gi.test(state.url) ? [ '/api/download', { method: 'POST', - body: JSON.stringify({url}), + body: JSON.stringify({url: state.url}), }, ] : null, @@ -50,39 +61,59 @@ export const FormInputComponent = (): JSX.Element => { { loadingTimeout: 10_000, refreshInterval: 30_000, - revalidateIfStale: true, revalidateOnMount: false, + onSuccess: () => + setState({ + ...state, + submitted: false, + }), }, ); React.useEffect(() => { if ( - !/^http(s?)(:\/\/)([a-z]+\.)*tiktok\.com\/(.+)$/gi.test(url) && - url.length + !/^http(s?)(:\/\/)([a-z]+\.)*tiktok\.com\/(.+)$/gi.test( + state.url, + ) && + state.url.length ) { - setError(new InvalidUrlError('Invalid TikTok Video URL')); + setState({ + ...state, + error: new InvalidUrlError('Invalid TikTok URL'), + }); } else { // submit event trigger. - if (submitted && !error) { + if (state.submitted && !state.error) { mutate(); } try { - const u = getTikTokURL(url); + const u = getTikTokURL(state.url); if (!u) { - setError(new InvalidUrlError('Invalid TikTok URL')); + setState({ + ...state, + error: new InvalidUrlError('Invalid TikTok URL'), + }); return; } - console.log(u); - setUrl(u); + setState({ + ...state, + url: u, + }); } catch { - setError(new InvalidUrlError('Invalid TikTok Video URL')); + setState({ + ...state, + error: new InvalidUrlError('Invalid TikTok URL'), + }); } - setError(undefined); + setState({ + ...state, + error: undefined, + }); } - }, [url, submitted]); + }, [state.submitted, state.url]); return ( @@ -91,28 +122,42 @@ export const FormInputComponent = (): JSX.Element => { Fill TikTok's Video URL below:

- {error instanceof Error - ? error.name.concat(': '.concat(error.message)) - : error - ? error + {state.error instanceof Error + ? state.error.name.concat( + ': '.concat(state.error.message), + ) + : state.error + ? state.error : ''}

{ event.preventDefault(); - if (!url.length) { - setError('Please fill the URL!'); + if (!state.url.length) { + setState({ + ...state, + error: 'Please fill the URL!', + }); return; } - !error && setSubmit(true); + !state.error && + setState({ + ...state, + submitted: true, + }); }} >
setUrl(event.target.value)} - value={url} + onChange={(event) => + setState({ + ...state, + url: event.target.value, + }) + } + value={state.url} placeholder="e.g: " className="p-3 border border-gray-300 font-sans h-auto w-auto outline-solid-blue-500" /> @@ -121,7 +166,7 @@ export const FormInputComponent = (): JSX.Element => {
@@ -129,14 +174,13 @@ export const FormInputComponent = (): JSX.Element => {
- {submitted && !data ? ( + {state.submitted && !data && (

Wait a minute

- ) : ( - data && - data.video && - data.video.urls.length && + )} + {data && data && data.video && data.video.urls.length && ( + )}
diff --git a/apps/web/components/Video.tsx b/apps/web/components/Video.tsx index e19fa8f..5cc00ae 100644 --- a/apps/web/components/Video.tsx +++ b/apps/web/components/Video.tsx @@ -2,64 +2,37 @@ import React from 'react'; import type {ExtractedInfoWithProvider} from './FormInput'; export const VideoComponent = ({data}: {data: ExtractedInfoWithProvider}) => { + const copyUrl = (url: string) => { + navigator.clipboard.writeText(url); + if (typeof window !== 'undefined') { + window.alert('URL Copied'); + } + }; return ( -

Your Video Is Ready!

-
-
- + This video is downloaded from{' '} + {data.provider}. + {data.caption &&
{data.caption}
} +
+ +
+ {data.video?.urls.map((url, index) => ( + + ))}
-
- -
- {data.music && ( -
-
    -
  • -

    Music:

    -
  • -
  • - Music URL:{' '} - - Click here - -
  • - {data.music.author && ( -
  • - Music Author: {data.music.author} -
  • - )} - {data.music.title && ( -
  • - Music Title: {data.music.title} -
  • - )} -
-
- )}
-

- © Source: {data.provider} -

); }; diff --git a/apps/web/pages/index.tsx b/apps/web/pages/index.tsx index 3774659..1e35b2b 100644 --- a/apps/web/pages/index.tsx +++ b/apps/web/pages/index.tsx @@ -11,7 +11,7 @@ const FormInputComponentDynamic = dynamic( export default () => { return (
-

+

TikTok-DL{' '} Download TikTok Video without watermark and free ads.