Add 'n' shortcut for new doc
Fixed cmd+enter shortcut to publish doc Fixed keyboard shortcut display on non-mac Fixed heading alignment Fixed documents smaller than page should not scroll
This commit is contained in:
@ -2,9 +2,8 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const ClickablePadding = styled.div`
|
||||
min-height: 50vh;
|
||||
cursor: ${({ onClick }) => (onClick ? 'text' : 'default')};
|
||||
${({ grow }) => grow && `flex-grow: 1;`};
|
||||
${({ grow }) => grow && `flex-grow: 100;`};
|
||||
`;
|
||||
|
||||
export default ClickablePadding;
|
||||
|
@ -1,8 +1,11 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import keydown from 'react-keydown';
|
||||
import Flex from 'shared/components/Flex';
|
||||
import { PlusIcon } from 'outline-icons';
|
||||
import { newDocumentUrl } from 'utils/routeHelpers';
|
||||
|
||||
import Header from './Header';
|
||||
import SidebarLink from './SidebarLink';
|
||||
@ -14,6 +17,7 @@ import UiStore from 'stores/UiStore';
|
||||
import DocumentsStore from 'stores/DocumentsStore';
|
||||
|
||||
type Props = {
|
||||
history: Object,
|
||||
collections: CollectionsStore,
|
||||
documents: DocumentsStore,
|
||||
onCreateCollection: () => void,
|
||||
@ -28,8 +32,17 @@ class Collections extends React.Component<Props> {
|
||||
this.props.collections.fetchPage({ limit: 100 });
|
||||
}
|
||||
|
||||
@keydown('n')
|
||||
goToNewDocument() {
|
||||
const activeCollection = this.props.collections.active;
|
||||
if (!activeCollection) return;
|
||||
|
||||
this.props.history.push(newDocumentUrl(activeCollection));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { collections, ui, documents } = this.props;
|
||||
|
||||
const content = (
|
||||
<Flex column>
|
||||
<Header>Collections</Header>
|
||||
@ -57,4 +70,6 @@ class Collections extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default inject('collections', 'ui', 'documents')(Collections);
|
||||
export default inject('collections', 'ui', 'documents')(
|
||||
withRouter(Collections)
|
||||
);
|
||||
|
@ -86,7 +86,7 @@ export default class Document extends BaseModel {
|
||||
@computed
|
||||
get isEmpty(): boolean {
|
||||
// Check if the document title has been modified and user generated content exists
|
||||
return this.text.replace(new RegExp(`^#$`), '').trim().length === 0;
|
||||
return this.text.replace(/^#/, '').trim().length === 0;
|
||||
}
|
||||
|
||||
@computed
|
||||
|
@ -194,6 +194,10 @@ class DocumentScene extends React.Component<Props> {
|
||||
handleCloseMoveModal = () => (this.moveModalOpen = false);
|
||||
handleOpenMoveModal = () => (this.moveModalOpen = true);
|
||||
|
||||
onSaveAndExit = () => {
|
||||
this.onSave({ done: true, publish: true });
|
||||
};
|
||||
|
||||
onSave = async (
|
||||
options: { done?: boolean, publish?: boolean, autosave?: boolean } = {}
|
||||
) => {
|
||||
@ -367,7 +371,7 @@ class DocumentScene extends React.Component<Props> {
|
||||
onImageUploadStop={this.onImageUploadStop}
|
||||
onSearchLink={this.onSearchLink}
|
||||
onChange={this.onChange}
|
||||
onSave={this.onSave}
|
||||
onSave={this.onSaveAndExit}
|
||||
onCancel={this.onDiscard}
|
||||
readOnly={!this.isEditing}
|
||||
toc={!revision}
|
||||
@ -387,7 +391,6 @@ const MaxWidth = styled(Flex)`
|
||||
padding: 0 16px;
|
||||
max-width: 100vw;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
${breakpoint('tablet')`
|
||||
padding: 0 24px;
|
||||
|
@ -48,6 +48,8 @@ class DocumentEditor extends React.Component<Props> {
|
||||
}
|
||||
|
||||
const StyledEditor = styled(Editor)`
|
||||
justify-content: start;
|
||||
|
||||
p {
|
||||
${Placeholder} {
|
||||
visibility: hidden;
|
||||
|
@ -10,6 +10,7 @@ import { NewDocumentIcon } from 'outline-icons';
|
||||
import Document from 'models/Document';
|
||||
import AuthStore from 'stores/AuthStore';
|
||||
import { documentEditUrl } from 'utils/routeHelpers';
|
||||
import { meta } from 'utils/keyboard';
|
||||
|
||||
import Flex from 'shared/components/Flex';
|
||||
import Breadcrumb from './Breadcrumb';
|
||||
@ -107,6 +108,7 @@ class Header extends React.Component<Props> {
|
||||
justify="space-between"
|
||||
readOnly={!isEditing}
|
||||
isCompact={this.isScrolled}
|
||||
shrink={false}
|
||||
>
|
||||
<Modal
|
||||
isOpen={this.showShareModal}
|
||||
@ -149,7 +151,7 @@ class Header extends React.Component<Props> {
|
||||
<Action>
|
||||
<Button
|
||||
onClick={this.handleSave}
|
||||
title="Save changes (Cmd+Enter)"
|
||||
title={`Save changes ${isDraft ? '' : `${meta}+Enter`}`}
|
||||
disabled={savingIsDisabled}
|
||||
isSaving={isSaving}
|
||||
neutral={isDraft}
|
||||
@ -164,7 +166,7 @@ class Header extends React.Component<Props> {
|
||||
<Action>
|
||||
<Button
|
||||
onClick={this.handlePublish}
|
||||
title="Publish document (Cmd+Enter)"
|
||||
title={`Publish document (${meta}+Enter)`}
|
||||
disabled={savingIsDisabled}
|
||||
small
|
||||
>
|
||||
|
@ -4,6 +4,7 @@ import styled from 'styled-components';
|
||||
import Key from 'components/Key';
|
||||
import Flex from 'shared/components/Flex';
|
||||
import HelpText from 'components/HelpText';
|
||||
import { meta } from 'utils/keyboard';
|
||||
|
||||
function KeyboardShortcuts() {
|
||||
return (
|
||||
@ -17,6 +18,11 @@ function KeyboardShortcuts() {
|
||||
|
||||
<h2>Navigation</h2>
|
||||
<List>
|
||||
<Keys>
|
||||
<Key>n</Key>
|
||||
</Keys>
|
||||
<Label>New document in current collection</Label>
|
||||
|
||||
<Keys>
|
||||
<Key>e</Key>
|
||||
</Keys>
|
||||
@ -46,44 +52,44 @@ function KeyboardShortcuts() {
|
||||
<h2>Editor</h2>
|
||||
<List>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>Enter</Key>
|
||||
<Key>{meta}</Key> + <Key>Enter</Key>
|
||||
</Keys>
|
||||
<Label>Save and exit document edit mode</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>S</Key>
|
||||
<Key>{meta}</Key> + <Key>S</Key>
|
||||
</Keys>
|
||||
<Label>Save document and continue editing</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>Esc</Key>
|
||||
<Key>{meta}</Key> + <Key>Esc</Key>
|
||||
</Keys>
|
||||
<Label>Cancel editing</Label>
|
||||
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>b</Key>
|
||||
<Key>{meta}</Key> + <Key>b</Key>
|
||||
</Keys>
|
||||
<Label>Bold</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>i</Key>
|
||||
<Key>{meta}</Key> + <Key>i</Key>
|
||||
</Keys>
|
||||
<Label>Italic</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>u</Key>
|
||||
<Key>{meta}</Key> + <Key>u</Key>
|
||||
</Keys>
|
||||
<Label>Underline</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>d</Key>
|
||||
<Key>{meta}</Key> + <Key>d</Key>
|
||||
</Keys>
|
||||
<Label>Strikethrough</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>k</Key>
|
||||
<Key>{meta}</Key> + <Key>k</Key>
|
||||
</Keys>
|
||||
<Label>Link</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>z</Key>
|
||||
<Key>{meta}</Key> + <Key>z</Key>
|
||||
</Keys>
|
||||
<Label>Undo</Label>
|
||||
<Keys>
|
||||
<Key>⌘</Key> + <Key>Shift</Key> + <Key>z</Key>
|
||||
<Key>{meta}</Key> + <Key>Shift</Key> + <Key>z</Key>
|
||||
</Keys>
|
||||
<Label>Redo</Label>
|
||||
</List>
|
||||
|
@ -13,6 +13,7 @@ import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
|
||||
import { DEFAULT_PAGINATION_LIMIT } from 'stores/BaseStore';
|
||||
import DocumentsStore from 'stores/DocumentsStore';
|
||||
import { searchUrl } from 'utils/routeHelpers';
|
||||
import { meta } from 'utils/keyboard';
|
||||
|
||||
import Flex from 'shared/components/Flex';
|
||||
import Empty from 'components/Empty';
|
||||
@ -193,8 +194,8 @@ class Search extends React.Component<Props> {
|
||||
{showShortcutTip && (
|
||||
<Fade>
|
||||
<HelpText small>
|
||||
Use the <strong>CMD+K</strong> shortcut to search from anywhere
|
||||
in Outline
|
||||
Use the <strong>{meta}+K</strong> shortcut to search from
|
||||
anywhere in Outline
|
||||
</HelpText>
|
||||
</Fade>
|
||||
)}
|
||||
|
3
app/utils/keyboard.js
Normal file
3
app/utils/keyboard.js
Normal file
@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
|
||||
export const meta = window.navigator.platform === 'MacIntel' ? '⌘' : 'Ctrl';
|
@ -18,6 +18,7 @@ type AlignValues =
|
||||
|
||||
type Props = {
|
||||
column?: ?boolean,
|
||||
shrink?: ?boolean,
|
||||
align?: AlignValues,
|
||||
justify?: JustifyValues,
|
||||
auto?: ?boolean,
|
||||
@ -36,6 +37,7 @@ const Container = styled.div`
|
||||
flex-direction: ${({ column }) => (column ? 'column' : 'row')};
|
||||
align-items: ${({ align }) => align};
|
||||
justify-content: ${({ justify }) => justify};
|
||||
flex-shrink: ${({ shrink }) => (shrink ? 1 : 0)};
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
`;
|
||||
|
Reference in New Issue
Block a user