import { zodResolver } from '@hookform/resolvers/zod'; import { useAtom, useAtomValue } from 'jotai'; import { useEffect } from 'preact/hooks'; import { FormProvider, useForm, useWatch } from 'react-hook-form'; import { feedbackDialogAtom } from '~/atoms/feedbackDialog'; import { projectIdAtom } from '~/atoms/project'; import InputField from '~/components/form/InputField'; import SelectField from '~/components/form/SelectField'; import IconFile from '~/components/icons/file.svg?react'; import Button from '~/components/ui/Button'; import Dialog from '~/components/ui/Dialog'; import useExportProject, { EXPORT_FORMATS } from '~/hooks/useExportProject'; import { usePersistedFormValues } from '~/hooks/usePersistedFormValues'; import { ExportFormatId } from '~/types/types'; import ExportOptions from './ExportOptions'; import ExportScenes from './ExportScenes'; import { ExportFormValues, exportFormSchema, PERSISTED_FIELDS } from './exportFormSchema'; const INVALID_FILENAME_CHARS = /[<>:"/\\|?*]/g; function sanitizeFileName(value: string): string { return value.replace(INVALID_FILENAME_CHARS, ''); } const NOTES: Record = { ableton: `Recorded fader automation is exported for LVL, PTC, LPF, HPF, FX, ATK, REL, PAN, TUNE, VEL and MOD. TIM automation is not exported because Ableton has no equivalent for the EP's real-time stretch control. Choke groups require Drum Rack, and the EP effects and stretching algorithms remain approximations.`, dawproject: `Unfortunately, the DAWproject format does not currently support the "Sampler" instrument, so you will need to manually assign the samples in your DAW.`, midi: `The simplest format supported by any DAW. But you have to assign the samples manually.`, reaper: `Only basic sampler features are supported`, }; function ExportProjectDialog({ open, onOpenChange, }: { open: boolean; onOpenChange: (open: boolean) => void; }) { const projectId = useAtomValue(projectIdAtom); const form = useForm({ resolver: zodResolver(exportFormSchema), defaultValues: { format: EXPORT_FORMATS[0].value, abletonVersion: '10', abletonOneShotPads: [], projectName: `Project${projectId}`, includeArchivedSamples: true, exportAllPadsWithSamples: false, clips: false, groupTracks: true, drumRackGroupA: false, drumRackGroupB: false, drumRackGroupC: false, drumRackGroupD: false, sendEffects: true, allScenes: true, selectedScenes: [], }, }); usePersistedFormValues(form, PERSISTED_FIELDS, exportFormSchema); const format = useWatch({ control: form.control, name: 'format' }); const projectName = useWatch({ control: form.control, name: 'projectName' }); const allScenes = useWatch({ control: form.control, name: 'allScenes' }); const selectedScenes = useWatch({ control: form.control, name: 'selectedScenes' }); const trimmedName = (projectName ?? '').trim(); const canExport = (allScenes || (selectedScenes?.length ?? 0) > 0) && trimmedName.length > 0; const { startExport, cancelExport, isPending, pendingStatus, percentage, reset, result, error, sampleReport, } = useExportProject(); const [_, openFeedbackDialog] = useAtom(feedbackDialogAtom); const handleExport = form.handleSubmit(async (values) => { await startExport({ ...values, projectName: values.projectName.trim(), }); }); useEffect(() => { reset(); }, [format]); return ( onOpenChange(false)} className="min-w-200 max-w-175">

Export

{EXPORT_FORMATS.map((f) => ( ))}

Project name

{NOTES[format] && (

Notes

{NOTES[format]}
)}
{percentage > 0 && ( <>
{pendingStatus}
)} {result && percentage >= 100 && (

Files to download

{result.files.map((f) => (
{f.name} {(f.size / 1024).toFixed(2)}KB
))} {sampleReport && (

Sample Report

✓ Downloaded: {sampleReport.downloaded.length} samples

{sampleReport.missing.length > 0 && (

✗ Missing: {sampleReport.missing.length} samples

    {sampleReport.missing.map((missing, index) => (
  • {missing.name}: {missing.error}
  • ))}
)}
)}
)} {error && (

Error

Opps, that's not good. Hope the error tracking system helps me to find the problem. If you can, please submit an error report - it really helps me fix things faster. Thanks!

)}
{isPending ? ( ) : ( )}
); } export default ExportProjectDialog;