diff --git a/CliClient/tests/models_Folder.js b/CliClient/tests/models_Folder.js index a96b861704..17ec6a4bb7 100644 --- a/CliClient/tests/models_Folder.js +++ b/CliClient/tests/models_Folder.js @@ -199,4 +199,23 @@ describe('models_Folder', function() { expect(folderPath[2].id).toBe(f3.id); })); + it('should sort folders alphabetically', asyncTest(async () => { + const f1 = await Folder.save({ title: 'folder1' }); + const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); + const f3 = await Folder.save({ title: 'folder3', parent_id: f1.id }); + const f4 = await Folder.save({ title: 'folder4' }); + const f5 = await Folder.save({ title: 'folder5', parent_id: f4.id }); + const f6 = await Folder.save({ title: 'folder6' }); + + const folders = await Folder.allAsTree(); + const sortedFolderTree = await Folder.sortFolderTree(folders); + + expect(sortedFolderTree.length).toBe(3); + expect(sortedFolderTree[0].id).toBe(f1.id); + expect(sortedFolderTree[0].children[0].id).toBe(f2.id); + expect(sortedFolderTree[0].children[1].id).toBe(f3.id); + expect(sortedFolderTree[1].id).toBe(f4.id); + expect(sortedFolderTree[1].children[0].id).toBe(f5.id); + expect(sortedFolderTree[2].id).toBe(f6.id); + })); }); diff --git a/ElectronClient/gui/MainScreen.jsx b/ElectronClient/gui/MainScreen.jsx index 864417499f..63ff30ef7d 100644 --- a/ElectronClient/gui/MainScreen.jsx +++ b/ElectronClient/gui/MainScreen.jsx @@ -248,6 +248,7 @@ class MainScreenComponent extends React.Component { }, }); } else if (command.name === 'moveToFolder') { + const folders = await Folder.sortFolderTree(); const startFolders = []; const maxDepth = 15; @@ -258,7 +259,8 @@ class MainScreenComponent extends React.Component { if (folder.children) addOptions(folder.children, (depth + 1) < maxDepth ? depth + 1 : maxDepth); } }; - addOptions(await Folder.allAsTree(), 0); + + addOptions(folders, 0); this.setState({ promptOptions: { @@ -748,7 +750,7 @@ class MainScreenComponent extends React.Component { color: theme.color, backgroundColor: theme.backgroundColor, }, - this.props.style + this.props.style, ); const promptOptions = this.state.promptOptions; const folders = this.props.folders; diff --git a/ReactNativeClient/lib/models/Folder.js b/ReactNativeClient/lib/models/Folder.js index 37296d64d2..25a79aee84 100644 --- a/ReactNativeClient/lib/models/Folder.js +++ b/ReactNativeClient/lib/models/Folder.js @@ -323,6 +323,33 @@ class Folder extends BaseItem { return rootFolders; } + static async sortFolderTree(folders) { + const output = folders ? folders : await this.allAsTree(); + + const sortFoldersAlphabetically = (folders) => { + folders.sort((a, b) => { + if (a.parentId === b.parentId) { + return a.title.localeCompare(b.title, undefined, { sensitivity: 'accent' }); + } + }); + return folders; + }; + + const sortFolders = (folders) => { + for (let i = 0; i < folders.length; i++) { + const folder = folders[i]; + if (folder.children) { + folder.children = sortFoldersAlphabetically(folder.children); + sortFolders(folder.children); + } + } + return folders; + }; + + sortFolders(sortFoldersAlphabetically(output)); + return output; + } + static load(id) { if (id == this.conflictFolderId()) return this.conflictFolder(); return super.load(id);