diff --git a/browser/components/ColorPicker.js b/browser/components/ColorPicker.js
new file mode 100644
index 00000000..9e0199c2
--- /dev/null
+++ b/browser/components/ColorPicker.js
@@ -0,0 +1,68 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { SketchPicker } from 'react-color'
+import CSSModules from 'browser/lib/CSSModules'
+import styles from './ColorPicker.styl'
+
+const componentHeight = 330
+
+class ColorPicker extends React.Component {
+ constructor (props) {
+ super(props)
+
+ this.state = {
+ color: this.props.color || '#939395'
+ }
+
+ this.onColorChange = this.onColorChange.bind(this)
+ this.handleConfirm = this.handleConfirm.bind(this)
+ }
+
+ componentWillReceiveProps (nextProps) {
+ this.onColorChange(nextProps.color)
+ }
+
+ onColorChange (color) {
+ this.setState({
+ color
+ })
+ }
+
+ handleConfirm () {
+ this.props.onConfirm(this.state.color)
+ }
+
+ render () {
+ const { onReset, onCancel, targetRect } = this.props
+ const { color } = this.state
+
+ const clientHeight = document.body.clientHeight
+ const alignX = targetRect.right + 4
+ let alignY = targetRect.top
+ if (targetRect.top + componentHeight > clientHeight) {
+ alignY = targetRect.bottom - componentHeight
+ }
+
+ return (
+
{note.tags.length > 0
- ? TagElementList(note.tags, showTagsAlphabetically)
+ ? TagElementList(note.tags, showTagsAlphabetically, coloredTags)
:
(
+const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count, color}) => (
handleContextMenu(e, name)}>
{isRelated
?
diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js
index e9b0ee37..11d8ac2a 100644
--- a/browser/main/Detail/SnippetNoteDetail.js
+++ b/browser/main/Detail/SnippetNoteDetail.js
@@ -20,6 +20,7 @@ import _ from 'lodash'
import {findNoteTitle} from 'browser/lib/findNoteTitle'
import convertModeName from 'browser/lib/convertModeName'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
+import FullscreenButton from './FullscreenButton'
import TrashButton from './TrashButton'
import RestoreButton from './RestoreButton'
import PermanentDeleteButton from './PermanentDeleteButton'
@@ -791,6 +792,7 @@ class SnippetNoteDetail extends React.Component {
showTagsAlphabetically={config.ui.showTagsAlphabetically}
data={data}
onChange={(e) => this.handleChange(e)}
+ coloredTags={config.coloredTags}
/>
@@ -799,11 +801,7 @@ class SnippetNoteDetail extends React.Component {
isActive={note.isStarred}
/>
-
this.handleFullScreenButton(e)}>
-
- {i18n.__('Fullscreen')}
-
+
this.handleFullScreenButton(e)} />
this.handleTrashButtonClick(e)} />
diff --git a/browser/main/Detail/StarButton.js b/browser/main/Detail/StarButton.js
index d74809cd..8000970d 100644
--- a/browser/main/Detail/StarButton.js
+++ b/browser/main/Detail/StarButton.js
@@ -54,7 +54,7 @@ class StarButton extends React.Component {
: '../resources/icon/icon-star.svg'
}
/>
- {i18n.__('Star')}
+ {i18n.__('Star')}
)
}
diff --git a/browser/main/Detail/StarButton.styl b/browser/main/Detail/StarButton.styl
index d5fd755b..e9c523e9 100644
--- a/browser/main/Detail/StarButton.styl
+++ b/browser/main/Detail/StarButton.styl
@@ -21,6 +21,11 @@
opacity 0
transition 0.1s
+.tooltip:lang(ja)
+ @extend .tooltip
+ right 103px
+ width 70px
+
.root--active
@extend .root
transition 0.15s
diff --git a/browser/main/Detail/TagSelect.js b/browser/main/Detail/TagSelect.js
index c5221f66..e3d9a567 100644
--- a/browser/main/Detail/TagSelect.js
+++ b/browser/main/Detail/TagSelect.js
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types'
import React from 'react'
+import invertColor from 'invert-color'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TagSelect.styl'
import _ from 'lodash'
@@ -185,19 +186,34 @@ class TagSelect extends React.Component {
}
render () {
- const { value, className, showTagsAlphabetically } = this.props
+ const { value, className, showTagsAlphabetically, coloredTags } = this.props
const tagList = _.isArray(value)
? (showTagsAlphabetically ? _.sortBy(value) : value).map((tag) => {
+ const wrapperStyle = {}
+ const textStyle = {}
+ const BLACK = '#333333'
+ const WHITE = '#f1f1f1'
+ const color = coloredTags[tag]
+ const invertedColor = color && invertColor(color, { black: BLACK, white: WHITE })
+ let iconRemove = '../resources/icon/icon-x.svg'
+ if (color) {
+ wrapperStyle.backgroundColor = color
+ textStyle.color = invertedColor
+ }
+ if (invertedColor === WHITE) {
+ iconRemove = '../resources/icon/icon-x-light.svg'
+ }
return (
- this.handleTagLabelClick(tag)}>#{tag}
+ this.handleTagLabelClick(tag)}>#{tag}
this.handleTagRemoveButtonClick(tag)}
>
-
+
)
@@ -246,7 +262,8 @@ TagSelect.contextTypes = {
TagSelect.propTypes = {
className: PropTypes.string,
value: PropTypes.arrayOf(PropTypes.string),
- onChange: PropTypes.func
+ onChange: PropTypes.func,
+ coloredTags: PropTypes.object
}
export default CSSModules(TagSelect, styles)
diff --git a/browser/main/Detail/TagSelect.styl b/browser/main/Detail/TagSelect.styl
index c6b13f3c..844561c6 100644
--- a/browser/main/Detail/TagSelect.styl
+++ b/browser/main/Detail/TagSelect.styl
@@ -3,19 +3,18 @@
align-items center
user-select none
vertical-align middle
- width 100%
- overflow-x scroll
+ width 96%
+ overflow-x auto
white-space nowrap
- margin-top 31px
+ top 50px
position absolute
-
-.root::-webkit-scrollbar
- display none
+ &::-webkit-scrollbar
+ height 8px
.tag
display flex
align-items center
- margin 0px 2px
+ margin 0px 2px 2px
padding 2px 4px
background-color alpha($ui-tag-backgroundColor, 3%)
border-radius 4px
diff --git a/browser/main/Detail/ToggleModeButton.js b/browser/main/Detail/ToggleModeButton.js
index 7c026429..fcbaab34 100644
--- a/browser/main/Detail/ToggleModeButton.js
+++ b/browser/main/Detail/ToggleModeButton.js
@@ -14,7 +14,7 @@ const ToggleModeButton = ({
onClick('EDITOR_PREVIEW')}>
- {i18n.__('Toggle Mode')}
+ {i18n.__('Toggle Mode')}
)
diff --git a/browser/main/Detail/ToggleModeButton.styl b/browser/main/Detail/ToggleModeButton.styl
index 73f5acbd..2b47b932 100644
--- a/browser/main/Detail/ToggleModeButton.styl
+++ b/browser/main/Detail/ToggleModeButton.styl
@@ -40,6 +40,11 @@
opacity 0
transition 0.1s
+.tooltip:lang(ja)
+ @extend .tooltip
+ left -8px
+ width 70px
+
body[data-theme="dark"]
.control-fullScreenButton
topBarButtonDark()
diff --git a/browser/main/Detail/TrashButton.js b/browser/main/Detail/TrashButton.js
index 473c2d0b..d26be66e 100644
--- a/browser/main/Detail/TrashButton.js
+++ b/browser/main/Detail/TrashButton.js
@@ -11,7 +11,7 @@ const TrashButton = ({
onClick={(e) => onClick(e)}
>

-
{i18n.__('Trash')}
+
{i18n.__('Trash')}
)
diff --git a/browser/main/Detail/TrashButton.styl b/browser/main/Detail/TrashButton.styl
index 7c7af878..a82cfa6b 100644
--- a/browser/main/Detail/TrashButton.styl
+++ b/browser/main/Detail/TrashButton.styl
@@ -17,6 +17,10 @@
opacity 0
transition 0.1s
+.tooltip:lang(ja)
+ @extend .tooltip
+ right 46px
+
.control-trashButton--in-trash
top 60px
topBarButtonRight()
diff --git a/browser/main/Main.js b/browser/main/Main.js
index 556c5daf..26fc8377 100644
--- a/browser/main/Main.js
+++ b/browser/main/Main.js
@@ -172,10 +172,21 @@ class Main extends React.Component {
delete CodeMirror.keyMap.emacs['Ctrl-V']
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
+ eventEmitter.on('menubar:togglemenubar', this.toggleMenuBarVisible.bind(this))
}
componentWillUnmount () {
eventEmitter.off('editor:fullscreen', this.toggleFullScreen)
+ eventEmitter.off('menubar:togglemenubar', this.toggleMenuBarVisible.bind(this))
+ }
+
+ toggleMenuBarVisible () {
+ const { config } = this.props
+ const { ui } = config
+
+ const newUI = Object.assign(ui, {showMenuBar: !ui.showMenuBar})
+ const newConfig = Object.assign(config, newUI)
+ ConfigManager.set(newConfig)
}
handleLeftSlideMouseDown (e) {
diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js
index dbc9cfd3..ca513c04 100644
--- a/browser/main/NoteList/index.js
+++ b/browser/main/NoteList/index.js
@@ -1047,6 +1047,7 @@ class NoteList extends React.Component {
storageName={this.getNoteStorage(note).name}
viewType={viewType}
showTagsAlphabetically={config.ui.showTagsAlphabetically}
+ coloredTags={config.coloredTags}
/>
)
}
diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js
index b98d859d..640bedbf 100644
--- a/browser/main/SideNav/index.js
+++ b/browser/main/SideNav/index.js
@@ -20,6 +20,7 @@ import i18n from 'browser/lib/i18n'
import context from 'browser/lib/context'
import { remote } from 'electron'
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
+import ColorPicker from 'browser/components/ColorPicker'
function matchActiveTags (tags, activeTags) {
return _.every(activeTags, v => tags.indexOf(v) >= 0)
@@ -27,6 +28,22 @@ function matchActiveTags (tags, activeTags) {
class SideNav extends React.Component {
// TODO: should not use electron stuff v0.7
+ constructor (props) {
+ super(props)
+
+ this.state = {
+ colorPicker: {
+ show: false,
+ color: null,
+ tagName: null,
+ targetRect: null
+ }
+ }
+
+ this.dismissColorPicker = this.dismissColorPicker.bind(this)
+ this.handleColorPickerConfirm = this.handleColorPickerConfirm.bind(this)
+ this.handleColorPickerReset = this.handleColorPickerReset.bind(this)
+ }
componentDidMount () {
EventEmitter.on('side:preferences', this.handleMenuButtonClick)
@@ -104,9 +121,64 @@ class SideNav extends React.Component {
click: this.deleteTag.bind(this, tag)
})
+ menu.push({
+ label: i18n.__('Customize Color'),
+ click: this.displayColorPicker.bind(this, tag, e.target.getBoundingClientRect())
+ })
+
context.popup(menu)
}
+ dismissColorPicker () {
+ this.setState({
+ colorPicker: {
+ show: false
+ }
+ })
+ }
+
+ displayColorPicker (tagName, rect) {
+ const { config } = this.props
+ this.setState({
+ colorPicker: {
+ show: true,
+ color: config.coloredTags[tagName],
+ tagName,
+ targetRect: rect
+ }
+ })
+ }
+
+ handleColorPickerConfirm (color) {
+ const { dispatch, config: {coloredTags} } = this.props
+ const { colorPicker: { tagName } } = this.state
+ const newColoredTags = Object.assign({}, coloredTags, {[tagName]: color.hex})
+
+ const config = { coloredTags: newColoredTags }
+ ConfigManager.set(config)
+ dispatch({
+ type: 'SET_CONFIG',
+ config
+ })
+ this.dismissColorPicker()
+ }
+
+ handleColorPickerReset () {
+ const { dispatch, config: {coloredTags} } = this.props
+ const { colorPicker: { tagName } } = this.state
+ const newColoredTags = Object.assign({}, coloredTags)
+
+ delete newColoredTags[tagName]
+
+ const config = { coloredTags: newColoredTags }
+ ConfigManager.set(config)
+ dispatch({
+ type: 'SET_CONFIG',
+ config
+ })
+ this.dismissColorPicker()
+ }
+
handleToggleButtonClick (e) {
const { dispatch, config } = this.props
@@ -207,6 +279,7 @@ class SideNav extends React.Component {
tagListComponent () {
const { data, location, config } = this.props
+ const { colorPicker } = this.state
const activeTags = this.getActiveTags(location.pathname)
const relatedTags = this.getRelatedTags(activeTags, data.noteMap)
let tagList = _.sortBy(data.tagNoteMap.map(
@@ -237,10 +310,11 @@ class SideNav extends React.Component {
handleClickTagListItem={this.handleClickTagListItem.bind(this)}
handleClickNarrowToTag={this.handleClickNarrowToTag.bind(this)}
handleContextMenu={this.handleTagContextMenu.bind(this)}
- isActive={this.getTagActive(location.pathname, tag.name)}
+ isActive={this.getTagActive(location.pathname, tag.name) || (colorPicker.tagName === tag.name)}
isRelated={tag.related}
key={tag.name}
count={tag.size}
+ color={config.coloredTags[tag.name]}
/>
)
})
@@ -333,6 +407,7 @@ class SideNav extends React.Component {
render () {
const { data, location, config, dispatch } = this.props
+ const { colorPicker: colorPickerState } = this.state
const isFolded = config.isSideNavFolded
@@ -349,6 +424,20 @@ class SideNav extends React.Component {
useDragHandle
/>
})
+
+ let colorPicker
+ if (colorPickerState.show) {
+ colorPicker = (
+
+ )
+ }
+
const style = {}
if (!isFolded) style.width = this.props.width
const isTagActive = location.pathname.match(/tag/)
@@ -368,6 +457,7 @@ class SideNav extends React.Component {
{this.SideNavComponent(isFolded, storageList)}
+ {colorPicker}
)
}
diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
index 81165777..059589d0 100644
--- a/browser/main/lib/ConfigManager.js
+++ b/browser/main/lib/ConfigManager.js
@@ -26,14 +26,16 @@ export const DEFAULT_CONFIG = {
toggleMain: OSX ? 'Command + Alt + L' : 'Super + Alt + E',
toggleMode: OSX ? 'Command + Alt + M' : 'Ctrl + M',
deleteNote: OSX ? 'Command + Shift + Backspace' : 'Ctrl + Shift + Backspace',
- pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V'
+ pasteSmartly: OSX ? 'Command + Shift + V' : 'Ctrl + Shift + V',
+ toggleMenuBar: 'Alt'
},
ui: {
language: 'en',
theme: 'default',
showCopyNotification: true,
disableDirectWrite: false,
- defaultNote: 'ALWAYS_ASK' // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE'
+ defaultNote: 'ALWAYS_ASK', // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE'
+ showMenuBar: false
},
editor: {
theme: 'base16-light',
@@ -86,7 +88,8 @@ export const DEFAULT_CONFIG = {
token: '',
username: '',
password: ''
- }
+ },
+ coloredTags: {}
}
function validate (config) {
diff --git a/browser/main/lib/shortcut.js b/browser/main/lib/shortcut.js
index 93e33c9b..3165606a 100644
--- a/browser/main/lib/shortcut.js
+++ b/browser/main/lib/shortcut.js
@@ -6,5 +6,8 @@ module.exports = {
},
'deleteNote': () => {
ee.emit('hotkey:deletenote')
+ },
+ 'toggleMenuBar': () => {
+ ee.emit('menubar:togglemenubar')
}
}
diff --git a/browser/main/modals/PreferencesModal/FolderItem.styl b/browser/main/modals/PreferencesModal/FolderItem.styl
index 2ded3ada..618e9bc4 100644
--- a/browser/main/modals/PreferencesModal/FolderItem.styl
+++ b/browser/main/modals/PreferencesModal/FolderItem.styl
@@ -62,7 +62,7 @@
.folderItem-right-button
vertical-align middle
height 25px
- margin-top 2.5px
+ margin-top 2px
colorDefaultButton()
border-radius 2px
border $ui-border
diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js
index 25098faa..218a68f6 100644
--- a/browser/main/modals/PreferencesModal/HotkeyTab.js
+++ b/browser/main/modals/PreferencesModal/HotkeyTab.js
@@ -80,7 +80,8 @@ class HotkeyTab extends React.Component {
toggleMain: this.refs.toggleMain.value,
toggleMode: this.refs.toggleMode.value,
deleteNote: this.refs.deleteNote.value,
- pasteSmartly: this.refs.pasteSmartly.value
+ pasteSmartly: this.refs.pasteSmartly.value,
+ toggleMenuBar: this.refs.toggleMenuBar.value
}
this.setState({
config
@@ -128,6 +129,17 @@ class HotkeyTab extends React.Component {
/>
+
{i18n.__('Toggle Editor Mode')}
diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js
index c8646c39..c6181a13 100644
--- a/browser/main/modals/PreferencesModal/UiTab.js
+++ b/browser/main/modals/PreferencesModal/UiTab.js
@@ -75,6 +75,7 @@ class UiTab extends React.Component {
showTagsAlphabetically: this.refs.showTagsAlphabetically.checked,
saveTagsAlphabetically: this.refs.saveTagsAlphabetically.checked,
enableLiveNoteCounts: this.refs.enableLiveNoteCounts.checked,
+ showMenuBar: this.refs.showMenuBar.checked,
disableDirectWrite: this.refs.uiD2w != null
? this.refs.uiD2w.checked
: false
@@ -238,6 +239,16 @@ class UiTab extends React.Component {
+