fix: Fixed issue where exporting multiple files with the same name would error

This commit is contained in:
Aman Harwara
2023-10-31 16:43:02 +05:30
parent d1c295751d
commit f408950aa4
3 changed files with 33 additions and 25 deletions

View File

@@ -1,7 +1,7 @@
import Icon from '@/Components/Icon/Icon'
import { observer } from 'mobx-react-lite'
import { useState, useEffect, useMemo, useCallback } from 'react'
import { NoteType, Platform, SNNote } from '@standardnotes/snjs'
import { NoteType, Platform, SNNote, pluralize } from '@standardnotes/snjs'
import {
CHANGE_EDITOR_WIDTH_COMMAND,
OPEN_NOTE_HISTORY_COMMAND,
@@ -99,6 +99,13 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
}, [])
const downloadSelectedItems = useCallback(async () => {
if (notes.length === 0) {
return
}
const toast = addToast({
type: ToastType.Progress,
message: `Exporting ${notes.length} ${pluralize(notes.length, 'note', 'notes')}...`,
})
try {
const result = await createNoteExport(application, notes)
if (!result) {
@@ -113,12 +120,14 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
filename: fileName,
isNativeMobileWeb: application.isNativeMobileWeb(),
})
dismissToast(toast)
} catch (error) {
console.error(error)
addToast({
type: ToastType.Error,
message: 'Could not export notes',
})
dismissToast(toast)
}
}, [application, notes])

View File

@@ -1,8 +1,16 @@
import { WebApplication } from '@/Application/WebApplication'
import { HeadlessSuperConverter } from '@/Components/SuperEditor/Tools/HeadlessSuperConverter'
import { NoteType, PrefKey, SNNote, PrefDefaults, FileItem, PrefValue, pluralize } from '@standardnotes/snjs'
import { WebApplicationInterface, parseAndCreateZippableFileName, sanitizeFileName } from '@standardnotes/ui-services'
import { NoteType, PrefKey, SNNote, PrefDefaults, FileItem, PrefValue } from '@standardnotes/snjs'
import { WebApplicationInterface, parseAndCreateZippableFileName } from '@standardnotes/ui-services'
import { ZipDirectoryEntry } from '@zip.js/zip.js'
// @ts-expect-error Using inline loaders to load CSS as string
import superEditorCSS from '!css-loader!sass-loader!../Components/SuperEditor/Lexical/Theme/editor.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import snColorsCSS from '!css-loader!sass-loader!@standardnotes/styles/src/Styles/_colors.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import exportOverridesCSS from '!css-loader!sass-loader!../Components/SuperEditor/Lexical/Theme/export-overrides.scss'
import { getBase64FromBlob } from './Utils'
import { parseFileName } from '@standardnotes/filepicker'
export const getNoteFormat = (application: WebApplicationInterface, note: SNNote) => {
if (note.noteType === NoteType.Super) {
@@ -25,15 +33,6 @@ export const getNoteFileName = (application: WebApplicationInterface, note: SNNo
const headlessSuperConverter = new HeadlessSuperConverter()
// @ts-expect-error Using inline loaders to load CSS as string
import superEditorCSS from '!css-loader!sass-loader!../Components/SuperEditor/Lexical/Theme/editor.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import snColorsCSS from '!css-loader!sass-loader!@standardnotes/styles/src/Styles/_colors.scss'
// @ts-expect-error Using inline loaders to load CSS as string
import exportOverridesCSS from '!css-loader!sass-loader!../Components/SuperEditor/Lexical/Theme/export-overrides.scss'
import { getBase64FromBlob } from './Utils'
import { ToastType, addToast, dismissToast } from '@standardnotes/toast'
const superHTML = (note: SNNote, content: string) => `<!DOCTYPE html>
<html>
<head>
@@ -175,11 +174,6 @@ export const createNoteExport = async (
return
}
const toast = addToast({
type: ToastType.Progress,
message: `Exporting ${notes.length} ${pluralize(notes.length, 'note', 'notes')}...`,
})
const superExportFormatPref = application.getPreference(
PrefKey.SuperNoteExportFormat,
PrefDefaults[PrefKey.SuperNoteExportFormat],
@@ -192,7 +186,6 @@ export const createNoteExport = async (
if (notes.length === 1 && !noteRequiresFolder(notes[0], superExportFormatPref, superEmbedBehaviorPref)) {
const blob = await getNoteBlob(application, notes[0], superEmbedBehaviorPref)
const fileName = getNoteFileName(application, notes[0])
dismissToast(toast)
return {
blob,
fileName,
@@ -211,31 +204,37 @@ export const createNoteExport = async (
await addEmbeddedFilesToFolder(application, notes[0], root)
const zippedBlob = await zipFS.exportBlob()
dismissToast(toast)
return {
blob: zippedBlob,
fileName: fileName + '.zip',
}
}
const filenameCounts: Record<string, number> = {}
for (const note of notes) {
const blob = await getNoteBlob(application, note, superEmbedBehaviorPref)
const fileName = parseAndCreateZippableFileName(getNoteFileName(application, note))
const _name = getNoteFileName(application, note)
filenameCounts[_name] = filenameCounts[_name] == undefined ? 0 : filenameCounts[_name] + 1
const currentFileNameIndex = filenameCounts[_name]
const fileName = parseAndCreateZippableFileName(_name, currentFileNameIndex > 0 ? ` - ${currentFileNameIndex}` : '')
if (!noteRequiresFolder(note, superExportFormatPref, superEmbedBehaviorPref)) {
root.addBlob(fileName, blob)
continue
}
const folder = root.addDirectory(sanitizeFileName(note.title))
const { name } = parseFileName(fileName)
const folder = root.addDirectory(name)
folder.addBlob(fileName, blob)
await addEmbeddedFilesToFolder(application, note, folder)
}
const zippedBlob = await zipFS.exportBlob()
dismissToast(toast)
return {
blob: zippedBlob,
fileName: `Standard Notes Export - ${application.archiveService.formattedDateForExports()}.zip`,