diff --git a/apps/web/components/ErrorBoundary.tsx b/apps/web/components/ErrorBoundary.tsx new file mode 100644 index 0000000..15c54e4 --- /dev/null +++ b/apps/web/components/ErrorBoundary.tsx @@ -0,0 +1,40 @@ +import {Component, ReactNode} from 'react'; + +interface Props { + children: ReactNode; + fallback: ReactNode; +} + +interface State { + hasError: boolean; + error?: Error; +} + +/** + * @class ErrorBoundary + */ +export class ErrorBoundary extends Component { + public state: State = { + hasError: false, + }; + + /** + * @param {Error} error an error. + * @return {State} + */ + public static getDerivedStateFromError(error: Error): State { + return {hasError: true, error}; + } + + /** + * Render error. + * @return {JSX.Element} + */ + public render(): JSX.Element { + if (this.state.hasError) { + return this.props.fallback as JSX.Element; + } + + return this.props.children as JSX.Element; + } +} diff --git a/apps/web/components/FormInput.tsx b/apps/web/components/FormInput.tsx index b01011d..2a583ff 100644 --- a/apps/web/components/FormInput.tsx +++ b/apps/web/components/FormInput.tsx @@ -1,4 +1,6 @@ -import React from 'react'; +import React, {Suspense} from 'react'; +import {ErrorBoundary} from './ErrorBoundary'; +import {TikTokVideoComponent} from './Video'; // // ERRORS /// /** @@ -13,7 +15,6 @@ class InvalidUrlError extends Error { this.name = 'INVALID_URL'; } } - /** * FormInput Component. * @return {JSX.Element} @@ -21,6 +22,7 @@ class InvalidUrlError extends Error { export const FormInputComponent = (): JSX.Element => { const [url, setUrl] = React.useState(''); const [error, setError] = React.useState(); + const [submitted, setSubmit] = React.useState(false); React.useEffect(() => { if ( @@ -49,7 +51,10 @@ export const FormInputComponent = (): JSX.Element => {
{}} + onSubmit={() => { + !error && setSubmit(true); + return; + }} >
{
+ + {submitted && ( + + Couldn't fetch tiktok's video url + + } + > + + Loading... + + } + > + + + + )} ); diff --git a/apps/web/components/Video.tsx b/apps/web/components/Video.tsx index 2c104db..1891ea2 100644 --- a/apps/web/components/Video.tsx +++ b/apps/web/components/Video.tsx @@ -1,22 +1,42 @@ import React from 'react'; +import useSWR, {Fetcher} from 'swr'; import {ExtractedInfo} from 'tiktok-dl-core'; -type ExtractedInfoWithProvider = ExtractedInfo & { +export type ExtractedInfoWithProvider = ExtractedInfo & { provider: string; }; +// fetcher +const fetcher: Fetcher = (...args) => + fetch(...args).then((res) => res.json()); + /** * Render tiktok video component. - * @param {ExtractedInfoWithProvider} data tiktok's api result. + * @param {{ url: URL; }} param0 TikTokVideoComponent props. * @return {JSX.Element} */ -export const TikTokVideoComponent = ( - data: ExtractedInfoWithProvider, -): JSX.Element => { +export const TikTokVideoComponent = ({url}: {url: URL}): JSX.Element => { + url.search = ''; // clean params. + const {data} = useSWR( + [ + '/api/download', + { + method: 'POST', + body: JSON.stringify({url: url.href}), + }, + ], + fetcher, + { + suspense: true, + }, + ); + + console.log(data); + return (
- {data.error ? ( + {data && !data.error ? ( <>

Here is your video:

    @@ -29,7 +49,7 @@ export const TikTokVideoComponent = ( ) : ( <>

    - Error: {data.error} + Error: {data && data.error ? data.error : 'wait'}

    )} diff --git a/apps/web/pages/api/download.ts b/apps/web/pages/api/download.ts index 420f603..ab29fc2 100644 --- a/apps/web/pages/api/download.ts +++ b/apps/web/pages/api/download.ts @@ -9,7 +9,7 @@ export default async (req: NextApiRequest, res: NextApiResponse) => { await ratelimitMiddleware(req, res); const providersType = Providers.map((p) => p.resourceName()); ow( - req.body || req.query, + req.method === 'POST' ? JSON.parse(req.body) : req.query, ow.object.partialShape({ url: ow.string.url.validate((v) => ({ validator: