mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
This commit is contained in:
parent
050a896c8b
commit
220f867814
@ -209,7 +209,6 @@ packages/app-desktop/gui/MainScreen/MainScreen.js
|
||||
packages/app-desktop/gui/MainScreen/commands/addProfile.js
|
||||
packages/app-desktop/gui/MainScreen/commands/commandPalette.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/duplicateNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/editAlarm.js
|
||||
packages/app-desktop/gui/MainScreen/commands/exportPdf.js
|
||||
@ -228,7 +227,6 @@ packages/app-desktop/gui/MainScreen/commands/openItem.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openPdfViewer.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openTag.js
|
||||
packages/app-desktop/gui/MainScreen/commands/permanentlyDeleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/print.js
|
||||
packages/app-desktop/gui/MainScreen/commands/renameFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/renameTag.js
|
||||
@ -921,10 +919,12 @@ packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/clipperUtils.js
|
||||
packages/lib/commands/deleteNote.js
|
||||
packages/lib/commands/historyBackward.js
|
||||
packages/lib/commands/historyForward.js
|
||||
packages/lib/commands/index.js
|
||||
packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/permanentlyDeleteNote.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.test.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -186,7 +186,6 @@ packages/app-desktop/gui/MainScreen/MainScreen.js
|
||||
packages/app-desktop/gui/MainScreen/commands/addProfile.js
|
||||
packages/app-desktop/gui/MainScreen/commands/commandPalette.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/duplicateNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/editAlarm.js
|
||||
packages/app-desktop/gui/MainScreen/commands/exportPdf.js
|
||||
@ -205,7 +204,6 @@ packages/app-desktop/gui/MainScreen/commands/openItem.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openPdfViewer.js
|
||||
packages/app-desktop/gui/MainScreen/commands/openTag.js
|
||||
packages/app-desktop/gui/MainScreen/commands/permanentlyDeleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/print.js
|
||||
packages/app-desktop/gui/MainScreen/commands/renameFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/renameTag.js
|
||||
@ -898,10 +896,12 @@ packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/clipperUtils.js
|
||||
packages/lib/commands/deleteNote.js
|
||||
packages/lib/commands/historyBackward.js
|
||||
packages/lib/commands/historyForward.js
|
||||
packages/lib/commands/index.js
|
||||
packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/permanentlyDeleteNote.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.test.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
|
@ -2,7 +2,6 @@
|
||||
import * as addProfile from './addProfile';
|
||||
import * as commandPalette from './commandPalette';
|
||||
import * as deleteFolder from './deleteFolder';
|
||||
import * as deleteNote from './deleteNote';
|
||||
import * as duplicateNote from './duplicateNote';
|
||||
import * as editAlarm from './editAlarm';
|
||||
import * as exportPdf from './exportPdf';
|
||||
@ -20,7 +19,6 @@ import * as openItem from './openItem';
|
||||
import * as openNote from './openNote';
|
||||
import * as openPdfViewer from './openPdfViewer';
|
||||
import * as openTag from './openTag';
|
||||
import * as permanentlyDeleteNote from './permanentlyDeleteNote';
|
||||
import * as print from './print';
|
||||
import * as renameFolder from './renameFolder';
|
||||
import * as renameTag from './renameTag';
|
||||
@ -52,7 +50,6 @@ const index: any[] = [
|
||||
addProfile,
|
||||
commandPalette,
|
||||
deleteFolder,
|
||||
deleteNote,
|
||||
duplicateNote,
|
||||
editAlarm,
|
||||
exportPdf,
|
||||
@ -70,7 +67,6 @@ const index: any[] = [
|
||||
openNote,
|
||||
openPdfViewer,
|
||||
openTag,
|
||||
permanentlyDeleteNote,
|
||||
print,
|
||||
renameFolder,
|
||||
renameTag,
|
||||
|
@ -23,6 +23,7 @@ import ItemChange from '@joplin/lib/models/ItemChange';
|
||||
import { getDisplayParentId } from '@joplin/lib/services/trash';
|
||||
import { itemIsReadOnlySync, ItemSlice } from '@joplin/lib/models/utils/readOnly';
|
||||
import { LayoutChangeEvent } from 'react-native';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
interface WrapperProps {
|
||||
}
|
||||
@ -140,6 +141,24 @@ describe('Note', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('pressing "delete permanently" should permanently delete a note', async () => {
|
||||
const noteId = await openNewNote({ title: 'To be deleted', body: '...', deleted_time: Date.now() });
|
||||
render(<WrappedNoteScreen />);
|
||||
|
||||
// Permanently delete note shows a confirmation dialog -- mock it.
|
||||
const deleteId = 0;
|
||||
shim.showMessageBox = jest.fn(async () => deleteId);
|
||||
|
||||
await openNoteActionsMenu();
|
||||
const deleteButton = await screen.findByText('Permanently delete note');
|
||||
fireEvent.press(deleteButton);
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(await Note.load(noteId)).toBeUndefined();
|
||||
});
|
||||
expect(shim.showMessageBox).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('delete should be disabled in a read-only note', async () => {
|
||||
const shareId = 'testShare';
|
||||
const noteId = await openNewNote({
|
||||
|
@ -627,21 +627,6 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
|
||||
await shared.saveOneProperty(this, name, value);
|
||||
}
|
||||
|
||||
private async deleteNote_onPress() {
|
||||
const note = this.state.note;
|
||||
if (!note.id) return;
|
||||
|
||||
const folderId = note.parent_id;
|
||||
|
||||
await Note.delete(note.id, { toTrash: true, sourceDescription: 'Delete note button' });
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Notes',
|
||||
folderId: folderId,
|
||||
});
|
||||
}
|
||||
|
||||
private async pickDocuments() {
|
||||
const result = await pickDocument({ multiple: true });
|
||||
return result;
|
||||
@ -1283,30 +1268,33 @@ class NoteScreenComponent extends BaseScreenComponent<Props, State> implements B
|
||||
});
|
||||
}
|
||||
|
||||
output.push({
|
||||
title: _('Delete'),
|
||||
onPress: () => {
|
||||
void this.deleteNote_onPress();
|
||||
},
|
||||
disabled: readOnly,
|
||||
});
|
||||
const commandService = CommandService.instance();
|
||||
const whenContext = commandService.currentWhenClauseContext();
|
||||
const addButtonFromCommand = (commandName: string, title?: string) => {
|
||||
if (commandName === '-') {
|
||||
output.push({ isDivider: true });
|
||||
} else {
|
||||
output.push({
|
||||
title: title ?? commandService.description(commandName),
|
||||
onPress: async () => {
|
||||
void commandService.execute(commandName);
|
||||
},
|
||||
disabled: !commandService.isEnabled(commandName, whenContext),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (whenContext.inTrash) {
|
||||
addButtonFromCommand('permanentlyDeleteNote');
|
||||
} else {
|
||||
addButtonFromCommand('deleteNote', _('Delete'));
|
||||
}
|
||||
|
||||
if (pluginCommands.length) {
|
||||
output.push({ isDivider: true });
|
||||
|
||||
const commandService = CommandService.instance();
|
||||
for (const commandName of pluginCommands) {
|
||||
if (commandName === '-') {
|
||||
output.push({ isDivider: true });
|
||||
} else {
|
||||
output.push({
|
||||
title: commandService.description(commandName),
|
||||
onPress: async () => {
|
||||
void commandService.execute(commandName);
|
||||
},
|
||||
disabled: !commandService.isEnabled(commandName),
|
||||
});
|
||||
}
|
||||
addButtonFromCommand(commandName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '../services/CommandService';
|
||||
import { _ } from '../locale';
|
||||
import Note from '../models/Note';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'deleteNote',
|
@ -1,13 +1,17 @@
|
||||
// AUTO-GENERATED using `gulp buildScriptIndexes`
|
||||
import * as deleteNote from './deleteNote';
|
||||
import * as historyBackward from './historyBackward';
|
||||
import * as historyForward from './historyForward';
|
||||
import * as openMasterPasswordDialog from './openMasterPasswordDialog';
|
||||
import * as permanentlyDeleteNote from './permanentlyDeleteNote';
|
||||
import * as synchronize from './synchronize';
|
||||
|
||||
const index: any[] = [
|
||||
deleteNote,
|
||||
historyBackward,
|
||||
historyForward,
|
||||
openMasterPasswordDialog,
|
||||
permanentlyDeleteNote,
|
||||
synchronize,
|
||||
];
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import bridge from '../../../services/bridge';
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '../services/CommandService';
|
||||
import { _ } from '../locale';
|
||||
import Note from '../models/Note';
|
||||
import shim from '../shim';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'permanentlyDeleteNote',
|
||||
@ -16,12 +16,15 @@ export const runtime = (): CommandRuntime => {
|
||||
if (!noteIds.length) return;
|
||||
const msg = await Note.permanentlyDeleteMessage(noteIds);
|
||||
|
||||
const ok = bridge().showConfirmMessageBox(msg, {
|
||||
const deleteIndex = 0;
|
||||
const result = await shim.showMessageBox(msg, {
|
||||
buttons: [_('Delete'), _('Cancel')],
|
||||
defaultId: 1,
|
||||
cancelId: 1,
|
||||
type: 'question',
|
||||
});
|
||||
|
||||
if (ok) {
|
||||
if (result === deleteIndex) {
|
||||
await Note.batchDelete(noteIds, { toTrash: false, sourceDescription: 'permanentlyDeleteNote command' });
|
||||
}
|
||||
},
|
@ -280,19 +280,32 @@ shared.initState = async function(comp: BaseNoteScreenComponent) {
|
||||
comp.scheduleFocusUpdate();
|
||||
}
|
||||
|
||||
const folder = Folder.byId(comp.props.folders, note.parent_id);
|
||||
|
||||
comp.setState({
|
||||
lastSavedNote: { ...note },
|
||||
note: note,
|
||||
mode: mode,
|
||||
folder: folder,
|
||||
isLoading: false,
|
||||
fromShare: !!comp.props.sharedData,
|
||||
noteResources: await shared.attachedResources(note ? note.body : ''),
|
||||
readOnly: itemIsReadOnlySync(ModelType.Note, ItemChange.SOURCE_UNSPECIFIED, note as ItemSlice, Setting.value('sync.userId'), BaseItem.syncShareCache),
|
||||
});
|
||||
|
||||
const fromShare = !!comp.props.sharedData;
|
||||
if (note) {
|
||||
const folder = Folder.byId(comp.props.folders, note.parent_id);
|
||||
comp.setState({
|
||||
lastSavedNote: { ...note },
|
||||
note: note,
|
||||
mode: mode,
|
||||
folder: folder,
|
||||
isLoading: false,
|
||||
fromShare: !!comp.props.sharedData,
|
||||
noteResources: await shared.attachedResources(note ? note.body : ''),
|
||||
readOnly: itemIsReadOnlySync(ModelType.Note, ItemChange.SOURCE_UNSPECIFIED, note as ItemSlice, Setting.value('sync.userId'), BaseItem.syncShareCache),
|
||||
});
|
||||
} else {
|
||||
// Handle the case where a non-existent note is loaded. This can happen briefly after deleting a note.
|
||||
comp.setState({
|
||||
lastSavedNote: {},
|
||||
note: {},
|
||||
mode,
|
||||
folder: null,
|
||||
isLoading: true,
|
||||
fromShare,
|
||||
noteResources: [],
|
||||
readOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (comp.props.sharedData) {
|
||||
if (comp.props.sharedData.title) {
|
||||
@ -315,7 +328,7 @@ shared.initState = async function(comp: BaseNoteScreenComponent) {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
comp.lastLoadedNoteId_ = note.id;
|
||||
comp.lastLoadedNoteId_ = note?.id;
|
||||
};
|
||||
|
||||
shared.toggleIsTodo_onPress = function(comp: BaseNoteScreenComponent) {
|
||||
|
Loading…
Reference in New Issue
Block a user