You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-11-26 22:41:17 +02:00
Desktop, Mobile: Fixes #13258: Prevent new notes from being created in trashed or missing notebooks in certain cases (#13575)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { utils, CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
import { utils, CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
import Setting from '@joplin/lib/models/Setting';
|
|
||||||
import Note from '@joplin/lib/models/Note';
|
import Note from '@joplin/lib/models/Note';
|
||||||
|
import Folder from '@joplin/lib/models/Folder';
|
||||||
|
|
||||||
export const newNoteEnabledConditions = 'oneFolderSelected && !inConflictFolder && !folderIsReadOnly && !folderIsTrash';
|
export const newNoteEnabledConditions = 'oneFolderSelected && !inConflictFolder && !folderIsReadOnly && !folderIsTrash';
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ export const declaration: CommandDeclaration = {
|
|||||||
export const runtime = (): CommandRuntime => {
|
export const runtime = (): CommandRuntime => {
|
||||||
return {
|
return {
|
||||||
execute: async (_context: CommandContext, body = '', isTodo = false) => {
|
execute: async (_context: CommandContext, body = '', isTodo = false) => {
|
||||||
const folderId = Setting.value('activeFolderId');
|
const folderId = await Folder.getValidActiveFolder();
|
||||||
if (!folderId) return;
|
if (!folderId) return;
|
||||||
|
|
||||||
const defaultValues = Note.previewFieldsWithDefaultValues({ includeTimestamps: false });
|
const defaultValues = Note.previewFieldsWithDefaultValues({ includeTimestamps: false });
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
|||||||
import Logger from '@joplin/utils/Logger';
|
import Logger from '@joplin/utils/Logger';
|
||||||
import goToNote, { GotoNoteOptions } from './util/goToNote';
|
import goToNote, { GotoNoteOptions } from './util/goToNote';
|
||||||
import Note from '@joplin/lib/models/Note';
|
import Note from '@joplin/lib/models/Note';
|
||||||
import Setting from '@joplin/lib/models/Setting';
|
import Folder from '@joplin/lib/models/Folder';
|
||||||
|
|
||||||
const logger = Logger.create('newNoteCommand');
|
const logger = Logger.create('newNoteCommand');
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ export const declaration: CommandDeclaration = {
|
|||||||
export const runtime = (): CommandRuntime => {
|
export const runtime = (): CommandRuntime => {
|
||||||
return {
|
return {
|
||||||
execute: async (_context: CommandContext, body = '', todo = false, options: GotoNoteOptions = null) => {
|
execute: async (_context: CommandContext, body = '', todo = false, options: GotoNoteOptions = null) => {
|
||||||
const folderId = Setting.value('activeFolderId');
|
const folderId = await Folder.getValidActiveFolder();
|
||||||
if (!folderId) {
|
if (!folderId) {
|
||||||
logger.warn('Not creating new note -- no active folder ID.');
|
logger.warn('Not creating new note -- no active folder ID.');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { FolderEntity } from '../services/database/types';
|
|||||||
import { createNTestNotes, setupDatabaseAndSynchronizer, sleep, switchClient, checkThrowAsync, createFolderTree, simulateReadOnlyShareEnv, expectThrow, withWarningSilenced } from '../testing/test-utils';
|
import { createNTestNotes, setupDatabaseAndSynchronizer, sleep, switchClient, checkThrowAsync, createFolderTree, simulateReadOnlyShareEnv, expectThrow, withWarningSilenced } from '../testing/test-utils';
|
||||||
import Folder from './Folder';
|
import Folder from './Folder';
|
||||||
import Note from './Note';
|
import Note from './Note';
|
||||||
|
import Setting from './Setting';
|
||||||
|
|
||||||
async function allItems() {
|
async function allItems() {
|
||||||
const folders = await Folder.all();
|
const folders = await Folder.all();
|
||||||
@@ -440,4 +441,40 @@ describe('models/Folder', () => {
|
|||||||
expect(Folder.atLeastOneRealFolderExists(folders)).toBe(false);
|
expect(Folder.atLeastOneRealFolderExists(folders)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should get active folder when activeFolderId is valid', async () => {
|
||||||
|
const activeFolder = await Folder.save({ title: 'folder' });
|
||||||
|
Setting.setValue('activeFolderId', activeFolder.id);
|
||||||
|
|
||||||
|
const validFolder = await Folder.getValidActiveFolder();
|
||||||
|
expect(validFolder).toBe(activeFolder.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get default folder when activeFolderId is trashed', async () => {
|
||||||
|
const defaultFolder = await Folder.save({ title: 'default' });
|
||||||
|
const activeFolder = await Folder.save({ title: 'folder' });
|
||||||
|
await Folder.delete(activeFolder.id, { toTrash: true });
|
||||||
|
Setting.setValue('activeFolderId', activeFolder.id);
|
||||||
|
|
||||||
|
const validFolder = await Folder.getValidActiveFolder();
|
||||||
|
expect(validFolder).toBe(defaultFolder.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get no folder when activeFolderId is undefined', async () => {
|
||||||
|
Setting.setValue('activeFolderId', undefined);
|
||||||
|
|
||||||
|
const validFolder = await Folder.getValidActiveFolder();
|
||||||
|
expect(validFolder).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get no folder when activeFolderId is trashed and there are no other not trashed folders', async () => {
|
||||||
|
const activeFolder = await Folder.save({ title: 'folder' });
|
||||||
|
const otherFolder = await Folder.save({ title: 'other' });
|
||||||
|
await Folder.delete(activeFolder.id, { toTrash: true });
|
||||||
|
await Folder.delete(otherFolder.id, { toTrash: true });
|
||||||
|
Setting.setValue('activeFolderId', activeFolder.id);
|
||||||
|
|
||||||
|
const validFolder = await Folder.getValidActiveFolder();
|
||||||
|
expect(validFolder).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { getTrashFolder } from '../services/trash';
|
|||||||
import getConflictFolderId from './utils/getConflictFolderId';
|
import getConflictFolderId from './utils/getConflictFolderId';
|
||||||
import getTrashFolderId from '../services/trash/getTrashFolderId';
|
import getTrashFolderId from '../services/trash/getTrashFolderId';
|
||||||
import { getCollator } from './utils/getCollator';
|
import { getCollator } from './utils/getCollator';
|
||||||
|
import Setting from './Setting';
|
||||||
const { substrWithEllipsis } = require('../string-utils.js');
|
const { substrWithEllipsis } = require('../string-utils.js');
|
||||||
|
|
||||||
const logger = Logger.create('models/Folder');
|
const logger = Logger.create('models/Folder');
|
||||||
@@ -918,7 +919,7 @@ export default class Folder extends BaseItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static defaultFolder() {
|
public static defaultFolder() {
|
||||||
return this.modelSelectOne('SELECT * FROM folders ORDER BY created_time DESC LIMIT 1');
|
return this.modelSelectOne('SELECT * FROM folders WHERE deleted_time = 0 ORDER BY created_time DESC LIMIT 1');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async canNestUnder(folderId: string, targetFolderId: string) {
|
public static async canNestUnder(folderId: string, targetFolderId: string) {
|
||||||
@@ -1076,4 +1077,18 @@ export default class Folder extends BaseItem {
|
|||||||
return this.getRealFolders(folders).length > 0;
|
return this.getRealFolders(folders).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async getValidActiveFolder() {
|
||||||
|
const folderId = Setting.value('activeFolderId');
|
||||||
|
if (!folderId) return null;
|
||||||
|
|
||||||
|
const folder = await Folder.load(folderId);
|
||||||
|
if (!folder || !!folder.deleted_time) {
|
||||||
|
const defaultFolder = await Folder.defaultFolder();
|
||||||
|
if (!defaultFolder) return null;
|
||||||
|
return defaultFolder.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return folderId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user