mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-11 18:24:43 +02:00
All: Handle saving collapsed states of sub-notebook
This commit is contained in:
parent
567596643c
commit
da6fdad2de
@ -615,6 +615,11 @@ class Application extends BaseApplication {
|
||||
id: Setting.value('activeFolderId'),
|
||||
});
|
||||
|
||||
this.store().dispatch({
|
||||
type: 'FOLDER_SET_COLLAPSED_ALL',
|
||||
ids: Setting.value('collapsedFolderIds'),
|
||||
});
|
||||
|
||||
// Note: Auto-update currently doesn't work in Linux: it downloads the update
|
||||
// but then doesn't install it on exit.
|
||||
if (shim.isWindows() || shim.isMac()) {
|
||||
|
@ -54,6 +54,15 @@ class SideBarComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.onFolderToggleClick_ = async (event) => {
|
||||
const folderId = event.currentTarget.getAttribute('folderid');
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'FOLDER_TOGGLE',
|
||||
id: folderId,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
style() {
|
||||
@ -68,7 +77,7 @@ class SideBarComponent extends React.Component {
|
||||
listItemContainer: {
|
||||
boxSizing: "border-box",
|
||||
height: itemHeight,
|
||||
paddingLeft: 14,
|
||||
// paddingLeft: 14,
|
||||
display: "flex",
|
||||
alignItems: "stretch",
|
||||
},
|
||||
@ -272,19 +281,22 @@ class SideBarComponent extends React.Component {
|
||||
const itemTitle = Folder.displayTitle(folder);
|
||||
|
||||
let containerStyle = Object.assign({}, this.style().listItemContainer);
|
||||
containerStyle.paddingLeft = containerStyle.paddingLeft + depth * 10;
|
||||
// containerStyle.paddingLeft = containerStyle.paddingLeft + depth * 10;
|
||||
|
||||
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
|
||||
|
||||
let expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
|
||||
let expandIconStyle = {
|
||||
visibility: hasChildren ? 'visible' : 'hidden',
|
||||
paddingLeft: 8 + depth * 10,
|
||||
}
|
||||
const expandIcon = <i style={expandIconStyle} className="fa fa-plus-square"></i>
|
||||
const expandLink = hasChildren ? <a style={expandLinkStyle} href="#" onClick={() => console.info('click')}>{expandIcon}</a> : <span style={expandLinkStyle}>{expandIcon}</span>
|
||||
|
||||
const iconName = this.props.collapsedFolderIds.indexOf(folder.id) >= 0 ? 'fa-minus-square' : 'fa-plus-square';
|
||||
const expandIcon = <i style={expandIconStyle} className={"fa " + iconName}></i>
|
||||
const expandLink = hasChildren ? <a style={expandLinkStyle} href="#" folderid={folder.id} onClick={this.onFolderToggleClick_}>{expandIcon}</a> : <span style={expandLinkStyle}>{expandIcon}</span>
|
||||
|
||||
return (
|
||||
<div style={containerStyle} key={folder.id} onDragStart={this.onFolderDragStart_} onDragOver={this.onFolderDragOver_} onDrop={this.onFolderDrop_} draggable={true} folderid={folder.id}>
|
||||
<div className="list-item-container" style={containerStyle} key={folder.id} onDragStart={this.onFolderDragStart_} onDragOver={this.onFolderDragOver_} onDrop={this.onFolderDrop_} draggable={true} folderid={folder.id}>
|
||||
{ expandLink }
|
||||
<a
|
||||
className="list-item"
|
||||
@ -293,9 +305,11 @@ class SideBarComponent extends React.Component {
|
||||
data-type={BaseModel.TYPE_FOLDER}
|
||||
onContextMenu={event => this.itemContextMenu(event)}
|
||||
style={style}
|
||||
folderid={folder.id}
|
||||
onClick={() => {
|
||||
this.folderItem_click(folder);
|
||||
}}
|
||||
onDoubleClick={this.onFolderToggleClick_}
|
||||
>
|
||||
{itemTitle}
|
||||
</a>
|
||||
@ -451,6 +465,7 @@ const mapStateToProps = state => {
|
||||
notesParentType: state.notesParentType,
|
||||
locale: state.settings.locale,
|
||||
theme: state.settings.theme,
|
||||
collapsedFolderIds: state.collapsedFolderIds,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -34,17 +34,15 @@ table td, table th {
|
||||
background-color: rgba(0,160,255,0.1) !important;
|
||||
}
|
||||
|
||||
.side-bar .list-item:hover,
|
||||
/*.side-bar .list-item:hover,
|
||||
.side-bar .synchronize-button:hover {
|
||||
/*background-color: #453E53;*/
|
||||
background-color: #01427B;
|
||||
}
|
||||
|
||||
.side-bar .list-item:active,
|
||||
.side-bar .synchronize-button:active {
|
||||
/*background-color: #564B6C;*/
|
||||
background-color: #0465BB;
|
||||
}
|
||||
}*/
|
||||
|
||||
.editor-toolbar .button:not(.disabled):hover,
|
||||
.header .button:not(.disabled):hover {
|
||||
|
@ -19,6 +19,7 @@ const BaseSyncTarget = require('lib/BaseSyncTarget.js');
|
||||
const { fileExtension } = require('lib/path-utils.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const { _, setLocale, defaultLocale, closestSupportedLocale } = require('lib/locale.js');
|
||||
const reduxSharedMiddleware = require('lib/components/shared/reduxSharedMiddleware');
|
||||
const os = require('os');
|
||||
const fs = require('fs-extra');
|
||||
const JoplinError = require('lib/JoplinError');
|
||||
@ -270,6 +271,8 @@ class BaseApplication {
|
||||
const newState = store.getState();
|
||||
let refreshNotes = false;
|
||||
|
||||
reduxSharedMiddleware(store, next, action);
|
||||
|
||||
if (action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) {
|
||||
Setting.setValue('activeFolderId', newState.selectedFolderId);
|
||||
this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null;
|
||||
|
@ -0,0 +1,9 @@
|
||||
const reduxSharedMiddleware = function(store, next, action) {
|
||||
const newState = store.getState();
|
||||
|
||||
if (action.type == 'FOLDER_SET_COLLAPSED' || action.type == 'FOLDER_TOGGLE') {
|
||||
Setting.setValue('collapsedFolderIds', newState.collapsedFolderIds);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = reduxSharedMiddleware;
|
@ -1,5 +1,6 @@
|
||||
const ArrayUtils = require('lib/ArrayUtils');
|
||||
const Folder = require('lib/models/Folder');
|
||||
const BaseModel = require('lib/BaseModel');
|
||||
|
||||
let shared = {};
|
||||
|
||||
@ -11,11 +12,26 @@ function folderHasChildren_(folders, folderId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function folderIsVisible(folders, folderId, collapsedFolderIds) {
|
||||
if (!collapsedFolderIds || !collapsedFolderIds.length) return true;
|
||||
|
||||
while (true) {
|
||||
let folder = BaseModel.byId(folders, folderId);
|
||||
if (!folder) throw new Error('No folder with id ' + folder.id);
|
||||
if (!folder.parent_id) return true;
|
||||
if (collapsedFolderIds.indexOf(folder.parent_id) >= 0) return false;
|
||||
folderId = folder.parent_id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function renderFoldersRecursive_(props, renderItem, items, parentId, depth) {
|
||||
const folders = props.folders;
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
let folder = folders[i];
|
||||
if (!Folder.idsEqual(folder.parent_id, parentId)) continue;
|
||||
if (!folderIsVisible(props.folders, folder.id, props.collapsedFolderIds)) continue;
|
||||
const hasChildren = folderHasChildren_(folders, folder.id);
|
||||
items.push(renderItem(folder, props.selectedFolderId == folder.id && props.notesParentType == 'Folder', hasChildren, depth));
|
||||
if (hasChildren) items = renderFoldersRecursive_(props, renderItem, items, folder.id, depth + 1);
|
||||
|
@ -91,6 +91,8 @@ class Setting extends BaseModel {
|
||||
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
|
||||
return platform === 'linux' ? _('Note: Does not work in all desktop environments.') : null;
|
||||
}},
|
||||
|
||||
'collapsedFolderIds': { value: [], type: Setting.TYPE_ARRAY, public: false },
|
||||
|
||||
'encryption.enabled': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'encryption.activeMasterKeyId': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
|
@ -26,6 +26,7 @@ const defaultState = {
|
||||
appState: 'starting',
|
||||
hasDisabledSyncItems: false,
|
||||
newNote: null,
|
||||
collapsedFolderIds: [],
|
||||
};
|
||||
|
||||
const stateUtils = {};
|
||||
@ -51,6 +52,23 @@ function stateHasEncryptedItems(state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function folderSetCollapsed(state, action) {
|
||||
const collapsedFolderIds = state.collapsedFolderIds.slice();
|
||||
const idx = collapsedFolderIds.indexOf(action.id);
|
||||
|
||||
if (action.collapsed) {
|
||||
if (idx >= 0) return state;
|
||||
collapsedFolderIds.push(action.id);
|
||||
} else {
|
||||
if (idx < 0) return state;
|
||||
collapsedFolderIds.splice(idx, 1);
|
||||
}
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.collapsedFolderIds = collapsedFolderIds;
|
||||
return newState;
|
||||
}
|
||||
|
||||
// When deleting a note, tag or folder
|
||||
function handleItemDelete(state, action) {
|
||||
let newState = Object.assign({}, state);
|
||||
@ -339,6 +357,26 @@ const reducer = (state = defaultState, action) => {
|
||||
newState.folders = action.items;
|
||||
break;
|
||||
|
||||
case 'FOLDER_SET_COLLAPSED':
|
||||
|
||||
newState = folderSetCollapsed(state, action);
|
||||
break;
|
||||
|
||||
case 'FOLDER_TOGGLE':
|
||||
|
||||
if (state.collapsedFolderIds.indexOf(action.id) >= 0) {
|
||||
newState = folderSetCollapsed(state, Object.assign({ collapsed: false }, action));
|
||||
} else {
|
||||
newState = folderSetCollapsed(state, Object.assign({ collapsed: true }, action));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FOLDER_SET_COLLAPSED_ALL':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.collapsedFolderIds = action.ids.slice();
|
||||
break;
|
||||
|
||||
case 'TAG_UPDATE_ALL':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
|
Loading…
Reference in New Issue
Block a user