mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Fixed folder selection and deletion issue
This commit is contained in:
parent
c9becb95aa
commit
57995b1818
@ -520,7 +520,7 @@ class Application {
|
|||||||
const result = next(action);
|
const result = next(action);
|
||||||
const newState = store.getState();
|
const newState = store.getState();
|
||||||
|
|
||||||
if (action.type == 'FOLDERS_SELECT') {
|
if (action.type == 'FOLDERS_SELECT' || action.type === 'FOLDER_DELETE') {
|
||||||
Setting.setValue('activeFolderId', newState.selectedFolderId);
|
Setting.setValue('activeFolderId', newState.selectedFolderId);
|
||||||
this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null;
|
this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null;
|
||||||
await this.refreshNotes(Folder.modelType(), newState.selectedFolderId);
|
await this.refreshNotes(Folder.modelType(), newState.selectedFolderId);
|
||||||
|
@ -43,8 +43,8 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set selectedFolderId(v) {
|
set selectedFolderId(v) {
|
||||||
this.updateIndexFromSelectedItemId()
|
|
||||||
this.selectedFolderId_ = v;
|
this.selectedFolderId_ = v;
|
||||||
|
this.updateIndexFromSelectedItemId()
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set selectedSearchId(v) {
|
set selectedSearchId(v) {
|
||||||
this.updateIndexFromSelectedItemId()
|
|
||||||
this.selectedSearchId_ = v;
|
this.selectedSearchId_ = v;
|
||||||
|
this.updateIndexFromSelectedItemId()
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set selectedTagId(v) {
|
set selectedTagId(v) {
|
||||||
this.updateIndexFromSelectedItemId()
|
|
||||||
this.selectedTagId_ = v;
|
this.selectedTagId_ = v;
|
||||||
|
this.updateIndexFromSelectedItemId()
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set notesParentType(v) {
|
set notesParentType(v) {
|
||||||
if (this.notesParentType_ === v) return;
|
//if (this.notesParentType_ === v) return;
|
||||||
this.notesParentType_ = v;
|
this.notesParentType_ = v;
|
||||||
this.updateIndexFromSelectedItemId()
|
this.updateIndexFromSelectedItemId()
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
@ -84,8 +84,6 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set searches(v) {
|
set searches(v) {
|
||||||
if (this.searches_ === v) return;
|
|
||||||
|
|
||||||
this.searches_ = v;
|
this.searches_ = v;
|
||||||
this.updateItems_ = true;
|
this.updateItems_ = true;
|
||||||
this.updateIndexFromSelectedItemId()
|
this.updateIndexFromSelectedItemId()
|
||||||
@ -97,8 +95,6 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set tags(v) {
|
set tags(v) {
|
||||||
if (this.tags_ === v) return;
|
|
||||||
|
|
||||||
this.tags_ = v;
|
this.tags_ = v;
|
||||||
this.updateItems_ = true;
|
this.updateItems_ = true;
|
||||||
this.updateIndexFromSelectedItemId()
|
this.updateIndexFromSelectedItemId()
|
||||||
@ -110,15 +106,13 @@ class FolderListWidget extends ListWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set folders(v) {
|
set folders(v) {
|
||||||
if (this.folders_ === v) return;
|
|
||||||
|
|
||||||
this.folders_ = v;
|
this.folders_ = v;
|
||||||
this.updateItems_ = true;
|
this.updateItems_ = true;
|
||||||
this.updateIndexFromSelectedItemId()
|
this.updateIndexFromSelectedItemId()
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
async onWillRender() {
|
render() {
|
||||||
if (this.updateItems_) {
|
if (this.updateItems_) {
|
||||||
this.logger().debug('Rebuilding items...', this.notesParentType, this.selectedJoplinItemId, this.selectedSearchId);
|
this.logger().debug('Rebuilding items...', this.notesParentType, this.selectedJoplinItemId, this.selectedSearchId);
|
||||||
const wasSelectedItemId = this.selectedJoplinItemId;
|
const wasSelectedItemId = this.selectedJoplinItemId;
|
||||||
@ -136,12 +130,14 @@ class FolderListWidget extends ListWidget {
|
|||||||
newItems = newItems.concat(this.searches);
|
newItems = newItems.concat(this.searches);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.items = newItems;
|
this.items = newItems;
|
||||||
|
|
||||||
this.notesParentType = previousParentType;
|
this.notesParentType = previousParentType;
|
||||||
this.updateIndexFromSelectedItemId(wasSelectedItemId)
|
this.updateIndexFromSelectedItemId(wasSelectedItemId)
|
||||||
this.updateItems_ = false;
|
this.updateItems_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
get selectedJoplinItemId() {
|
get selectedJoplinItemId() {
|
||||||
|
18
README.md
18
README.md
@ -1,6 +1,12 @@
|
|||||||
# Joplin
|
# Joplin
|
||||||
|
|
||||||
INTRODUCTION
|
Joplin is a free, open source note taking and todo application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified with your own text editor.
|
||||||
|
|
||||||
|
Notes exported from Evenotes via .enex files [can be imported](#importing-notes-from-evernote) into Joplin, including the formatted content (which is converted to markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.).
|
||||||
|
|
||||||
|
The notes can be [synchronised](#synchronisation) with various targets including the file system (for example with a network directory) or with Microsoft OneDrive. When synchronising the notes, notebooks, tags and other metadata are saved to plain text files which can be easily inspected, backed up and moved around.
|
||||||
|
|
||||||
|
The application is still under development but is out of Beta and should be suitable for every day use.
|
||||||
|
|
||||||
![Joplin Terminal Screenshot](https://github.com/laurent22/joplin/blob/master/docs/images/ScreenshotTerminal.png)
|
![Joplin Terminal Screenshot](https://github.com/laurent22/joplin/blob/master/docs/images/ScreenshotTerminal.png)
|
||||||
|
|
||||||
@ -114,19 +120,21 @@ INFO ABOUT SYNC
|
|||||||
|
|
||||||
# Android client
|
# Android client
|
||||||
|
|
||||||
LINK TO ANDROID CLIENT
|
An Android client is available and can synchronise with the terminal client via OneDrive:
|
||||||
|
|
||||||
|
<a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png'/></a>
|
||||||
|
|
||||||
# URLs
|
# URLs
|
||||||
|
|
||||||
By pressing Ctrl+Click on a URL, most terminals will open that URL in the default browser. However, one issue especially with long URLs is that they can end up like this:
|
By pressing Ctrl+Click on a URL, most terminals will open that URL in the default browser. However, one issue especially with long URLs is that they can end up like this:
|
||||||
|
|
||||||
<img src="https://github.com/laurent22/joplin/blob/master/docs/images/UrlCut.png" width="240">
|
<img src="https://github.com/laurent22/joplin/blob/master/docs/images/UrlCut.png" width="240px">
|
||||||
|
|
||||||
Not only it makes the text hard to read, but the link, being cut in two, will also not be clickable.
|
Not only it makes the text hard to read, but the link, being cut in two, will also not be clickable.
|
||||||
|
|
||||||
As a solution Joplin tries to start a mini-server in the background and, if successful, all the links will be converted to a much shorter, local URL:
|
As a solution Joplin tries to start a mini-server in the background and, if successful, all the links will be converted to a much shorter, local URL:
|
||||||
|
|
||||||
<img src="https://github.com/laurent22/joplin/blob/master/docs/images/UrlNoCut.png" width="240">
|
<img src="https://github.com/laurent22/joplin/blob/master/docs/images/UrlNoCut.png" width="240px">
|
||||||
|
|
||||||
With this it means that not only the text will be more readable but links are also unlikely to be cut. Note that both resources (files that are attached to notes) and external links are handled in this way.
|
With this it means that not only the text will be more readable but links are also unlikely to be cut. Note that both resources (files that are attached to notes) and external links are handled in this way.
|
||||||
|
|
||||||
@ -147,8 +155,6 @@ The applications is currently available in English and French. If you would like
|
|||||||
|
|
||||||
There are two types of shortcuts: those that manipulate the user interface directly, such as TAB to move from one widget to another, and those that are simply shortcuts to actual commands. In a way similar to Vim, these commands are generally a verb followed by an object. For example, typing `mn` ([m]ake [n]ote), is used to create a new note, it will switch the interface to command line mode and pre-fill it with `mknote ""` from where the title of the note can be entered.
|
There are two types of shortcuts: those that manipulate the user interface directly, such as TAB to move from one widget to another, and those that are simply shortcuts to actual commands. In a way similar to Vim, these commands are generally a verb followed by an object. For example, typing `mn` ([m]ake [n]ote), is used to create a new note, it will switch the interface to command line mode and pre-fill it with `mknote ""` from where the title of the note can be entered.
|
||||||
|
|
||||||
*List of shortcuts:*
|
|
||||||
|
|
||||||
Tab Give focus to next widget
|
Tab Give focus to next widget
|
||||||
Shift+Tab Give focus to previous widget
|
Shift+Tab Give focus to previous widget
|
||||||
: Enter command line mode
|
: Enter command line mode
|
||||||
|
@ -39,6 +39,38 @@ function historyCanGoBackTo(route) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function folderOrNoteDelete(state, action) {
|
||||||
|
let newState = Object.assign({}, state);
|
||||||
|
|
||||||
|
const idKey = action.type === 'FOLDER_DELETE' ? 'folderId' : 'noteId';
|
||||||
|
const listKey = action.type === 'FOLDER_DELETE' ? 'folders' : 'notes';
|
||||||
|
const selectedItemKey = action.type === 'FOLDER_DELETE' ? 'selectedFolderId' : 'selectedNoteId';
|
||||||
|
|
||||||
|
let previousIndex = 0;
|
||||||
|
let newItems = [];
|
||||||
|
const items = state[listKey];
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
let f = items[i];
|
||||||
|
if (f.id == action[idKey]) {
|
||||||
|
previousIndex = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newItems.push(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
newState = Object.assign({}, state);
|
||||||
|
newState[listKey] = newItems;
|
||||||
|
|
||||||
|
if (previousIndex >= newItems.length) {
|
||||||
|
previousIndex = newItems.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newIndex = previousIndex >= 0 ? newItems[previousIndex].id : null;
|
||||||
|
newState[selectedItemKey] = newIndex;
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
function updateOneTagOrFolder(state, action) {
|
function updateOneTagOrFolder(state, action) {
|
||||||
let newItems = action.type === 'TAGS_UPDATE_ONE' ? state.tags.splice(0) : state.folders.splice(0);
|
let newItems = action.type === 'TAGS_UPDATE_ONE' ? state.tags.splice(0) : state.folders.splice(0);
|
||||||
let item = action.type === 'TAGS_UPDATE_ONE' ? action.tag : action.folder;
|
let item = action.type === 'TAGS_UPDATE_ONE' ? action.tag : action.folder;
|
||||||
@ -87,7 +119,6 @@ const reducer = (state = defaultState, action) => {
|
|||||||
try {
|
try {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
|
||||||
|
|
||||||
case 'NAV_BACK':
|
case 'NAV_BACK':
|
||||||
|
|
||||||
if (!navHistory.length) break;
|
if (!navHistory.length) break;
|
||||||
@ -246,25 +277,7 @@ const reducer = (state = defaultState, action) => {
|
|||||||
|
|
||||||
case 'NOTES_DELETE':
|
case 'NOTES_DELETE':
|
||||||
|
|
||||||
var previousIndex = 0;
|
newState = folderOrNoteDelete(state, action);
|
||||||
var newNotes = [];
|
|
||||||
for (let i = 0; i < state.notes.length; i++) {
|
|
||||||
let f = state.notes[i];
|
|
||||||
if (f.id == action.noteId) {
|
|
||||||
previousIndex = i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
newNotes.push(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
|
||||||
newState.notes = newNotes;
|
|
||||||
|
|
||||||
if (previousIndex >= newNotes.length) {
|
|
||||||
previousIndex = newNotes.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
newState.selectedNoteId = previousIndex >= 0 ? newNotes[previousIndex].id : null;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'FOLDERS_UPDATE_ALL':
|
case 'FOLDERS_UPDATE_ALL':
|
||||||
@ -293,55 +306,16 @@ const reducer = (state = defaultState, action) => {
|
|||||||
case 'TAGS_UPDATE_ONE':
|
case 'TAGS_UPDATE_ONE':
|
||||||
|
|
||||||
newState = updateOneTagOrFolder(state, action);
|
newState = updateOneTagOrFolder(state, action);
|
||||||
|
|
||||||
// var newTags = state.tags.splice(0);
|
|
||||||
// var found = false;
|
|
||||||
// for (let i = 0; i < newTags.length; i++) {
|
|
||||||
// let n = newTags[i];
|
|
||||||
// if (n.id == action.tag.id) {
|
|
||||||
// newTags[i] = Object.assign(newTags[i], action.tag);
|
|
||||||
// found = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!found) newTags.push(action.tag);
|
|
||||||
|
|
||||||
// newState = Object.assign({}, state);
|
|
||||||
// newState.tags = newTags;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'FOLDERS_UPDATE_ONE':
|
case 'FOLDERS_UPDATE_ONE':
|
||||||
|
|
||||||
newState = updateOneTagOrFolder(state, action);
|
newState = updateOneTagOrFolder(state, action);
|
||||||
// var newFolders = state.folders.splice(0);
|
|
||||||
// var found = false;
|
|
||||||
// for (let i = 0; i < newFolders.length; i++) {
|
|
||||||
// let n = newFolders[i];
|
|
||||||
// if (n.id == action.folder.id) {
|
|
||||||
// newFolders[i] = Object.assign(newFolders[i], action.folder);
|
|
||||||
// found = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!found) newFolders.push(action.folder);
|
|
||||||
|
|
||||||
// newState = Object.assign({}, state);
|
|
||||||
// newState.folders = newFolders;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'FOLDER_DELETE':
|
case 'FOLDER_DELETE':
|
||||||
|
|
||||||
var newFolders = [];
|
newState = folderOrNoteDelete(state, action);
|
||||||
for (let i = 0; i < state.folders.length; i++) {
|
|
||||||
let f = state.folders[i];
|
|
||||||
if (f.id == action.folderId) continue;
|
|
||||||
newFolders.push(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
newState = Object.assign({}, state);
|
|
||||||
newState.folders = newFolders;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'SIDE_MENU_TOGGLE':
|
case 'SIDE_MENU_TOGGLE':
|
||||||
|
Loading…
Reference in New Issue
Block a user