Add option for vertically stacked reading pane (#2243)

* Add option for vertically stacked reading pane

* Switch from creating a separate column to scoping ThreadList to split+list modes

* Better styling for vertical reading pane

* Fix bug that prevented changing the panel layout via the preferences dialog

* Add resize functionality for vertical thread list

* Add Contact Toolbar button to Thread List Vertical View

* Remove debug log

Co-authored-by: Ben Gotow <ben@foundry376.com>
This commit is contained in:
Janosch Maier 2021-03-26 16:15:33 +01:00 committed by GitHub
parent d0583899ee
commit c7f7dc027c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 161 additions and 43 deletions

View file

@ -26,7 +26,7 @@ export function activate() {
ComponentRegistry.register(ToggleWithTutorialTip, {
location: WorkspaceStore.Sheet.Threads.Toolbar.Right,
modes: ['split'],
modes: ['split', 'splitVertical'],
});
}

View file

@ -62,8 +62,9 @@ export function activate() {
'Preferences',
{},
{
split: ['Preferences'],
list: ['Preferences'],
split: ['Preferences'],
splitVertical: ['Preferences'],
}
);

View file

@ -135,11 +135,13 @@ class AppearanceModeSwitch extends React.Component<
}
_onApplyChanges = () => {
AppEnv.commands.dispatch(`navigation:select-${this.state.value}-mode`);
// The command to be called contains an `off` as this denotes the current
// state that is used to show the menu item in an (in)active state.
AppEnv.commands.dispatch(`navigation:${this.state.value}-mode-off`);
};
_renderModeOptions() {
return ['list', 'split'].map(mode => (
return ['list', 'split', 'splitVertical'].map(mode => (
<AppearanceModeOption
mode={mode}
key={mode}
@ -174,6 +176,7 @@ const AppearanceModeOption = function AppearanceModeOption(props) {
const label = {
list: localized('Single Panel'),
split: localized('Two Panel'),
splitVertical: localized('Two Panel Vertical'),
}[props.mode];
return (

View file

@ -136,7 +136,7 @@
}
.container-appearance {
width: 400px;
width: 600px;
margin: 0 auto;
input[type='radio'] {
@ -156,7 +156,7 @@
}
.appearance-mode-switch {
max-width: 400px;
max-width: 600px;
text-align: right;
.appearance-mode {

View file

@ -2,6 +2,7 @@ import { ComponentRegistry, WorkspaceStore } from 'mailspring-exports';
import ThreadList from './thread-list';
import ThreadListToolbar from './thread-list-toolbar';
import ThreadListVertical from './thread-list-vertical';
import ThreadListEmptyFolderBar from './thread-list-empty-folder-bar';
import MessageListToolbar from './message-list-toolbar';
import SelectedItemsStack from './selected-items-stack';
@ -15,6 +16,12 @@ export function activate() {
ComponentRegistry.register(ThreadList, {
location: WorkspaceStore.Location.ThreadList,
modes: ['split', 'list'],
});
ComponentRegistry.register(ThreadListVertical, {
location: WorkspaceStore.Location.ThreadList,
modes: ['splitVertical'],
});
ComponentRegistry.register(SelectedItemsStack, {

View file

@ -0,0 +1,47 @@
import React from 'react';
import { InjectedComponentSet } from 'mailspring-component-kit';
import { WorkspaceStore } from 'mailspring-exports';
import { ResizableRegion, ResizableHandle } from '../../../src/components/resizable-region';
class ThreadListVertical extends React.Component<{}, { style: string; syncing: boolean }> {
static displayName = 'ThreadListVertical';
static containerRequired = false;
render() {
const minHeight = 100;
const initialHeight = AppEnv.getThreadListVerticalHeight() || 400;
return (
<>
<ResizableRegion
minHeight={minHeight}
initialHeight={initialHeight}
handle={ResizableHandle.Bottom}
onResize={h => this._onResize(h)}
>
<InjectedComponentSet
matching={{ location: WorkspaceStore.Location.ThreadList, modes: ['split'] }}
/>
</ResizableRegion>
<ResizableRegion>
<div style={{ height: '100%', width: '100%', borderTop: '0.5px solid #dddddd' }}>
<div className="sheet-toolbar" style={{ borderBottom: '0' }}>
<InjectedComponentSet
matching={{ location: WorkspaceStore.Location.MessageList.Toolbar, modes: ['split'] }}
/>
</div>
<InjectedComponentSet
matching={{ location: WorkspaceStore.Location.MessageList, modes: ['split'] }}
/>
</div>
</ResizableRegion>
</>
);
}
_onResize = (height) => {
AppEnv.storeThreadListVerticalHeight(height);
};
}
export default ThreadListVertical;

View file

@ -508,6 +508,8 @@
"Reading": "Lesen",
"Reading Pane Off": "Lesefenster aus",
"Reading Pane On": "Lesefenster ein",
"Horizontal Reading Pane": "Horizontales Lesefenster",
"Vertical Reading Pane": "Vertikales Lesefenster",
"Rebuild": "Wiederherstellen",
"Rebuild Cache...": "Cache neu erstellen...",
"Recipient": "Empfänger:",
@ -776,6 +778,7 @@
"Twitter Handle": "Twitter Handle",
"Twitter Profile Image": "Twitter Profilbild",
"Two Panel": "Zwei Panel",
"Two Panel Vertical": "Zwei vertikale Panel",
"Uhoh - that's a pro feature!": "Uhoh - das ist ein Pro-Feature!",
"Unable to Add Account": "Account kann nicht hinzugefügt werden",
"Unable to Start Local Server": "Der lokale Server konnte nicht gestartet werden",

View file

@ -97,28 +97,42 @@ module.exports = {
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-split-mode',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
type: 'radio',
command: 'navigation:select-split-mode',
command: 'navigation:list-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:list-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:split-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:split-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-on',
checked: true,
hideWhenDisabled: true,
},

View file

@ -69,28 +69,42 @@ module.exports = {
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-split-mode',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
type: 'radio',
command: 'navigation:select-split-mode',
command: 'navigation:list-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:list-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:split-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:split-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-on',
checked: true,
hideWhenDisabled: true,
},

View file

@ -44,28 +44,42 @@ module.exports = {
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-split-mode',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
type: 'radio',
command: 'navigation:select-split-mode',
command: 'navigation:list-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane Off'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:list-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:split-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Reading Pane On'),
label: localized('Horizontal Reading Pane'),
type: 'radio',
command: 'navigation:select-list-mode',
command: 'navigation:split-mode-on',
checked: true,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-off',
checked: false,
hideWhenDisabled: true,
},
{
label: localized('Vertical Reading Pane'),
type: 'radio',
command: 'navigation:splitVertical-mode-on',
checked: true,
hideWhenDisabled: true,
},

View file

@ -593,6 +593,14 @@ export default class AppEnvConstructor {
return this.savedState.columnWidths[id];
}
storeThreadListVerticalHeight(height) {
this.savedState.threadListVerticalHeight = height;
}
getThreadListVerticalHeight() {
return this.savedState.threadListVerticalHeight;
}
async startWindow() {
const { windowType } = this.getLoadSettings();

View file

@ -3,7 +3,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { PropTypes, Utils } from 'mailspring-exports';
const ResizableHandle: { [side: string]: IResizeHandle } = {
export const ResizableHandle: { [side: string]: IResizeHandle } = {
Top: {
axis: 'vertical',
className: 'flexbox-handle-vertical flexbox-handle-top',

View file

@ -30,7 +30,7 @@ export default {
mode: {
type: 'string',
default: 'list',
enum: ['split', 'list'],
enum: ['split', 'list', 'splitVertical'],
},
systemTray: {
type: 'boolean',

View file

@ -119,6 +119,7 @@ class WorkspaceStore extends MailspringStore {
{
list: ['RootSidebar', 'ThreadList'],
split: ['RootSidebar', 'ThreadList', 'MessageList', 'MessageListSidebar'],
splitVertical: ['RootSidebar', 'ThreadList', 'MessageListSidebar'],
}
);
this.defineSheet('Thread', {}, { list: ['MessageList', 'MessageListSidebar'] });
@ -222,8 +223,14 @@ class WorkspaceStore extends MailspringStore {
'core:pop-sheet': () => this.popSheet(),
},
this._preferredLayoutMode === 'list'
? { 'navigation:select-split-mode': () => this._onSelectLayoutMode('split') }
: { 'navigation:select-list-mode': () => this._onSelectLayoutMode('list') }
? { 'navigation:list-mode-on': () => this._onSelectLayoutMode('list') }
: { 'navigation:list-mode-off': () => this._onSelectLayoutMode('list') },
this._preferredLayoutMode === 'split'
? { 'navigation:split-mode-on': () => this._onSelectLayoutMode('split') }
: { 'navigation:split-mode-off': () => this._onSelectLayoutMode('split') },
this._preferredLayoutMode === 'splitVertical'
? { 'navigation:splitVertical-mode-on': () => this._onSelectLayoutMode('splitVertical') }
: { 'navigation:splitVertical-mode-off': () => this._onSelectLayoutMode('splitVertical') }
)
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB