mirror of
https://github.com/laurent22/joplin.git
synced 2026-10-25 02:47:28 +00:00
Desktop: Show export warnings on export completion to match mobile behaviour (#16682)
This commit is contained in:
1 parent
cd32d862c4
commit
97ab341275
6 files changed
+62
-10
No files matched your search
@@ -228,17 +228,23 @@ export default class InteropServiceHelper {
|
||||
if (options.sourceNoteIds) exportOptions.sourceNoteIds = options.sourceNoteIds;
|
||||
|
||||
const service = InteropService.instance();
|
||||
let keepModalOpen = false;
|
||||
|
||||
try {
|
||||
const result = await service.export(exportOptions);
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('Export result: ', result);
|
||||
if (result.warnings.length) {
|
||||
keepModalOpen = true;
|
||||
const message = [_('Export completed, but some items were skipped because they have not been downloaded to this device or could not be exported:'), '', ...result.warnings].join('\n');
|
||||
void CommandService.instance().execute('showModalMessage', message, true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
bridge().showErrorMessageBox(_('Could not export notes: %s', error.message));
|
||||
}
|
||||
|
||||
void CommandService.instance().execute('hideModalMessage');
|
||||
if (!keepModalOpen) void CommandService.instance().execute('hideModalMessage');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -100,6 +100,7 @@ export interface AppState extends State, AppWindowState {
|
||||
layoutMoveMode: boolean;
|
||||
startupPluginsLoaded: boolean;
|
||||
modalOverlayMessage: string|null;
|
||||
modalOverlayHasCloseButton: boolean;
|
||||
|
||||
// Extra reducer keys go here
|
||||
mainLayout: LayoutItem;
|
||||
@@ -143,6 +144,7 @@ export function createAppDefaultState(resourceEditWatcherDefaultState: Partial<A
|
||||
startupPluginsLoaded: false,
|
||||
isResettingLayout: false,
|
||||
modalOverlayMessage: null,
|
||||
modalOverlayHasCloseButton: false,
|
||||
aiStatus: defaultAiStatus(),
|
||||
...resourceEditWatcherDefaultState,
|
||||
};
|
||||
@@ -396,11 +398,15 @@ export default function(state: AppState, action: any) {
|
||||
}
|
||||
|
||||
case 'SHOW_MODAL_MESSAGE':
|
||||
newState = { ...newState, modalOverlayMessage: action.message };
|
||||
newState = {
|
||||
...newState,
|
||||
modalOverlayMessage: action.message,
|
||||
modalOverlayHasCloseButton: !!action.hasCloseButton,
|
||||
};
|
||||
break;
|
||||
|
||||
case 'HIDE_MODAL_MESSAGE':
|
||||
newState = { ...newState, modalOverlayMessage: null };
|
||||
newState = { ...newState, modalOverlayMessage: null, modalOverlayHasCloseButton: false };
|
||||
break;
|
||||
|
||||
case 'NOTE_FILE_WATCHER_ADD':
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
import * as React from 'react';
|
||||
import Dialog from '@joplin/lib/components/Dialog';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
interface Props {
|
||||
message: string;
|
||||
hasCloseButton: boolean;
|
||||
onClose: ()=> void;
|
||||
}
|
||||
|
||||
const ModalMessageOverlay: React.FC<Props> = ({ message }) => {
|
||||
const ModalMessageOverlay: React.FC<Props> = ({ message, hasCloseButton, onClose }) => {
|
||||
let brIndex = 1;
|
||||
const lines = message.split('\n').map((line: string) => {
|
||||
if (!line.trim()) return <br key={`${brIndex++}`}/>;
|
||||
return <div key={line} className="text">{line}</div>;
|
||||
});
|
||||
|
||||
return <Dialog contentFillsScreen={true}>
|
||||
<div className="modal-message">
|
||||
<div className="loading-animation" />
|
||||
<div className="text" role="status">
|
||||
return <Dialog contentFillsScreen={true} onCancel={hasCloseButton ? onClose : undefined}>
|
||||
<div className={`modal-message ${hasCloseButton ? '-with-close-button' : ''}`}>
|
||||
{!hasCloseButton && <div className="loading-animation" />}
|
||||
<div className={`text ${hasCloseButton ? 'modal-message-scrollable-content' : ''}`} role="status">
|
||||
{lines}
|
||||
</div>
|
||||
{hasCloseButton && <div className="modal-message-actions">
|
||||
<button type="button" onClick={onClose}>{_('OK')}</button>
|
||||
</div>}
|
||||
</div>
|
||||
</Dialog>;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@ interface Props {
|
||||
appDialogStates: AppStateDialog[];
|
||||
pluginsLegacy: Record<string, { dialogOpen?: boolean; userData?: unknown }>;
|
||||
modalMessage: string|null;
|
||||
modalMessageHasCloseButton: boolean;
|
||||
|
||||
customCss: string;
|
||||
editorNoteStatuses: EditorNoteStatuses;
|
||||
@@ -127,7 +128,11 @@ const WindowCommandsAndDialogs: React.FC<Props> = props => {
|
||||
return <>
|
||||
<div ref={setReferenceElement}/>
|
||||
{pluginDialog}
|
||||
{props.modalMessage !== null ? <ModalMessageOverlay message={props.modalMessage}/> : null}
|
||||
{props.modalMessage !== null ? <ModalMessageOverlay
|
||||
message={props.modalMessage}
|
||||
hasCloseButton={props.modalMessageHasCloseButton}
|
||||
onClose={() => props.dispatch({ type: 'HIDE_MODAL_MESSAGE' })}
|
||||
/> : null}
|
||||
<PluginDialogs
|
||||
themeId={props.themeId}
|
||||
visibleDialogs={props.visibleDialogs}
|
||||
@@ -210,5 +215,6 @@ export default connect((state: AppState, ownProps: ConnectProps) => {
|
||||
editorNoteStatuses: state.editorNoteStatuses,
|
||||
pluginsLegacy: state.pluginsLegacy,
|
||||
modalMessage: state.modalOverlayMessage,
|
||||
modalMessageHasCloseButton: state.modalOverlayHasCloseButton,
|
||||
};
|
||||
})(WindowCommandsAndDialogs);
|
||||
@@ -6,10 +6,11 @@ export const declaration: CommandDeclaration = {
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context: CommandContext, message: string) => {
|
||||
execute: async (context: CommandContext, message: string, hasCloseButton = false) => {
|
||||
context.dispatch({
|
||||
type: 'SHOW_MODAL_MESSAGE',
|
||||
message,
|
||||
hasCloseButton,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -126,6 +126,33 @@ a {
|
||||
color: grey;
|
||||
font-size: 1.2em;
|
||||
margin: 40px 20px;
|
||||
|
||||
&.-with-close-button {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 80px);
|
||||
justify-content: flex-start;
|
||||
max-height: calc(100vh - 80px);
|
||||
min-width: min(600px, calc(100vw - 40px));
|
||||
}
|
||||
}
|
||||
|
||||
.modal-message-scrollable-content {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-message-actions {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: flex-end;
|
||||
padding-top: 20px;
|
||||
|
||||
button {
|
||||
min-width: 80px;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-animation {
|
||||
|
||||
Reference in new issue
Block a user