1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-11 18:24:43 +02:00

Desktop: Allow resizing left panels

This commit is contained in:
Laurent Cozic 2019-02-16 01:12:43 +00:00
parent 88e6315d09
commit 81e4cd319d
6 changed files with 136 additions and 12 deletions

View File

@ -17,6 +17,7 @@ const { _ } = require('lib/locale.js');
const layoutUtils = require('lib/layout-utils.js');
const { bridge } = require('electron').remote.require('./bridge');
const eventManager = require('../eventManager');
const VerticalResizer = require('./VerticalResizer.min');
class MainScreenComponent extends React.Component {
@ -24,6 +25,16 @@ class MainScreenComponent extends React.Component {
super();
this.notePropertiesDialog_close = this.notePropertiesDialog_close.bind(this);
this.sidebar_onDrag = this.sidebar_onDrag.bind(this);
this.noteList_onDrag = this.noteList_onDrag.bind(this);
}
sidebar_onDrag(event) {
Setting.setValue('style.sidebar.width', this.props.sidebarWidth + event.deltaX);
}
noteList_onDrag(event) {
Setting.setValue('style.noteList.width', Setting.value('style.noteList.width') + event.deltaX);
}
notePropertiesDialog_close() {
@ -265,8 +276,8 @@ class MainScreenComponent extends React.Component {
}
}
styles(themeId, width, height, messageBoxVisible, isSidebarVisible) {
const styleKey = themeId + '_' + width + '_' + height + '_' + messageBoxVisible + '_' + (+isSidebarVisible);
styles(themeId, width, height, messageBoxVisible, isSidebarVisible, sidebarWidth, noteListWidth) {
const styleKey = [themeId, width, height, messageBoxVisible, (+isSidebarVisible), sidebarWidth, noteListWidth].join('_');
if (styleKey === this.styleKey_) return this.styles_;
const theme = themeStyle(themeId);
@ -288,10 +299,16 @@ class MainScreenComponent extends React.Component {
backgroundColor: theme.warningBackgroundColor,
}
this.styles_.verticalResizer = {
width: 5,
height: height,
display: 'inline-block',
};
const rowHeight = height - theme.headerHeight - (messageBoxVisible ? this.styles_.messageBox.height : 0);
this.styles_.sideBar = {
width: Math.floor(layoutUtils.size(width * .2, 150, 300)),
width: sidebarWidth - this.styles_.verticalResizer.width,
height: rowHeight,
display: 'inline-block',
verticalAlign: 'top',
@ -303,14 +320,14 @@ class MainScreenComponent extends React.Component {
}
this.styles_.noteList = {
width: Math.floor(layoutUtils.size(width * .2, 150, 300)),
width: noteListWidth - this.styles_.verticalResizer.width,
height: rowHeight,
display: 'inline-block',
verticalAlign: 'top',
};
this.styles_.noteText = {
width: Math.floor(layoutUtils.size(width - this.styles_.sideBar.width - this.styles_.noteList.width, 0)),
width: Math.floor(width - this.styles_.sideBar.width - this.styles_.noteList.width - 10),
height: rowHeight,
display: 'inline-block',
verticalAlign: 'top',
@ -346,7 +363,7 @@ class MainScreenComponent extends React.Component {
const notes = this.props.notes;
const messageBoxVisible = this.props.hasDisabledSyncItems || this.props.showMissingMasterKeyMessage;
const sidebarVisibility = this.props.sidebarVisibility;
const styles = this.styles(this.props.theme, style.width, style.height, messageBoxVisible, sidebarVisibility);
const styles = this.styles(this.props.theme, style.width, style.height, messageBoxVisible, sidebarVisibility, this.props.sidebarWidth, this.props.noteListWidth);
const selectedFolderId = this.props.selectedFolderId;
const onConflictFolder = this.props.selectedFolderId === Folder.conflictFolderId();
@ -462,7 +479,9 @@ class MainScreenComponent extends React.Component {
<Header style={styles.header} showBackButton={false} items={headerItems} />
{messageComp}
<SideBar style={styles.sideBar} />
<VerticalResizer style={styles.verticalResizer} onDrag={this.sidebar_onDrag}/>
<NoteList style={styles.noteList} />
<VerticalResizer style={styles.verticalResizer} onDrag={this.noteList_onDrag}/>
<NoteText style={styles.noteText} visiblePanes={this.props.noteVisiblePanes} />
</div>
);
@ -482,6 +501,8 @@ const mapStateToProps = (state) => {
showMissingMasterKeyMessage: state.notLoadedMasterKeys.length && state.masterKeys.length,
selectedFolderId: state.selectedFolderId,
sidebarVisibility: state.sidebarVisibility,
sidebarWidth: state.settings['style.sidebar.width'],
noteListWidth: state.settings['style.noteList.width'],
};
};

View File

@ -17,7 +17,7 @@ class NavigatorComponent extends Component {
}
updateWindowTitle(title) {
bridge().window().setTitle(title);
if (bridge().window()) bridge().window().setTitle(title);
}
render() {

View File

@ -18,6 +18,7 @@ const Mark = require('mark.js/dist/mark.min.js');
const SearchEngine = require('lib/services/SearchEngine');
const NoteListUtils = require('./utils/NoteListUtils');
const { replaceRegexDiacritics, pregQuote } = require('lib/string-utils');
const VerticalResizer = require("./VerticalResizer.min");
class NoteListComponent extends React.Component {
@ -29,6 +30,7 @@ class NoteListComponent extends React.Component {
this.itemRenderer = this.itemRenderer.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.verticalResizer_onDrag = this.verticalResizer_onDrag.bind(this);
}
style() {
@ -72,6 +74,10 @@ class NoteListComponent extends React.Component {
return style;
}
verticalResizer_onDrag(event) {
Setting.setValue('style.noteList.width', Setting.value('style.noteList.width') + event.deltaX);
}
itemContextMenu(event) {
const currentItemId = event.currentTarget.getAttribute('data-id');
if (!currentItemId) return;
@ -381,7 +387,7 @@ class NoteListComponent extends React.Component {
const theme = themeStyle(this.props.theme);
const style = this.props.style;
let notes = this.props.notes.slice();
if (!notes.length) {
const padding = 10;
const emptyDivStyle = Object.assign({
@ -396,16 +402,16 @@ class NoteListComponent extends React.Component {
return <div style={emptyDivStyle}>{ this.props.folders.length ? _('No notes in here. Create one by clicking on "New note".') : _('There is currently no notebook. Create one by clicking on "New notebook".')}</div>
}
return (
return (
<ItemList
ref={this.itemListRef}
itemHeight={this.style().listItem.height}
style={style}
className={"note-list"}
items={notes}
style={style}
itemRenderer={this.itemRenderer}
onKeyDown={this.onKeyDown}
></ItemList>
/>
);
}

View File

@ -728,7 +728,8 @@ class SideBarComponent extends React.Component {
return (
<div ref={this.rootRef} onKeyDown={this.onKeyDown} className="side-bar" style={style}>
<div style={{flex:1, overflowY: 'auto'}}>
<div style={{flex:1, overflowX: 'hidden', overflowY: 'auto'}}>
{items}
</div>
<div style={{flex:0}}>

View File

@ -0,0 +1,91 @@
const React = require("react");
class VerticalResizer extends React.PureComponent {
constructor() {
super();
this.state = {
parentRight: 0,
parentHeight: 0,
parentWidth: 0,
drag: {
startX: 0,
lastX: 0,
},
};
this.onDragStart = this.onDragStart.bind(this);
this.onDrag = this.onDrag.bind(this);
this.onDragEnd = this.onDragEnd.bind(this);
this.document_onDragOver = this.document_onDragOver.bind(this);
}
document_onDragOver(event) {
event.dataTransfer.dropEffect = 'none';
}
onDragStart(event) {
document.addEventListener('dragover', this.document_onDragOver)
event.dataTransfer.dropEffect= 'none';
this.setState({
drag: {
startX: event.nativeEvent.screenX,
lastX: event.nativeEvent.screenX,
}
});
if (this.props.onDragStart) this.props.onDragStart({});
}
onDrag(event) {
if (!event.nativeEvent.buttons) return;
const newX = event.nativeEvent.screenX;
const delta = newX - this.state.drag.lastX;
if (!delta) return;
this.setState({
drag: Object.assign({}, this.state.drag, { lastX: newX }),
}, () => {
this.props.onDrag({ deltaX: delta });
});
}
onDragEnd(event) {
document.removeEventListener('dragover', this.document_onDragOver);
}
componentWillUnmount() {
document.removeEventListener('dragover', this.document_onDragOver);
}
render() {
const debug = false;
const rootStyle = Object.assign({}, {
height: '100%',
width:5,
borderColor:'red',
borderWidth: debug ? 1 : 0,
borderStyle:'solid',
cursor: 'col-resize',
boxSizing: 'border-box',
opacity: 0,
}, this.props.style);
return (
<div
style={rootStyle}
draggable={true}
onDragStart={this.onDragStart}
onDrag={this.onDrag}
onDragEnd={this.onDragEnd}
/>
);
}
}
module.exports = VerticalResizer;

View File

@ -104,6 +104,8 @@ class Setting extends BaseModel {
'style.zoom': {value: 100, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Global zoom percentage'), minimum: 50, maximum: 500, step: 10},
'style.editor.fontSize': {value: 13, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1},
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font family'), description: () => _('This must be *monospace* font or it will not work properly. If the font is incorrect or empty, it will default to a generic monospace font.')},
'style.sidebar.width': {value: 150, minimum: 100, maximum: 200, type: Setting.TYPE_INT, public: false, appTypes: ['desktop'] },
'style.noteList.width': {value: 150, minimum: 100, maximum: 200, type: Setting.TYPE_INT, public: false, appTypes: ['desktop'] },
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
'autoUpdate.includePreReleases': { value: false, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Get pre-releases when checking for updates'), description: () => _('See the pre-release page for more details: %s', 'https://joplin.cozic.net/prereleases') },
'clipperServer.autoStart': { value: false, type: Setting.TYPE_BOOL, public: false },
@ -280,6 +282,9 @@ class Setting extends BaseModel {
// Don't log this to prevent sensitive info (passwords, auth tokens...) to end up in logs
// this.logger().info('Setting: ' + key + ' = ' + c.value + ' => ' + value);
if (('minimum' in md) && value < md.minimum) value = md.minimum;
if (('maximum' in md) && value > md.maximum) value = md.maximum;
c.value = value;
this.dispatch({