import * as React from 'react'; import { Text, Alert, View } from 'react-native'; import { _ } from '@joplin/lib/locale'; import Logger from '@joplin/utils/Logger'; import { ProgressBar } from 'react-native-paper'; import { FunctionComponent, useCallback, useState } from 'react'; import shim from '@joplin/lib/shim'; import { join } from 'path'; import Share from 'react-native-share'; import exportAllFolders, { makeExportCacheDirectory } from './utils/exportAllFolders'; import { ExportProgressState } from '@joplin/lib/services/interop/types'; import { ConfigScreenStyles } from '../configScreenStyles'; import SettingsButton from '../SettingsButton'; const logger = Logger.create('NoteExportButton'); interface Props { styles: ConfigScreenStyles; } enum ExportStatus { NotStarted, Exporting, Exported, } export const exportButtonTitle = () => _('Export all notes as JEX'); export const exportButtonDescription = () => _('Share a copy of all notes in a file format that can be imported by Joplin on a computer.'); const NoteExportButton: FunctionComponent = props => { const [exportStatus, setExportStatus] = useState(ExportStatus.NotStarted); const [exportProgress, setExportProgress] = useState(0); const [warnings, setWarnings] = useState(''); const startExport = useCallback(async () => { // Don't run multiple exports at the same time. if (exportStatus === ExportStatus.Exporting) { return; } setExportStatus(ExportStatus.Exporting); const exportTargetPath = join(await makeExportCacheDirectory(), 'jex-export.jex'); logger.info(`Exporting all folders to path ${exportTargetPath}`); try { // Initially, undetermined progress setExportProgress(undefined); const status = await exportAllFolders(exportTargetPath, (status, progress) => { if (progress !== null) { setExportProgress(progress); } else if (status === ExportProgressState.Closing || status === ExportProgressState.QueuingItems) { // We don't have a numeric progress value and the closing/queuing state may take a while. // Set a special progress value: setExportProgress(undefined); } }); setExportStatus(ExportStatus.Exported); setWarnings(status.warnings.join('\n')); await Share.open({ type: 'application/jex', filename: 'export.jex', url: `file://${exportTargetPath}`, failOnCancel: false, }); } catch (e) { logger.error('Unable to export:', e); // Display a message to the user (e.g. in the case where the user is out of disk space). Alert.alert(_('Error'), _('Unable to export or share data. Reason: %s', e.toString())); setExportStatus(ExportStatus.NotStarted); } finally { await shim.fsDriver().remove(exportTargetPath); } }, [exportStatus]); if (exportStatus === ExportStatus.NotStarted || exportStatus === ExportStatus.Exporting) { const progressComponent = ( ); const startOrCancelExportButton = ( ); return startOrCancelExportButton; } else { const warningComponent = ( {_('Warnings:\n%s', warnings)} ); const exportSummary = ( {_('Exported successfully!')} {warnings.length > 0 ? warningComponent : null} ); return exportSummary; } }; export default NoteExportButton;