fix: remove lazy pdf loader

This commit is contained in:
David Nguyen
2025-02-26 21:48:06 +11:00
parent 6474b4a524
commit 596d30e2e5
25 changed files with 14590 additions and 14938 deletions

View File

@ -13,7 +13,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from '@documenso/ui/primitives/dialog'; } from '@documenso/ui/primitives/dialog';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
import { useOptionalCurrentTeam } from '~/providers/team'; import { useOptionalCurrentTeam } from '~/providers/team';
@ -97,7 +97,7 @@ export const DocumentDuplicateDialog = ({
</div> </div>
) : ( ) : (
<div className="p-2 [&>div]:h-[50vh] [&>div]:overflow-y-scroll"> <div className="p-2 [&>div]:h-[50vh] [&>div]:overflow-y-scroll">
<LazyPDFViewer key={document?.id} documentData={documentData} /> <PDFViewer key={document?.id} documentData={documentData} />
</div> </div>
)} )}

View File

@ -25,7 +25,7 @@ import { Card, CardContent } from '@documenso/ui/primitives/card';
import { ElementVisible } from '@documenso/ui/primitives/element-visible'; import { ElementVisible } from '@documenso/ui/primitives/element-visible';
import { Input } from '@documenso/ui/primitives/input'; import { Input } from '@documenso/ui/primitives/input';
import { Label } from '@documenso/ui/primitives/label'; import { Label } from '@documenso/ui/primitives/label';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { SignaturePad } from '@documenso/ui/primitives/signature-pad'; import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
@ -338,7 +338,7 @@ export const EmbedDirectTemplateClientPage = ({
<div className="relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row"> <div className="relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row">
{/* Viewer */} {/* Viewer */}
<div className="flex-1"> <div className="flex-1">
<LazyPDFViewer <PDFViewer
documentData={documentData} documentData={documentData}
onDocumentLoad={() => setHasDocumentLoaded(true)} onDocumentLoad={() => setHasDocumentLoaded(true)}
/> />

View File

@ -24,7 +24,7 @@ import { Card, CardContent } from '@documenso/ui/primitives/card';
import { ElementVisible } from '@documenso/ui/primitives/element-visible'; import { ElementVisible } from '@documenso/ui/primitives/element-visible';
import { Input } from '@documenso/ui/primitives/input'; import { Input } from '@documenso/ui/primitives/input';
import { Label } from '@documenso/ui/primitives/label'; import { Label } from '@documenso/ui/primitives/label';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { RadioGroup, RadioGroupItem } from '@documenso/ui/primitives/radio-group'; import { RadioGroup, RadioGroupItem } from '@documenso/ui/primitives/radio-group';
import { SignaturePad } from '@documenso/ui/primitives/signature-pad'; import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
@ -278,7 +278,7 @@ export const EmbedSignDocumentClientPage = ({
<div className="embed--DocumentContainer relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row"> <div className="embed--DocumentContainer relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row">
{/* Viewer */} {/* Viewer */}
<div className="embed--DocumentViewer flex-1"> <div className="embed--DocumentViewer flex-1">
<LazyPDFViewer <PDFViewer
documentData={documentData} documentData={documentData}
onDocumentLoad={() => setHasDocumentLoaded(true)} onDocumentLoad={() => setHasDocumentLoaded(true)}
/> />

View File

@ -12,7 +12,7 @@ import { trpc } from '@documenso/trpc/react';
import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Card, CardContent } from '@documenso/ui/primitives/card';
import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root'; import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root';
import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types'; import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { Stepper } from '@documenso/ui/primitives/stepper'; import { Stepper } from '@documenso/ui/primitives/stepper';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
@ -136,7 +136,7 @@ export const DirectTemplatePageView = ({
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer <PDFViewer
key={template.id} key={template.id}
documentData={template.templateDocumentData} documentData={template.templateDocumentData}
onDocumentLoad={() => setIsDocumentPdfLoaded(true)} onDocumentLoad={() => setIsDocumentPdfLoaded(true)}

View File

@ -21,7 +21,7 @@ import type { FieldWithSignatureAndFieldMeta } from '@documenso/prisma/types/fie
import type { RecipientWithFields } from '@documenso/prisma/types/recipient-with-fields'; import type { RecipientWithFields } from '@documenso/prisma/types/recipient-with-fields';
import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Card, CardContent } from '@documenso/ui/primitives/card';
import { ElementVisible } from '@documenso/ui/primitives/element-visible'; import { ElementVisible } from '@documenso/ui/primitives/element-visible';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { DocumentSigningAutoSign } from '~/components/general/document-signing/document-signing-auto-sign'; import { DocumentSigningAutoSign } from '~/components/general/document-signing/document-signing-auto-sign';
import { DocumentSigningCheckboxField } from '~/components/general/document-signing/document-signing-checkbox-field'; import { DocumentSigningCheckboxField } from '~/components/general/document-signing/document-signing-checkbox-field';
@ -140,12 +140,7 @@ export const DocumentSigningPageView = ({
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer <PDFViewer key={documentData.id} documentData={documentData} document={document} />
key={documentData.id}
documentData={documentData}
document={document}
password={documentMeta?.password}
/>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -24,7 +24,7 @@ import { AddSubjectFormPartial } from '@documenso/ui/primitives/document-flow/ad
import type { TAddSubjectFormSchema } from '@documenso/ui/primitives/document-flow/add-subject.types'; import type { TAddSubjectFormSchema } from '@documenso/ui/primitives/document-flow/add-subject.types';
import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root'; import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root';
import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types'; import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { Stepper } from '@documenso/ui/primitives/stepper'; import { Stepper } from '@documenso/ui/primitives/stepper';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
@ -132,9 +132,6 @@ export const DocumentEditForm = ({
}, },
}); });
const { mutateAsync: setPasswordForDocument } =
trpc.document.setPasswordForDocument.useMutation();
const documentFlow: Record<EditDocumentStep, DocumentFlowStep> = { const documentFlow: Record<EditDocumentStep, DocumentFlowStep> = {
settings: { settings: {
title: msg`General`, title: msg`General`,
@ -315,13 +312,6 @@ export const DocumentEditForm = ({
} }
}; };
const onPasswordSubmit = async (password: string) => {
await setPasswordForDocument({
documentId: document.id,
password,
});
};
const currentDocumentFlow = documentFlow[step]; const currentDocumentFlow = documentFlow[step];
/** /**
@ -340,12 +330,10 @@ export const DocumentEditForm = ({
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer <PDFViewer
key={document.documentData.id} key={document.documentData.id}
documentData={document.documentData} documentData={document.documentData}
document={document} document={document}
password={document.documentMeta?.password}
onPasswordSubmit={onPasswordSubmit}
onDocumentLoad={() => setIsDocumentPdfLoaded(true)} onDocumentLoad={() => setIsDocumentPdfLoaded(true)}
/> />
</CardContent> </CardContent>

View File

@ -15,7 +15,7 @@ import { cn } from '@documenso/ui/lib/utils';
import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Card, CardContent } from '@documenso/ui/primitives/card';
import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root'; import { DocumentFlowFormContainer } from '@documenso/ui/primitives/document-flow/document-flow-root';
import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types'; import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/types';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { Stepper } from '@documenso/ui/primitives/stepper'; import { Stepper } from '@documenso/ui/primitives/stepper';
import { AddTemplateFieldsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-fields'; import { AddTemplateFieldsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-fields';
import type { TAddTemplateFieldsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-fields.types'; import type { TAddTemplateFieldsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-fields.types';
@ -236,7 +236,7 @@ export const TemplateEditForm = ({
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer <PDFViewer
key={templateDocumentData.id} key={templateDocumentData.id}
documentData={templateDocumentData} documentData={templateDocumentData}
onDocumentLoad={() => setIsDocumentPdfLoaded(true)} onDocumentLoad={() => setIsDocumentPdfLoaded(true)}

View File

@ -16,7 +16,7 @@ import { formatDocumentsPath } from '@documenso/lib/utils/teams';
import { Badge } from '@documenso/ui/primitives/badge'; import { Badge } from '@documenso/ui/primitives/badge';
import { Button } from '@documenso/ui/primitives/button'; import { Button } from '@documenso/ui/primitives/button';
import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Card, CardContent } from '@documenso/ui/primitives/card';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { DocumentHistorySheet } from '~/components/general/document/document-history-sheet'; import { DocumentHistorySheet } from '~/components/general/document/document-history-sheet';
import { DocumentPageViewButton } from '~/components/general/document/document-page-view-button'; import { DocumentPageViewButton } from '~/components/general/document/document-page-view-button';
@ -196,7 +196,7 @@ export default function DocumentPage() {
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer document={document} key={documentData.id} documentData={documentData} /> <PDFViewer document={document} key={documentData.id} documentData={documentData} />
</CardContent> </CardContent>
</Card> </Card>

View File

@ -16,6 +16,7 @@ import { getSubscriptionsByUserId } from '@documenso/lib/server-only/subscriptio
import { BillingPlans } from '~/components/general/billing-plans'; import { BillingPlans } from '~/components/general/billing-plans';
import { BillingPortalButton } from '~/components/general/billing-portal-button'; import { BillingPortalButton } from '~/components/general/billing-portal-button';
import { appMetaTags } from '~/utils/meta'; import { appMetaTags } from '~/utils/meta';
import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/billing'; import type { Route } from './+types/billing';
@ -62,17 +63,17 @@ export async function loader({ request }: Route.LoaderArgs) {
const isMissingOrInactiveOrFreePlan = const isMissingOrInactiveOrFreePlan =
!subscription || subscription.status === SubscriptionStatus.INACTIVE; !subscription || subscription.status === SubscriptionStatus.INACTIVE;
return { return superLoaderJson({
prices, prices,
subscription, subscription,
subscriptionProductName: subscriptionProduct?.name, subscriptionProductName: subscriptionProduct?.name,
isMissingOrInactiveOrFreePlan, isMissingOrInactiveOrFreePlan,
}; });
} }
export default function TeamsSettingBillingPage({ loaderData }: Route.ComponentProps) { export default function TeamsSettingBillingPage() {
const { prices, subscription, subscriptionProductName, isMissingOrInactiveOrFreePlan } = const { prices, subscription, subscriptionProductName, isMissingOrInactiveOrFreePlan } =
loaderData; useSuperLoaderData<typeof loader>();
const { i18n } = useLingui(); const { i18n } = useLingui();

View File

@ -14,6 +14,7 @@ import { Card, CardContent } from '@documenso/ui/primitives/card';
import { SettingsHeader } from '~/components/general/settings-header'; import { SettingsHeader } from '~/components/general/settings-header';
import { TeamBillingPortalButton } from '~/components/general/teams/team-billing-portal-button'; import { TeamBillingPortalButton } from '~/components/general/teams/team-billing-portal-button';
import { TeamSettingsBillingInvoicesTable } from '~/components/tables/team-settings-billing-invoices-table'; import { TeamSettingsBillingInvoicesTable } from '~/components/tables/team-settings-billing-invoices-table';
import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/settings.billing'; import type { Route } from './+types/settings.billing';
@ -31,16 +32,16 @@ export async function loader({ request, params }: Route.LoaderArgs) {
teamSubscription = await stripe.subscriptions.retrieve(team.subscription.planId); teamSubscription = await stripe.subscriptions.retrieve(team.subscription.planId);
} }
return { return superLoaderJson({
team, team,
teamSubscription, teamSubscription,
}; });
} }
export default function TeamsSettingBillingPage({ loaderData }: Route.ComponentProps) { export default function TeamsSettingBillingPage() {
const { _ } = useLingui(); const { _ } = useLingui();
const { team, teamSubscription } = loaderData; const { team, teamSubscription } = useSuperLoaderData<typeof loader>();
const canManageBilling = canExecuteTeamAction('MANAGE_BILLING', team.currentTeamMember.role); const canManageBilling = canExecuteTeamAction('MANAGE_BILLING', team.currentTeamMember.role);

View File

@ -9,7 +9,7 @@ import { getTemplateById } from '@documenso/lib/server-only/template/get-templat
import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams'; import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams';
import { Button } from '@documenso/ui/primitives/button'; import { Button } from '@documenso/ui/primitives/button';
import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Card, CardContent } from '@documenso/ui/primitives/card';
import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
import { TemplateBulkSendDialog } from '~/components/dialogs/template-bulk-send-dialog'; import { TemplateBulkSendDialog } from '~/components/dialogs/template-bulk-send-dialog';
import { TemplateDirectLinkDialogWrapper } from '~/components/dialogs/template-direct-link-dialog-wrapper'; import { TemplateDirectLinkDialogWrapper } from '~/components/dialogs/template-direct-link-dialog-wrapper';
@ -144,11 +144,7 @@ export default function TemplatePage() {
gradient gradient
> >
<CardContent className="p-2"> <CardContent className="p-2">
<LazyPDFViewer <PDFViewer document={template} key={template.id} documentData={templateDocumentData} />
document={template}
key={template.id}
documentData={templateDocumentData}
/>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -76,7 +76,7 @@
"@babel/preset-typescript": "^7.26.0", "@babel/preset-typescript": "^7.26.0",
"@lingui/babel-plugin-lingui-macro": "^5.2.0", "@lingui/babel-plugin-lingui-macro": "^5.2.0",
"@lingui/vite-plugin": "^5.2.0", "@lingui/vite-plugin": "^5.2.0",
"@react-router/dev": "^7.1.1", "@react-router/dev": "^7.1.5",
"@react-router/remix-routes-option-adapter": "^7.1.5", "@react-router/remix-routes-option-adapter": "^7.1.5",
"@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.2", "@rollup/plugin-commonjs": "^28.0.2",

View File

@ -1,4 +1,6 @@
import { defineConfig } from '@lingui/cli';
import type { LinguiConfig } from '@lingui/conf'; import type { LinguiConfig } from '@lingui/conf';
import { formatter } from '@lingui/format-po';
import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n'; import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n';
@ -14,6 +16,7 @@ const config: LinguiConfig = {
}, },
], ],
compileNamespace: 'es', compileNamespace: 'es',
format: formatter({ lineNumbers: false }),
}; };
export default config; export default config;

2
package-lock.json generated
View File

@ -158,7 +158,7 @@
"@babel/preset-typescript": "^7.26.0", "@babel/preset-typescript": "^7.26.0",
"@lingui/babel-plugin-lingui-macro": "^5.2.0", "@lingui/babel-plugin-lingui-macro": "^5.2.0",
"@lingui/vite-plugin": "^5.2.0", "@lingui/vite-plugin": "^5.2.0",
"@react-router/dev": "^7.1.1", "@react-router/dev": "^7.1.5",
"@react-router/remix-routes-option-adapter": "^7.1.5", "@react-router/remix-routes-option-adapter": "^7.1.5",
"@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.2", "@rollup/plugin-commonjs": "^28.0.2",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ import { DateTime } from 'luxon';
import { getServerLimits } from '@documenso/ee/server-only/limits/server'; import { getServerLimits } from '@documenso/ee/server-only/limits/server';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { DOCUMENSO_ENCRYPTION_KEY } from '@documenso/lib/constants/crypto';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt'; import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt';
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data'; import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data';
@ -26,7 +25,6 @@ import { searchDocumentsWithKeyword } from '@documenso/lib/server-only/document/
import { sendDocument } from '@documenso/lib/server-only/document/send-document'; import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { updateDocument } from '@documenso/lib/server-only/document/update-document'; import { updateDocument } from '@documenso/lib/server-only/document/update-document';
import { getTeamById } from '@documenso/lib/server-only/team/get-team'; import { getTeamById } from '@documenso/lib/server-only/team/get-team';
import { symmetricEncrypt } from '@documenso/lib/universal/crypto';
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions'; import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
import { authenticatedProcedure, procedure, router } from '../trpc'; import { authenticatedProcedure, procedure, router } from '../trpc';
@ -55,7 +53,6 @@ import {
ZMoveDocumentToTeamSchema, ZMoveDocumentToTeamSchema,
ZResendDocumentMutationSchema, ZResendDocumentMutationSchema,
ZSearchDocumentsMutationSchema, ZSearchDocumentsMutationSchema,
ZSetPasswordForDocumentMutationSchema,
ZSetSigningOrderForDocumentMutationSchema, ZSetSigningOrderForDocumentMutationSchema,
ZSuccessResponseSchema, ZSuccessResponseSchema,
ZUpdateDocumentRequestSchema, ZUpdateDocumentRequestSchema,
@ -444,35 +441,6 @@ export const documentRouter = router({
}); });
}), }),
/**
* @private
*/
setPasswordForDocument: authenticatedProcedure
.input(ZSetPasswordForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
const { teamId } = ctx;
const { documentId, password } = input;
const key = DOCUMENSO_ENCRYPTION_KEY;
if (!key) {
throw new Error('Missing encryption key');
}
const securePassword = symmetricEncrypt({
data: password,
key,
});
await upsertDocumentMeta({
userId: ctx.user.id,
teamId,
documentId,
password: securePassword,
requestMetadata: ctx.metadata,
});
}),
/** /**
* @private * @private
* *

View File

@ -6,7 +6,7 @@ import { X } from 'lucide-react';
import { cn } from '../../lib/utils'; import { cn } from '../../lib/utils';
import { Dialog, DialogOverlay, DialogPortal, DialogTrigger } from '../../primitives/dialog'; import { Dialog, DialogOverlay, DialogPortal, DialogTrigger } from '../../primitives/dialog';
import { LazyPDFViewerNoLoader } from '../../primitives/lazy-pdf-viewer'; import PDFViewer from '../../primitives/pdf-viewer';
export type DocumentDialogProps = { export type DocumentDialogProps = {
trigger?: React.ReactNode; trigger?: React.ReactNode;
@ -43,7 +43,7 @@ export default function DocumentDialog({ trigger, documentData, ...props }: Docu
)} )}
onClick={() => props.onOpenChange?.(false)} onClick={() => props.onOpenChange?.(false)}
> >
<LazyPDFViewerNoLoader <PDFViewer
className="mx-auto w-full max-w-3xl xl:max-w-5xl" className="mx-auto w-full max-w-3xl xl:max-w-5xl"
documentData={documentData} documentData={documentData}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}

View File

@ -1,107 +0,0 @@
import { useEffect } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from './button';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog';
import { Form, FormControl, FormField, FormItem, FormMessage } from './form/form';
import { Input } from './input';
const ZPasswordDialogFormSchema = z.object({
password: z.string(),
});
type TPasswordDialogFormSchema = z.infer<typeof ZPasswordDialogFormSchema>;
type PasswordDialogProps = {
open: boolean;
onOpenChange: (_open: boolean) => void;
defaultPassword?: string;
onPasswordSubmit?: (password: string) => void;
isError?: boolean;
};
export const PasswordDialog = ({
open,
onOpenChange,
defaultPassword,
onPasswordSubmit,
isError,
}: PasswordDialogProps) => {
const { _ } = useLingui();
const form = useForm<TPasswordDialogFormSchema>({
defaultValues: {
password: defaultPassword ?? '',
},
resolver: zodResolver(ZPasswordDialogFormSchema),
});
const onFormSubmit = ({ password }: TPasswordDialogFormSchema) => {
onPasswordSubmit?.(password);
};
useEffect(() => {
if (isError) {
form.setError('password', {
type: 'manual',
message: _(msg`The password you have entered is incorrect. Please try again.`),
});
}
}, [form, isError]);
return (
<Dialog open={open}>
<DialogContent className="w-full max-w-md">
<DialogHeader>
<DialogTitle>
<Trans>Password Required</Trans>
</DialogTitle>
<DialogDescription className="text-muted-foreground">
<Trans>
This document is password protected. Please enter the password to view the document.
</Trans>
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onFormSubmit)}>
<fieldset className="flex flex-wrap items-start justify-between gap-4">
<FormField
name="password"
control={form.control}
render={({ field }) => (
<FormItem className="relative flex-1">
<FormControl>
<Input
type="password"
className="bg-background"
placeholder={_(msg`Enter password`)}
autoComplete="off"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div>
<Button>
<Trans>Submit</Trans>
</Button>
</div>
</fieldset>
</form>
</Form>
</DialogContent>
</Dialog>
);
};

View File

@ -1,31 +0,0 @@
// Todo: (RR7) Not sure if this actually makes it client-only.
import { Suspense, lazy } from 'react';
import { Trans } from '@lingui/react/macro';
import { Loader } from 'lucide-react';
import { Await } from 'react-router';
const LoadingComponent = () => (
<div className="dark:bg-background flex h-[80vh] max-h-[60rem] flex-col items-center justify-center bg-white/50">
<Loader className="text-documenso h-12 w-12 animate-spin" />
<p className="text-muted-foreground mt-4">
<Trans>Loading document...</Trans>
</p>
</div>
);
export const LazyPDFViewerImport = lazy(async () => import('./pdf-viewer'));
export const LazyPDFViewer = (props: React.ComponentProps<typeof LazyPDFViewerImport>) => (
<Suspense fallback={<LoadingComponent />}>
<Await resolve={LazyPDFViewerImport}>
<LazyPDFViewerImport {...props} />
</Await>
</Suspense>
);
export const LazyPDFViewerNoLoader = (props: React.ComponentProps<typeof LazyPDFViewer>) => (
<Suspense fallback={null}>
<LazyPDFViewerImport {...props} />
</Suspense>
);

View File

@ -5,18 +5,15 @@ import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
import type { DocumentData } from '@prisma/client'; import type { DocumentData } from '@prisma/client';
import { Loader } from 'lucide-react'; import { Loader } from 'lucide-react';
import { type PDFDocumentProxy, PasswordResponses } from 'pdfjs-dist'; import { type PDFDocumentProxy } from 'pdfjs-dist';
import pdfWorker from 'pdfjs-dist/build/pdf.worker.min?url';
import { Document as PDFDocument, Page as PDFPage, pdfjs } from 'react-pdf'; import { Document as PDFDocument, Page as PDFPage, pdfjs } from 'react-pdf';
import 'react-pdf/dist/esm/Page/AnnotationLayer.css'; import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css'; import 'react-pdf/dist/esm/Page/TextLayer.css';
import { match } from 'ts-pattern';
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import { getFile } from '@documenso/lib/universal/upload/get-file'; import { getFile } from '@documenso/lib/universal/upload/get-file';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
import { PasswordDialog } from './document-password-dialog';
import { useToast } from './use-toast'; import { useToast } from './use-toast';
export type LoadedPDFDocument = PDFDocumentProxy; export type LoadedPDFDocument = PDFDocumentProxy;
@ -24,7 +21,10 @@ export type LoadedPDFDocument = PDFDocumentProxy;
/** /**
* This imports the worker from the `pdfjs-dist` package. * This imports the worker from the `pdfjs-dist` package.
*/ */
pdfjs.GlobalWorkerOptions.workerSrc = pdfWorker; pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url,
).toString();
export type OnPDFViewerPageClick = (_event: { export type OnPDFViewerPageClick = (_event: {
pageNumber: number; pageNumber: number;
@ -49,8 +49,6 @@ const PDFLoader = () => (
export type PDFViewerProps = { export type PDFViewerProps = {
className?: string; className?: string;
documentData: DocumentData; documentData: DocumentData;
password?: string | null;
onPasswordSubmit?: (password: string) => void | Promise<void>;
onDocumentLoad?: (_doc: LoadedPDFDocument) => void; onDocumentLoad?: (_doc: LoadedPDFDocument) => void;
onPageClick?: OnPDFViewerPageClick; onPageClick?: OnPDFViewerPageClick;
[key: string]: unknown; [key: string]: unknown;
@ -59,8 +57,6 @@ export type PDFViewerProps = {
export const PDFViewer = ({ export const PDFViewer = ({
className, className,
documentData, documentData,
password: defaultPassword,
onPasswordSubmit,
onDocumentLoad, onDocumentLoad,
onPageClick, onPageClick,
...props ...props
@ -70,11 +66,7 @@ export const PDFViewer = ({
const $el = useRef<HTMLDivElement>(null); const $el = useRef<HTMLDivElement>(null);
const passwordCallbackRef = useRef<((password: string | null) => void) | null>(null);
const [isDocumentBytesLoading, setIsDocumentBytesLoading] = useState(false); const [isDocumentBytesLoading, setIsDocumentBytesLoading] = useState(false);
const [isPasswordModalOpen, setIsPasswordModalOpen] = useState(false);
const [isPasswordError, setIsPasswordError] = useState(false);
const [documentBytes, setDocumentBytes] = useState<Uint8Array | null>(null); const [documentBytes, setDocumentBytes] = useState<Uint8Array | null>(null);
const [width, setWidth] = useState(0); const [width, setWidth] = useState(0);
@ -190,21 +182,6 @@ export const PDFViewer = ({
className={cn('w-full overflow-hidden rounded', { className={cn('w-full overflow-hidden rounded', {
'h-[80vh] max-h-[60rem]': numPages === 0, 'h-[80vh] max-h-[60rem]': numPages === 0,
})} })}
onPassword={(callback, reason) => {
// If the document already has a password, we don't need to ask for it again.
if (defaultPassword && reason !== PasswordResponses.INCORRECT_PASSWORD) {
callback(defaultPassword);
return;
}
setIsPasswordModalOpen(true);
passwordCallbackRef.current = callback;
match(reason)
.with(PasswordResponses.NEED_PASSWORD, () => setIsPasswordError(false))
.with(PasswordResponses.INCORRECT_PASSWORD, () => setIsPasswordError(true));
}}
onLoadSuccess={(d) => onDocumentLoaded(d)} onLoadSuccess={(d) => onDocumentLoaded(d)}
// Uploading a invalid document causes an error which doesn't appear to be handled by the `error` prop. // Uploading a invalid document causes an error which doesn't appear to be handled by the `error` prop.
// Therefore we add some additional custom error handling. // Therefore we add some additional custom error handling.
@ -263,19 +240,6 @@ export const PDFViewer = ({
</div> </div>
))} ))}
</PDFDocument> </PDFDocument>
<PasswordDialog
open={isPasswordModalOpen}
onOpenChange={setIsPasswordModalOpen}
onPasswordSubmit={(password) => {
passwordCallbackRef.current?.(password);
setIsPasswordModalOpen(false);
void onPasswordSubmit?.(password);
}}
isError={isPasswordError}
/>
</> </>
)} )}
</div> </div>