import { Accordion, Alert, Button, Checkbox, Col, Grid, Group, MultiSelect, NumberInput, PasswordInput, Select, Stack, Text, Textarea, TextInput, } from "@mantine/core"; import { useForm, yupResolver } from "@mantine/form"; import { useModals } from "@mantine/modals"; import { ModalsContextProps } from "@mantine/modals/lib/context"; import moment from "moment"; import React, { useState } from "react"; import { TbAlertCircle } from "react-icons/tb"; import { FormattedMessage } from "react-intl"; import * as yup from "yup"; import useTranslate, { translateOutsideContext, } from "../../../hooks/useTranslate.hook"; import shareService from "../../../services/share.service"; import { FileUpload } from "../../../types/File.type"; import { CreateShare } from "../../../types/share.type"; import { getExpirationPreview } from "../../../utils/date.util"; import toast from "../../../utils/toast.util"; const showCreateUploadModal = ( modals: ModalsContextProps, options: { isUserSignedIn: boolean; isReverseShare: boolean; allowUnauthenticatedShares: boolean; enableEmailRecepients: boolean; maxExpirationInHours: number; shareIdLength: number; simplified: boolean; }, files: FileUpload[], uploadCallback: (createShare: CreateShare, files: FileUpload[]) => void, ) => { const t = translateOutsideContext(); if (options.simplified) { return modals.openModal({ title: t("upload.modal.title"), children: ( ), }); } return modals.openModal({ title: t("upload.modal.title"), children: ( ), }); }; const generateShareId = (length: number = 16) => { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; const randomArray = new Uint8Array(length >= 3 ? length : 3); crypto.getRandomValues(randomArray); randomArray.forEach((number) => { result += chars[number % chars.length]; }); return result; }; const generateAvailableLink = async ( shareIdLength: number, times: number = 10, ): Promise => { if (times <= 0) { throw new Error("Could not generate available link"); } const _link = generateShareId(shareIdLength); if (!(await shareService.isShareIdAvailable(_link))) { return await generateAvailableLink(shareIdLength, times - 1); } else { return _link; } }; const CreateUploadModalBody = ({ uploadCallback, files, options, }: { files: FileUpload[]; uploadCallback: (createShare: CreateShare, files: FileUpload[]) => void; options: { isUserSignedIn: boolean; isReverseShare: boolean; allowUnauthenticatedShares: boolean; enableEmailRecepients: boolean; maxExpirationInHours: number; shareIdLength: number; }; }) => { const modals = useModals(); const t = useTranslate(); const generatedLink = generateShareId(options.shareIdLength); const [showNotSignedInAlert, setShowNotSignedInAlert] = useState(true); const validationSchema = yup.object().shape({ link: yup .string() .required(t("common.error.field-required")) .min(3, t("common.error.too-short", { length: 3 })) .max(50, t("common.error.too-long", { length: 50 })) .matches(new RegExp("^[a-zA-Z0-9_-]*$"), { message: t("upload.modal.link.error.invalid"), }), name: yup .string() .transform((value) => value || undefined) .min(3, t("common.error.too-short", { length: 3 })) .max(30, t("common.error.too-long", { length: 30 })), password: yup .string() .transform((value) => value || undefined) .min(3, t("common.error.too-short", { length: 3 })) .max(30, t("common.error.too-long", { length: 30 })), maxViews: yup .number() .transform((value) => value || undefined) .min(1), }); const form = useForm({ initialValues: { name: undefined, link: generatedLink, recipients: [] as string[], password: undefined, maxViews: undefined, description: undefined, expiration_num: 1, expiration_unit: "-days", never_expires: false, }, validate: yupResolver(validationSchema), }); const onSubmit = form.onSubmit(async (values) => { if (!(await shareService.isShareIdAvailable(values.link))) { form.setFieldError("link", t("upload.modal.link.error.taken")); } else { const expirationString = form.values.never_expires ? "never" : form.values.expiration_num + form.values.expiration_unit; const expirationDate = moment().add( form.values.expiration_num, form.values.expiration_unit.replace( "-", "", ) as moment.unitOfTime.DurationConstructor, ); if ( options.maxExpirationInHours != 0 && (form.values.never_expires || expirationDate.isAfter( moment().add(options.maxExpirationInHours, "hours"), )) ) { form.setFieldError( "expiration_num", t("upload.modal.expires.error.too-long", { max: moment .duration(options.maxExpirationInHours, "hours") .humanize(), }), ); return; } uploadCallback( { id: values.link, name: values.name, expiration: expirationString, recipients: values.recipients, description: values.description, security: { password: values.password || undefined, maxViews: values.maxViews || undefined, }, }, files, ); modals.closeAll(); } }); return ( <> {showNotSignedInAlert && !options.isUserSignedIn && ( setShowNotSignedInAlert(false)} icon={} title={t("upload.modal.not-signed-in")} color="yellow" > )}
({ color: theme.colors.gray[6], })} > {`${window.location.origin}/s/${form.values.link}`} {!options.isReverseShare && ( <>