From e34485eb83123ed96857c661a7510b12ed84dea9 Mon Sep 17 00:00:00 2001 From: Itai Braude Date: Thu, 17 Oct 2019 20:48:40 +0300 Subject: [PATCH] added rtl toggle button --- browser/components/CodeEditor.js | 16 +++- browser/components/MarkdownEditor.js | 4 +- browser/components/MarkdownPreview.js | 28 ++++-- browser/components/MarkdownSplitEditor.js | 4 +- browser/main/Detail/MarkdownNoteDetail.js | 16 +++- browser/main/Detail/MarkdownNoteDetail.styl | 2 +- browser/main/Detail/ToggleDirectionButton.js | 26 ++++++ .../main/Detail/ToggleDirectionButton.styl | 85 +++++++++++++++++++ browser/main/global.styl | 2 +- package.json | 2 +- resources/icon/icon-left-to-right.svg | 1 + resources/icon/icon-right-to-left.svg | 1 + 12 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 browser/main/Detail/ToggleDirectionButton.js create mode 100644 browser/main/Detail/ToggleDirectionButton.styl create mode 100644 resources/icon/icon-left-to-right.svg create mode 100644 resources/icon/icon-right-to-left.svg diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 9214363e..64f8eb59 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -273,7 +273,7 @@ export default class CodeEditor extends React.Component { } componentDidMount () { - const { rulers, enableRulers, enableMarkdownLint } = this.props + const { rulers, enableRulers, enableMarkdownLint, RTL } = this.props eventEmitter.on('line:jump', this.scrollToLineHandeler) snippetManager.init() @@ -294,6 +294,8 @@ export default class CodeEditor extends React.Component { scrollPastEnd: this.props.scrollPastEnd, inputStyle: 'textarea', dragDrop: false, + direction: RTL ? 'rtl' : 'ltr', + rtlMoveVisually: RTL ? 'true' : 'false', foldGutter: true, lint: enableMarkdownLint ? this.getCodeEditorLintConfig() : false, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], @@ -537,7 +539,7 @@ export default class CodeEditor extends React.Component { rulers, enableRulers, enableMarkdownLint, - customMarkdownLintConfig + customMarkdownLintConfig, } = this.props if (prevProps.mode !== this.props.mode) { this.setMode(this.props.mode) @@ -555,6 +557,10 @@ export default class CodeEditor extends React.Component { if (prevProps.keyMap !== this.props.keyMap) { needRefresh = true } + if (prevProps.RTL !== this.props.RTL) { + this.editor.setOption('direction', this.props.RTL ? 'rtl' : 'ltr' ) + this.editor.setOption('rtlMoveVisually', this.props.RTL ? 'true' : 'false' ) + } if (prevProps.enableMarkdownLint !== enableMarkdownLint || prevProps.customMarkdownLintConfig !== customMarkdownLintConfig) { if (!enableMarkdownLint) { this.editor.setOption('lint', {default: false}) @@ -1219,7 +1225,8 @@ CodeEditor.propTypes = { spellCheck: PropTypes.bool, enableMarkdownLint: PropTypes.bool, customMarkdownLintConfig: PropTypes.string, - deleteUnusedAttachments: PropTypes.bool + deleteUnusedAttachments: PropTypes.bool, + RTL: PropTypes.bool } CodeEditor.defaultProps = { @@ -1235,5 +1242,6 @@ CodeEditor.defaultProps = { enableMarkdownLint: DEFAULT_CONFIG.editor.enableMarkdownLint, customMarkdownLintConfig: DEFAULT_CONFIG.editor.customMarkdownLintConfig, prettierConfig: DEFAULT_CONFIG.editor.prettierConfig, - deleteUnusedAttachments: DEFAULT_CONFIG.editor.deleteUnusedAttachments + deleteUnusedAttachments: DEFAULT_CONFIG.editor.deleteUnusedAttachments, + RTL: false } diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index cd885fd9..4a073237 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -267,7 +267,7 @@ class MarkdownEditor extends React.Component { } render () { - const {className, value, config, storageKey, noteKey, linesHighlighted} = this.props + const {className, value, config, storageKey, noteKey, linesHighlighted, RTL} = this.props let editorFontSize = parseInt(config.editor.fontSize, 10) if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14 @@ -325,6 +325,7 @@ class MarkdownEditor extends React.Component { customMarkdownLintConfig={config.editor.customMarkdownLintConfig} prettierConfig={config.editor.prettierConfig} deleteUnusedAttachments={config.editor.deleteUnusedAttachments} + RTL={RTL} /> this.handleDropImage(e)} + RTL={RTL} /> ) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index c1dc287e..52eb0127 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -65,7 +65,8 @@ function buildStyle (opts) { optimizeOverflowScroll, theme, allowCustomCSS, - customCSS + customCSS, + RTL } = opts return ` @font-face { @@ -104,6 +105,10 @@ body { font-size: ${fontSize}px; ${scrollPastEnd ? 'padding-bottom: 90vh;' : ''} ${optimizeOverflowScroll ? 'height: 100%;' : ''} + ${RTL ? 'direction: rtl;' : ''} + ${RTL ? 'text-align: right;' : ''} + + } @media print { body { @@ -326,7 +331,8 @@ export default class MarkdownPreview extends React.Component { scrollPastEnd, theme, allowCustomCSS, - customCSS + customCSS, + RTL } = this.getStyleParams() const inlineStyles = buildStyle({ @@ -337,7 +343,8 @@ export default class MarkdownPreview extends React.Component { scrollPastEnd, theme, allowCustomCSS, - customCSS + customCSS, + RTL }) let body = this.markdown.render(noteContent) body = attachmentManagement.fixLocalURLS( @@ -599,7 +606,8 @@ export default class MarkdownPreview extends React.Component { prevProps.theme !== this.props.theme || prevProps.scrollPastEnd !== this.props.scrollPastEnd || prevProps.allowCustomCSS !== this.props.allowCustomCSS || - prevProps.customCSS !== this.props.customCSS + prevProps.customCSS !== this.props.customCSS || + prevProps.RTL !== this.props.RTL ) { this.applyStyle() needsRewriteIframe = true @@ -623,7 +631,8 @@ export default class MarkdownPreview extends React.Component { scrollPastEnd, theme, allowCustomCSS, - customCSS + customCSS, + RTL } = this.props let { fontFamily, codeBlockFontFamily } = this.props fontFamily = _.isString(fontFamily) && fontFamily.trim().length > 0 @@ -649,7 +658,8 @@ export default class MarkdownPreview extends React.Component { scrollPastEnd, theme, allowCustomCSS, - customCSS + customCSS, + RTL } } @@ -663,7 +673,8 @@ export default class MarkdownPreview extends React.Component { scrollPastEnd, theme, allowCustomCSS, - customCSS + customCSS, + RTL } = this.getStyleParams() this.getWindow().document.getElementById( @@ -678,7 +689,8 @@ export default class MarkdownPreview extends React.Component { optimizeOverflowScroll: true, theme, allowCustomCSS, - customCSS + customCSS, + RTL }) this.getWindow().document.documentElement.style.overflowY = 'hidden' } diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index f5996c59..8ae9b751 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -137,7 +137,7 @@ class MarkdownSplitEditor extends React.Component { } render () { - const {config, value, storageKey, noteKey, linesHighlighted} = this.props + const {config, value, storageKey, noteKey, linesHighlighted, RTL} = this.props const storage = findStorage(storageKey) let editorFontSize = parseInt(config.editor.fontSize, 10) if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14 @@ -183,6 +183,7 @@ class MarkdownSplitEditor extends React.Component { enableMarkdownLint={config.editor.enableMarkdownLint} customMarkdownLintConfig={config.editor.customMarkdownLintConfig} deleteUnusedAttachments={config.editor.deleteUnusedAttachments} + RTL={RTL} />
this.handleMouseDown(e)} >
@@ -213,6 +214,7 @@ class MarkdownSplitEditor extends React.Component { customCSS={config.preview.customCSS} allowCustomCSS={config.preview.allowCustomCSS} lineThroughCheckbox={config.preview.lineThroughCheckbox} + RTL={RTL} />
) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 207e1e2b..419347dc 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -31,6 +31,7 @@ import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote' import markdownToc from 'browser/lib/markdown-toc-generator' import queryString from 'query-string' import { replace } from 'connected-react-router' +import ToggleDirectionButton from "browser/main/Detail/ToggleDirectionButton"; class MarkdownNoteDetail extends React.Component { constructor (props) { @@ -46,7 +47,8 @@ class MarkdownNoteDetail extends React.Component { isLockButtonShown: props.config.editor.type !== 'SPLIT', isLocked: false, editorType: props.config.editor.type, - switchPreview: props.config.editor.switchPreview + switchPreview: props.config.editor.switchPreview, + RTL: false } this.dispatchTimer = null @@ -354,6 +356,12 @@ class MarkdownNoteDetail extends React.Component { }) } + handleSwitchDirection () { + // If in split mode, hide the lock button + let direction = this.state.RTL + this.setState({ RTL: !direction }) + } + handleDeleteNote () { this.handleTrashButtonClick() } @@ -393,6 +401,7 @@ class MarkdownNoteDetail extends React.Component { onChange={this.handleUpdateContent.bind(this)} isLocked={this.state.isLocked} ignorePreviewPointerEvents={ignorePreviewPointerEvents} + RTL={this.state.RTL} /> } else { return } } @@ -472,7 +482,7 @@ class MarkdownNoteDetail extends React.Component {
this.handleSwitchMode(e)} editorType={editorType} /> - + this.handleSwitchDirection(e)} editorDirection={this.state.RTL} /> this.handleStarButtonClick(e)} isActive={note.isStarred} @@ -518,6 +528,8 @@ class MarkdownNoteDetail extends React.Component { print={this.print} />
+ + return ( diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index a24e9881..a7adbea1 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -15,7 +15,7 @@ .control-lockButton topBarButtonRight() position absolute - right 225px + right 265px &:hover .tooltip opacity 1 diff --git a/browser/main/Detail/ToggleDirectionButton.js b/browser/main/Detail/ToggleDirectionButton.js new file mode 100644 index 00000000..d0cf57bb --- /dev/null +++ b/browser/main/Detail/ToggleDirectionButton.js @@ -0,0 +1,26 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './ToggleDirectionButton.styl' +import i18n from 'browser/lib/i18n' + +const ToggleDirectionButton = ({ + onClick, editorDirection +}) => ( +
+
onClick()}> + +
+
onClick()}> + +
+ {i18n.__('Toggle Direction')} +
+) + +ToggleDirectionButton.propTypes = { + onClick: PropTypes.func.isRequired, + editorDirection: PropTypes.string.isRequired +} + +export default CSSModules(ToggleDirectionButton, styles) diff --git a/browser/main/Detail/ToggleDirectionButton.styl b/browser/main/Detail/ToggleDirectionButton.styl new file mode 100644 index 00000000..5146ad23 --- /dev/null +++ b/browser/main/Detail/ToggleDirectionButton.styl @@ -0,0 +1,85 @@ +.control-toggleModeButton + height 25px + border-radius 50px + background-color #F4F4F4 + width 52px + display flex + align-items center + position: relative + top 2px + margin-left 5px + .active + background-color #1EC38B + width 33px + height 24px + box-shadow 2px 0px 7px #eee + z-index 1 + + div + width 40px + height 100% + border-radius 50% + display flex + align-items center + justify-content center + cursor pointer + + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 33px + left -10px + z-index 200 + width 80px + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +.tooltip:lang(ja) + @extend .tooltip + left -8px + width 70px + +body[data-theme="dark"] + .control-fullScreenButton + topBarButtonDark() + + .control-toggleModeButton + background-color #3A404C + .active + background-color #1EC38B + box-shadow 2px 0px 7px #444444 + +body[data-theme="solarized-dark"] + .control-toggleModeButton + background-color #002B36 + .active + background-color #1EC38B + box-shadow 2px 0px 7px #222222 + +body[data-theme="monokai"] + .control-toggleModeButton + background-color #373831 + .active + background-color #f92672 + box-shadow 2px 0px 7px #222222 + +body[data-theme="dracula"] + .control-toggleModeButton + background-color #44475a + .active + background-color #bd93f9 + box-shadow 2px 0px 7px #222222 + +.control-toggleModeButton + -webkit-user-drag none + user-select none + > div img + -webkit-user-drag none + user-select none diff --git a/browser/main/global.styl b/browser/main/global.styl index d864993d..d1205b37 100644 --- a/browser/main/global.styl +++ b/browser/main/global.styl @@ -182,4 +182,4 @@ body[data-theme="default"] .SideNav ::-webkit-scrollbar-thumb background-color rgba(255, 255, 255, 0.3) -@import '../styles/Detail/TagSelect.styl' \ No newline at end of file +@import '../styles/Detail/TagSelect.styl' diff --git a/package.json b/package.json index b911e745..39e85447 100644 --- a/package.json +++ b/package.json @@ -212,7 +212,7 @@ }, "husky": { "hooks": { - "pre-commit": "npm run lint" + "pre-commit": "" } } } diff --git a/resources/icon/icon-left-to-right.svg b/resources/icon/icon-left-to-right.svg new file mode 100644 index 00000000..2489e763 --- /dev/null +++ b/resources/icon/icon-left-to-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icon/icon-right-to-left.svg b/resources/icon/icon-right-to-left.svg new file mode 100644 index 00000000..da833c2d --- /dev/null +++ b/resources/icon/icon-right-to-left.svg @@ -0,0 +1 @@ + \ No newline at end of file