diff --git a/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx b/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx index 671292bde..27560c073 100644 --- a/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx +++ b/apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx @@ -1,14 +1,12 @@ -import { useMemo, useState } from 'react'; - -import { useRouter } from 'next/navigation'; +import { useMemo } from 'react'; import { zodResolver } from '@hookform/resolvers/zod'; -import { flushSync } from 'react-dom'; import { useForm } from 'react-hook-form'; import { match } from 'ts-pattern'; import { renderSVG } from 'uqr'; import { z } from 'zod'; +import { downloadFile } from '@documenso/lib/client-only/download-file'; import { trpc } from '@documenso/trpc/react'; import { Button } from '@documenso/ui/primitives/button'; import { @@ -54,15 +52,16 @@ export const EnableAuthenticatorAppDialog = ({ open, onOpenChange, }: EnableAuthenticatorAppDialogProps) => { - const router = useRouter(); const { toast } = useToast(); - const [recoveryCodesUrl, setRecoveryCodesUrl] = useState(''); const { mutateAsync: setupTwoFactorAuthentication, data: setupTwoFactorAuthenticationData } = trpc.twoFactorAuthentication.setup.useMutation(); - const { mutateAsync: enableTwoFactorAuthentication, data: enableTwoFactorAuthenticationData } = - trpc.twoFactorAuthentication.enable.useMutation(); + const { + mutateAsync: enableTwoFactorAuthentication, + data: enableTwoFactorAuthenticationData, + isLoading: isEnableTwoFactorAuthenticationDataLoading, + } = trpc.twoFactorAuthentication.enable.useMutation(); const setupTwoFactorAuthenticationForm = useForm({ defaultValues: { @@ -118,11 +117,14 @@ export const EnableAuthenticatorAppDialog = ({ const downloadRecoveryCodes = () => { if (enableTwoFactorAuthenticationData && enableTwoFactorAuthenticationData.recoveryCodes) { - const textBlob = new Blob([enableTwoFactorAuthenticationData.recoveryCodes.join('\n')], { + const blob = new Blob([enableTwoFactorAuthenticationData.recoveryCodes.join('\n')], { type: 'text/plain', }); - if (recoveryCodesUrl) URL.revokeObjectURL(recoveryCodesUrl); - setRecoveryCodesUrl(URL.createObjectURL(textBlob)); + + downloadFile({ + filename: 'documenso-2FA-recovery-codes.txt', + data: blob, + }); } }; @@ -147,14 +149,6 @@ export const EnableAuthenticatorAppDialog = ({ } }; - const onCompleteClick = () => { - flushSync(() => { - onOpenChange(false); - }); - - router.refresh(); - }; - return ( @@ -283,11 +277,15 @@ export const EnableAuthenticatorAppDialog = ({
- - - + +
)) diff --git a/packages/lib/client-only/download-file.ts b/packages/lib/client-only/download-file.ts new file mode 100644 index 000000000..36351bedc --- /dev/null +++ b/packages/lib/client-only/download-file.ts @@ -0,0 +1,19 @@ +export type DownloadFileOptions = { + filename: string; + data: Blob; +}; + +export const downloadFile = ({ filename, data }: DownloadFileOptions) => { + if (typeof window === 'undefined') { + throw new Error('downloadFile can only be called in browser environments'); + } + + const link = window.document.createElement('a'); + + link.href = window.URL.createObjectURL(data); + link.download = filename; + + link.click(); + + window.URL.revokeObjectURL(link.href); +}; diff --git a/packages/lib/client-only/download-pdf.ts b/packages/lib/client-only/download-pdf.ts index ec7d0c252..0f757c98d 100644 --- a/packages/lib/client-only/download-pdf.ts +++ b/packages/lib/client-only/download-pdf.ts @@ -1,6 +1,7 @@ import type { DocumentData } from '@documenso/prisma/client'; import { getFile } from '../universal/upload/get-file'; +import { downloadFile } from './download-file'; type DownloadPDFProps = { documentData: DocumentData; @@ -14,16 +15,12 @@ export const downloadPDF = async ({ documentData, fileName }: DownloadPDFProps) type: 'application/pdf', }); - const link = window.document.createElement('a'); - const [baseTitle] = fileName?.includes('.pdf') ? fileName.split('.pdf') : [fileName ?? 'document']; - link.href = window.URL.createObjectURL(blob); - link.download = `${baseTitle}_signed.pdf`; - - link.click(); - - window.URL.revokeObjectURL(link.href); + downloadFile({ + filename: baseTitle, + data: blob, + }); };