feat: Allow exporting multiple Super notes and select what format to export them to (#2191)
This commit is contained in:
@@ -32,6 +32,8 @@ import { iconClass } from './ClassNames'
|
||||
import SuperNoteOptions from './SuperNoteOptions'
|
||||
import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem'
|
||||
import MenuItem from '../Menu/MenuItem'
|
||||
import ModalOverlay from '../Modal/ModalOverlay'
|
||||
import SuperExportModal from './SuperExportModal'
|
||||
|
||||
const iconSize = MenuItemIconSize
|
||||
const iconClassDanger = `text-danger mr-2 ${iconSize}`
|
||||
@@ -94,6 +96,11 @@ const NotesOptions = ({
|
||||
}
|
||||
}, [application])
|
||||
|
||||
const [showExportSuperModal, setShowExportSuperModal] = useState(false)
|
||||
const closeSuperExportModal = useCallback(() => {
|
||||
setShowExportSuperModal(false)
|
||||
}, [])
|
||||
|
||||
const downloadSelectedItems = useCallback(async () => {
|
||||
if (notes.length === 1) {
|
||||
const note = notes[0]
|
||||
@@ -165,6 +172,8 @@ const NotesOptions = ({
|
||||
return null
|
||||
}
|
||||
|
||||
const isOnlySuperNoteSelected = notes.length === 1 && notes[0].noteType === NoteType.Super
|
||||
|
||||
return (
|
||||
<>
|
||||
{notes.length === 1 && (
|
||||
@@ -251,13 +260,22 @@ const NotesOptions = ({
|
||||
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
|
||||
</MenuItem>
|
||||
)}
|
||||
{notes[0].noteType !== NoteType.Super && (
|
||||
{!isOnlySuperNoteSelected && (
|
||||
<>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
application.isNativeMobileWeb()
|
||||
? void shareSelectedNotes(application, notes)
|
||||
: void downloadSelectedItems()
|
||||
if (application.isNativeMobileWeb()) {
|
||||
void shareSelectedNotes(application, notes)
|
||||
} else {
|
||||
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
|
||||
|
||||
if (hasSuperNote) {
|
||||
setShowExportSuperModal(true)
|
||||
return
|
||||
}
|
||||
|
||||
void downloadSelectedItems()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
|
||||
@@ -374,6 +392,10 @@ const NotesOptions = ({
|
||||
<NoteSizeWarning note={notes[0]} />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<ModalOverlay isOpen={showExportSuperModal} onDismiss={closeSuperExportModal}>
|
||||
<SuperExportModal exportNotes={downloadSelectedItems} close={closeSuperExportModal} />
|
||||
</ModalOverlay>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { ApplicationEvent, PrefKey, PrefValue } from '@standardnotes/snjs'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useApplication } from '../ApplicationProvider'
|
||||
import Dropdown from '../Dropdown/Dropdown'
|
||||
import Modal from '../Modal/Modal'
|
||||
|
||||
type Props = {
|
||||
exportNotes: () => void
|
||||
close: () => void
|
||||
}
|
||||
|
||||
const SuperExportModal = ({ exportNotes, close }: Props) => {
|
||||
const application = useApplication()
|
||||
const [superNoteExportFormat, setSuperNoteExportFormat] = useState<PrefValue[PrefKey.SuperNoteExportFormat]>(
|
||||
() => application.getPreference(PrefKey.SuperNoteExportFormat) || 'json',
|
||||
)
|
||||
useEffect(() => {
|
||||
return application.addSingleEventObserver(ApplicationEvent.PreferencesChanged, async () => {
|
||||
setSuperNoteExportFormat(application.getPreference(PrefKey.SuperNoteExportFormat) || 'json')
|
||||
})
|
||||
}, [application, superNoteExportFormat])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Export notes"
|
||||
className={{
|
||||
description: 'p-4',
|
||||
}}
|
||||
close={close}
|
||||
actions={[
|
||||
{
|
||||
label: 'Cancel',
|
||||
type: 'cancel',
|
||||
onClick: close,
|
||||
mobileSlot: 'left',
|
||||
},
|
||||
{
|
||||
label: 'Export',
|
||||
type: 'primary',
|
||||
onClick: exportNotes,
|
||||
mobileSlot: 'right',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<div className="mb-4">
|
||||
<div className="mb-1 text-base">
|
||||
We detected your selection includes Super notes. How do you want to export them?
|
||||
</div>
|
||||
<Dropdown
|
||||
id="export-format-dropdown"
|
||||
label="Super notes export format"
|
||||
items={[
|
||||
{ label: 'Keep as Super', value: 'json' },
|
||||
{ label: 'Markdown', value: 'md' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
]}
|
||||
value={superNoteExportFormat}
|
||||
onChange={(value) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportFormat,
|
||||
value as PrefValue[PrefKey.SuperNoteExportFormat],
|
||||
)
|
||||
}}
|
||||
portal={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-passive-0">
|
||||
Note that if you convert Super notes to Markdown then import them back into Standard Notes in the future, you
|
||||
will lose some formatting that the Markdown format is incapable of expressing, such as collapsible blocks and
|
||||
embeds.
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default SuperExportModal
|
||||
Reference in New Issue
Block a user