From 89a76d9eadb7619741d2eea4313eb6c594feb6c8 Mon Sep 17 00:00:00 2001 From: Rokt33r Date: Thu, 19 May 2016 13:58:39 +0900 Subject: [PATCH] resizible list --- browser/main/ArticleDetail/index.js | 339 --------------- browser/main/Main.js | 91 +++- browser/main/Main.styl | 25 ++ .../ArticleEditor.js | 0 browser/main/NoteDetail/NoteDetail.styl | 17 + .../ShareButton.js | 0 browser/main/NoteDetail/index.js | 45 ++ browser/main/NoteList/NoteList.styl | 4 + browser/main/NoteList/index.js | 150 +++++++ browser/main/SideNav/FolderItem.styl | 1 + browser/main/SideNav/RepositorySection.js | 2 +- browser/main/SideNav/RepositorySection.styl | 9 +- browser/main/SideNav/SideNav.styl | 6 +- browser/main/SideNav/index.js | 21 +- browser/main/StatusBar/StatusBar.styl | 3 +- browser/main/TopBar/TopBar.styl | 12 +- browser/main/TopBar/index.js | 5 +- browser/main/lib/ConfigManager.js | 14 +- browser/main/store.js | 7 +- browser/styles/index.styl | 1 + browser/styles/main/ArticleDetail.styl | 393 ------------------ browser/styles/main/ArticleList.styl | 105 ----- browser/styles/main/ArticleNavigator.styl | 213 ---------- browser/styles/main/index.styl | 19 - 24 files changed, 370 insertions(+), 1112 deletions(-) delete mode 100644 browser/main/ArticleDetail/index.js create mode 100644 browser/main/Main.styl rename browser/main/{ArticleDetail => NoteDetail}/ArticleEditor.js (100%) create mode 100644 browser/main/NoteDetail/NoteDetail.styl rename browser/main/{ArticleDetail => NoteDetail}/ShareButton.js (100%) create mode 100644 browser/main/NoteDetail/index.js create mode 100644 browser/main/NoteList/NoteList.styl create mode 100644 browser/main/NoteList/index.js delete mode 100644 browser/styles/main/ArticleDetail.styl delete mode 100644 browser/styles/main/ArticleList.styl delete mode 100644 browser/styles/main/ArticleNavigator.styl diff --git a/browser/main/ArticleDetail/index.js b/browser/main/ArticleDetail/index.js deleted file mode 100644 index 1db13315..00000000 --- a/browser/main/ArticleDetail/index.js +++ /dev/null @@ -1,339 +0,0 @@ -import React, { PropTypes } from 'react' -import ReactDOM from 'react-dom' -import moment from 'moment' -import _ from 'lodash' -import TagSelect from 'browser/components/TagSelect' -import ModeSelect from 'browser/components/ModeSelect' -import ShareButton from './ShareButton' -import { openModal, isModalOpen } from 'browser/main/lib/modal' -import DeleteArticleModal from '../modals/DeleteArticleModal' -import ArticleEditor from './ArticleEditor' -const electron = require('electron') -const ipc = electron.ipcRenderer -import fetchConfig from 'browser/lib/fetchConfig' - -let config = fetchConfig() -ipc.on('config-apply', function (e, newConfig) { - config = newConfig -}) - -const BRAND_COLOR = '#18AF90' -const OSX = global.process.platform === 'darwin' - -const tagSelectTutorialElement = ( - - Attach some tags here! - - - - - - - - -) - -const modeSelectTutorialElement = ( - - Select code syntax!! - - - - - - - -) - -export default class ArticleDetail extends React.Component { - constructor (props) { - super(props) - - this.deleteHandler = (e) => { - if (isModalOpen()) return true - this.handleDeleteButtonClick() - } - this.uncacheHandler = (e) => { - if (isModalOpen()) return true - this.handleUncache() - } - this.titleHandler = (e) => { - if (isModalOpen()) return true - if (this.refs.title) { - this.focusTitle() - } - } - this.editHandler = (e) => { - if (isModalOpen()) return true - if (this.refs.editor) this.refs.editor.switchEditMode() - } - this.previewHandler = (e) => { - if (isModalOpen()) return true - if (this.refs.editor) this.refs.editor.switchPreviewMode() - } - this.configApplyHandler = (e, config) => this.handleConfigApply(e, config) - - this.state = { - article: Object.assign({content: ''}, props.activeArticle), - openShareDropdown: false, - fontFamily: config['editor-font-family'] - } - } - - componentDidMount () { - this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000) - this.shareDropdownInterceptor = (e) => { - e.stopPropagation() - } - - ipc.on('detail-delete', this.deleteHandler) - ipc.on('detail-uncache', this.uncacheHandler) - ipc.on('detail-title', this.titleHandler) - ipc.on('detail-edit', this.editHandler) - ipc.on('detail-preview', this.previewHandler) - ipc.on('config-apply', this.configApplyHandler) - } - - componentWillUnmount () { - clearInterval(this.refreshTimer) - - ipc.removeListener('detail-delete', this.deleteHandler) - ipc.removeListener('detail-uncache', this.uncacheHandler) - ipc.removeListener('detail-title', this.titleHandler) - ipc.removeListener('detail-edit', this.editHandler) - ipc.removeListener('detail-preview', this.previewHandler) - } - - componentDidUpdate (prevProps, prevState) { - if (this.props.activeArticle == null || prevProps.activeArticle == null || this.props.activeArticle.key !== prevProps.activeArticle.key) { - if (this.refs.editor) this.refs.editor.resetCursorPosition() - } - - if (prevProps.activeArticle == null && this.props.activeArticle) { - - } - } - - handleConfigApply (e, config) { - this.setState({ - fontFamily: config['editor-font-family'] - }) - } - - renderEmpty () { - return ( -
-
-
{OSX ? 'Command(⌘)' : 'Ctrl(^)'} + N
to create a new post
-
-
- ) - } - - handleOthersButtonClick (e) { - this.deleteHandler() - } - - handleFolderKeyChange (e) { - let { dispatch, activeArticle, status, folders } = this.props - let article = Object.assign({}, activeArticle, { - FolderKey: e.target.value, - updatedAt: new Date() - }) - - // dispatch(updateArticle(article)) - - let targetFolderKey = e.target.value - if (status.targetFolders.length > 0) { - let targetFolder = _.findWhere(folders, {key: targetFolderKey}) - // dispatch(switchFolder(targetFolder.name)) - } - } - - handleTitleChange (e) { - let { dispatch, activeArticle } = this.props - let article = Object.assign({}, activeArticle, { - title: e.target.value, - updatedAt: new Date() - }) - // dispatch(updateArticle(article)) - } - - handleTagsChange (newTag, tags) { - let { dispatch, activeArticle } = this.props - let article = Object.assign({}, activeArticle, { - tags: tags, - updatedAt: new Date() - }) - - // dispatch(updateArticle(article)) - } - - handleModeChange (value) { - let { dispatch, activeArticle } = this.props - let article = Object.assign({}, activeArticle, { - mode: value, - updatedAt: new Date() - }) - - // dispatch(updateArticle(article)) - this.switchEditMode() - } - - handleContentChange (value) { - let { dispatch, activeArticle } = this.props - if (activeArticle.content !== value) { - let article = Object.assign({}, activeArticle, { - content: value, - updatedAt: new Date() - }) - - // dispatch(updateArticle(article)) - } - } - - handleDeleteButtonClick (e) { - if (this.props.activeArticle) { - openModal(DeleteArticleModal, {articleKey: this.props.activeArticle.key}) - } - } - - handleTitleKeyDown (e) { - if (e.keyCode === 9 && !e.shiftKey) { - e.preventDefault() - this.refs.mode.handleIdleSelectClick() - } - } - - handleModeSelectKeyDown (e) { - if (e.keyCode === 9 && !e.shiftKey) { - e.preventDefault() - this.switchEditMode() - } - - if (e.keyCode === 9 && e.shiftKey) { - e.preventDefault() - this.focusTitle() - } - - if (e.keyCode === 27) { - this.focusTitle() - } - } - - switchEditMode () { - this.refs.editor.switchEditMode() - } - - focusTitle () { - if (this.refs.title) { - let titleEl = ReactDOM.findDOMNode(this.refs.title) - titleEl.focus() - titleEl.select() - } - } - - render () { - let { folders, status, tags, activeArticle, modified, user } = this.props - if (activeArticle == null) return this.renderEmpty() - let folderOptions = folders.map((folder) => { - return ( - - ) - }) - - let isUnsaved = !!_.findWhere(modified, {key: activeArticle.key}) - - return ( -
-
-
- - Unsaved - : `Created : ${moment(activeArticle.createdAt).format('YYYY/MM/DD')} Updated : ${moment(activeArticle.updatedAt).format('YYYY/MM/DD')}` - } - /> - -
- - - -
-
-
- this.handleTagsChange(tags, tag)} - suggestTags={tags} - /> - - {status.isTutorialOpen ? tagSelectTutorialElement : null} -
-
- -
-
-
- this.handleTitleKeyDown(e)} - placeholder='(Untitled)' - ref='title' - value={activeArticle.title} - onChange={(e) => this.handleTitleChange(e)} - style={{ - fontFamily: this.state.fontFamily - }} - /> -
- this.handleModeChange(e)} - onKeyDown={(e) => this.handleModeSelectKeyDown(e)} - value={activeArticle.mode} - className='ArticleDetail-panel-header-mode' - /> - {status.isTutorialOpen ? modeSelectTutorialElement : null} -
- this.handleContentChange(content)} - /> -
-
- ) - } -} - -ArticleDetail.propTypes = { - dispatch: PropTypes.func, - repositories: PropTypes.array -} diff --git a/browser/main/Main.js b/browser/main/Main.js index 10fbcd01..ee8f12e6 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -1,13 +1,27 @@ import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './Main.styl' import { connect } from 'react-redux' import SideNav from './SideNav' import TopBar from './TopBar' -import ArticleList from './ArticleList' -import ArticleDetail from './ArticleDetail' +import NoteList from './NoteList' +import NoteDetail from './NoteDetail' import Repository from 'browser/lib/Repository' import StatusBar from './StatusBar' +import _ from 'lodash' +import ConfigManager from 'browser/main/lib/ConfigManager' class Main extends React.Component { + constructor (props) { + super(props) + + let { config } = props + + this.state = { + isSliderFocused: false, + listWidth: config.listWidth + } + } componentDidMount () { let { dispatch } = this.props @@ -18,25 +32,74 @@ class Main extends React.Component { }) } + handleSlideMouseDown (e) { + e.preventDefault() + this.setState({ + isSliderFocused: true + }) + } + + handleMouseUp (e) { + if (this.state.isSliderFocused) { + this.setState({ + isSliderFocused: false + }, () => { + let { dispatch } = this.props + let newListWidth = this.state.listWidth + // TODO: ConfigManager should dispatch itself. + ConfigManager.set({listWidth: newListWidth}) + dispatch({ + type: 'SET_LIST_WIDTH', + listWidth: newListWidth + }) + }) + } + } + + handleMouseMove (e) { + if (this.state.isSliderFocused) { + let offset = this.refs.body.getBoundingClientRect().left + let newListWidth = e.pageX - offset + if (newListWidth < 10) { + newListWidth = 10 + } else if (newListWidth > 600) { + newListWidth = 600 + } + this.setState({ + listWidth: newListWidth + }) + } + } + render () { + let { config } = this.props + return (
this.handleMouseMove(e)} + onMouseUp={(e) => this.handleMouseUp(e)} > - - - + +
+ +
this.handleSlideMouseDown(e)} + draggable='false' + /> + +
) @@ -48,4 +111,4 @@ Main.propTypes = { repositories: PropTypes.array } -export default connect((x) => x)(Main) +export default connect((x) => x)(CSSModules(Main, styles)) diff --git a/browser/main/Main.styl b/browser/main/Main.styl new file mode 100644 index 00000000..ef6eddb3 --- /dev/null +++ b/browser/main/Main.styl @@ -0,0 +1,25 @@ +.root + absolute top left bottom right + +.body + absolute right + bottom $statusBar-height - 1 + top $topBar-height - 1 + left $sideNav-width + +.body--expanded + @extend .body + left $sideNav--folded-width + +.slider + absolute top bottom + width 5px + background-color $ui-backgroundColor + border-width 0 1px 0 + border-style solid + border-color $ui-borderColor + cursor ew-resize + +.slider--active + @extend .slider + background-color $ui-button--active-backgroundColor diff --git a/browser/main/ArticleDetail/ArticleEditor.js b/browser/main/NoteDetail/ArticleEditor.js similarity index 100% rename from browser/main/ArticleDetail/ArticleEditor.js rename to browser/main/NoteDetail/ArticleEditor.js diff --git a/browser/main/NoteDetail/NoteDetail.styl b/browser/main/NoteDetail/NoteDetail.styl new file mode 100644 index 00000000..3a641159 --- /dev/null +++ b/browser/main/NoteDetail/NoteDetail.styl @@ -0,0 +1,17 @@ +.root + absolute top bottom right + border-width 1px 0 + border-style solid + border-color $ui-borderColor + +.empty + height 320px + display flex + align-items center +.empty-message + width 100% + font-size 42px + line-height 72px + text-align center + color $ui-inactive-text-color + diff --git a/browser/main/ArticleDetail/ShareButton.js b/browser/main/NoteDetail/ShareButton.js similarity index 100% rename from browser/main/ArticleDetail/ShareButton.js rename to browser/main/NoteDetail/ShareButton.js diff --git a/browser/main/NoteDetail/index.js b/browser/main/NoteDetail/index.js new file mode 100644 index 00000000..3d9b7c56 --- /dev/null +++ b/browser/main/NoteDetail/index.js @@ -0,0 +1,45 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './NoteDetail.styl' +const electron = require('electron') + +const OSX = global.process.platform === 'darwin' + +class NoteDetail extends React.Component { + componentDidUpdate (prevProps, prevState) { + } + + renderEmpty () { + return ( +
+
{OSX ? 'Command(⌘)' : 'Ctrl(^)'} + N
to create a new post
+
+ ) + } + + render () { + let isEmpty = true + let view = isEmpty + ? this.renderEmpty() + : null + return ( +
+ {view} +
+ ) + } +} + +NoteDetail.propTypes = { + dispatch: PropTypes.func, + repositories: PropTypes.array, + style: PropTypes.shape({ + left: PropTypes.number + }) +} + +export default CSSModules(NoteDetail, styles) diff --git a/browser/main/NoteList/NoteList.styl b/browser/main/NoteList/NoteList.styl new file mode 100644 index 00000000..26643c16 --- /dev/null +++ b/browser/main/NoteList/NoteList.styl @@ -0,0 +1,4 @@ +.root + absolute top left bottom + border-top $ui-border + border-bottom $ui-border diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js new file mode 100644 index 00000000..e7a05d33 --- /dev/null +++ b/browser/main/NoteList/index.js @@ -0,0 +1,150 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './NoteList.styl' +import ReactDOM from 'react-dom' +import ModeIcon from 'browser/components/ModeIcon' +import moment from 'moment' +import _ from 'lodash' + +const electron = require('electron') +const remote = electron.remote +const ipc = electron.ipcRenderer + +class NoteList extends React.Component { + constructor (props) { + super(props) + + // this.focusHandler = (e) => this.focus() + } + + componentDidMount () { + // this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000) + // ipc.on('list-focus', this.focusHandler) + // this.focus() + } + + componentWillUnmount () { + // clearInterval(this.refreshTimer) + // ipc.removeListener('list-focus', this.focusHandler) + } + + componentDidUpdate () { + // return false + // var index = articles.indexOf(null) + // var el = ReactDOM.findDOMNode(this) + // var li = el.querySelectorAll('.NoteList>div')[index] + + // if (li == null) { + // return + // } + + // var overflowBelow = el.clientHeight + el.scrollTop < li.offsetTop + li.clientHeight + // if (overflowBelow) { + // el.scrollTop = li.offsetTop + li.clientHeight - el.clientHeight + // } + // var overflowAbove = el.scrollTop > li.offsetTop + // if (overflowAbove) { + // el.scrollTop = li.offsetTop + // } + } + + focus () { + // ReactDOM.findDOMNode(this).focus() + } + + // 移動ができなかったらfalseを返す: + selectPriorArticle () { + let { articles, activeArticle, dispatch } = this.props + let targetIndex = articles.indexOf(activeArticle) - 1 + let targetArticle = articles[targetIndex] + return false + } + + selectNextArticle () { + let { articles, activeArticle, dispatch } = this.props + let targetIndex = articles.indexOf(activeArticle) + 1 + let targetArticle = articles[targetIndex] + + if (targetArticle != null) { + dispatch(switchArticle(targetArticle.key)) + return true + } + return false + } + + handleArticleClick (article) { + let { dispatch } = this.props + return function (e) { + dispatch(switchArticle(article.key)) + } + } + + handleNoteListKeyDown (e) { + if (e.metaKey || e.ctrlKey) return true + + if (e.keyCode === 65 && !e.shiftKey) { + e.preventDefault() + remote.getCurrentWebContents().send('top-new-post') + } + + if (e.keyCode === 65 && e.shiftKey) { + e.preventDefault() + remote.getCurrentWebContents().send('nav-new-folder') + } + + if (e.keyCode === 68) { + e.preventDefault() + remote.getCurrentWebContents().send('detail-delete') + } + + if (e.keyCode === 84) { + e.preventDefault() + remote.getCurrentWebContents().send('detail-title') + } + + if (e.keyCode === 69) { + e.preventDefault() + remote.getCurrentWebContents().send('detail-edit') + } + + if (e.keyCode === 83) { + e.preventDefault() + remote.getCurrentWebContents().send('detail-save') + } + + if (e.keyCode === 38) { + e.preventDefault() + this.selectPriorArticle() + } + + if (e.keyCode === 40) { + e.preventDefault() + this.selectNextArticle() + } + } + + render () { + let articleElements = [] + + return ( +
this.handleNoteListKeyDown(e)} + style={this.props.style} + > + {articleElements} +
+ ) + } +} + +NoteList.propTypes = { + dispatch: PropTypes.func, + repositories: PropTypes.array, + style: PropTypes.shape({ + width: PropTypes.number + }) +} + +export default CSSModules(NoteList, styles) diff --git a/browser/main/SideNav/FolderItem.styl b/browser/main/SideNav/FolderItem.styl index 8cbeb646..bf64366b 100644 --- a/browser/main/SideNav/FolderItem.styl +++ b/browser/main/SideNav/FolderItem.styl @@ -86,6 +86,7 @@ margin-left 0 overflow ellipsis background-color $ui-tooltip-backgroundColor + z-index 10 color white line-height 34px border-top-right-radius 5px diff --git a/browser/main/SideNav/RepositorySection.js b/browser/main/SideNav/RepositorySection.js index 110d3a22..a643d9e8 100644 --- a/browser/main/SideNav/RepositorySection.js +++ b/browser/main/SideNav/RepositorySection.js @@ -158,7 +158,7 @@ class RepositorySection extends React.Component { onContextMenu={(e) => this.handleContextButtonClick(e)} >
- + {repository.name}
diff --git a/browser/main/SideNav/RepositorySection.styl b/browser/main/SideNav/RepositorySection.styl index e73e9c8c..f9e7e9fe 100644 --- a/browser/main/SideNav/RepositorySection.styl +++ b/browser/main/SideNav/RepositorySection.styl @@ -10,10 +10,12 @@ text-align left font-size 14px color $ui-inactive-text-color + &:hover + background-color $ui-button--hover-backgroundColor &:hover .header-control-button opacity 1 &:active - background-color $ui-button--active-backgroundColor !important + background-color $ui-button--active-backgroundColor color $ui-button--active-color .header-control-button, .header-control-button--show color white @@ -22,6 +24,8 @@ @extend .header background-color $ui-button--active-backgroundColor color $ui-button--active-color + &:hover + background-color $ui-button--active-backgroundColor .header-control-button, .header-control-button--show color white @@ -124,6 +128,7 @@ margin-left 0 overflow ellipsis background-color $ui-tooltip-backgroundColor + z-index 10 color white line-height 34px border-top-right-radius 5px @@ -136,6 +141,7 @@ height 33px top inherit bottom inherit + z-index 11 left 43px box-sizing border-box overflow hidden @@ -164,6 +170,7 @@ margin-left 0 overflow ellipsis background-color $ui-tooltip-backgroundColor + z-index 10 color white line-height 34px border-top-right-radius 5px diff --git a/browser/main/SideNav/SideNav.styl b/browser/main/SideNav/SideNav.styl index 8fcab2f6..e4249119 100644 --- a/browser/main/SideNav/SideNav.styl +++ b/browser/main/SideNav/SideNav.styl @@ -1,8 +1,9 @@ .root absolute top left - bottom $statusBar-height + bottom $statusBar-height - 1 width $sideNav-width border-right $ui-border + border-bottom $ui-border background-color $ui-backgroundColor user-select none color $ui-text-color @@ -88,6 +89,7 @@ margin-left 0 overflow hidden background-color $ui-tooltip-backgroundColor + z-index 10 color white line-height 34px border-top-right-radius 5px @@ -99,6 +101,7 @@ text-align center &:hover .menu-button-label width 100px + // TODO: extract tooltip style to a mixin .menu-button-label position fixed display inline-block @@ -110,6 +113,7 @@ margin-left 0 overflow ellipsis background-color $ui-tooltip-backgroundColor + z-index 10 color white line-height 34px border-top-right-radius 5px diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 025236d6..05411f16 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -74,8 +74,7 @@ class SideNav extends React.Component { }) return ( -
@@ -83,7 +82,7 @@ class SideNav extends React.Component {
@@ -92,17 +91,13 @@ class SideNav extends React.Component {
@@ -132,7 +127,13 @@ SideNav.contextTypes = { SideNav.propTypes = { dispatch: PropTypes.func, - repositories: PropTypes.array + repositories: PropTypes.array, + config: PropTypes.shape({ + isSideNavFolded: PropTypes.bool + }), + location: PropTypes.shape({ + pathname: PropTypes.string + }) } export default CSSModules(SideNav, styles) diff --git a/browser/main/StatusBar/StatusBar.styl b/browser/main/StatusBar/StatusBar.styl index bdbc431d..7687b112 100644 --- a/browser/main/StatusBar/StatusBar.styl +++ b/browser/main/StatusBar/StatusBar.styl @@ -1,7 +1,6 @@ .root absolute bottom left right - height $statusBar-height - border-top $ui-border + height $statusBar-height - 1 background-color $ui-backgroundColor .pathname diff --git a/browser/main/TopBar/TopBar.styl b/browser/main/TopBar/TopBar.styl index 570e8912..56ad9c72 100644 --- a/browser/main/TopBar/TopBar.styl +++ b/browser/main/TopBar/TopBar.styl @@ -2,14 +2,13 @@ absolute top right background-color $ui-backgroundColor left $sideNav-width - border-bottom $ui-border - height 60px + height $topBar-height -1 clearfix() .left float left - height 59px - line-height 60px + height $topBar-height - 1 + line-height $topBar-height .left-search margin-top 12px @@ -60,11 +59,12 @@ .left-control-newPostButton-tooltip position fixed + line-height 1.4 background-color $ui-tooltip-backgroundColor color $ui-tooltip-text-color font-size 10px margin-left -35px - margin-top 12px + margin-top 5px padding 5px z-index 1 border-radius 5px @@ -73,7 +73,7 @@ .right float right - height 60px + height $topBar-height -1 clearfix() .right-helpButton diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 922ccf48..3aa89aee 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react' +import { connect } from 'react-redux' import CSSModules from 'browser/lib/CSSModules' import styles from './TopBar.styl' import activityRecord from 'browser/lib/activityRecord' @@ -80,7 +81,7 @@ class TopBar extends React.Component { onClick={(e) => this.handleNewPostButtonClick(e)}> - New Post ({OSX ? '⌘' : '^'} + n) + New Post {OSX ? '⌘' : '^'} + n @@ -111,4 +112,4 @@ TopBar.propTypes = { }) } -export default CSSModules(TopBar, styles) +export default connect((x) => x)(CSSModules(TopBar, styles)) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 71153544..692bf3c9 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -2,13 +2,16 @@ import _ from 'lodash' const defaultConfig = { zoom: 1, - isSideNavFolded: false + isSideNavFolded: false, + listWidth: 250 } -function _validate (config) { +function validate (config) { + console.log(config) if (!_.isObject(config)) return false if (!_.isNumber(config.zoom) || config.zoom < 0) return false if (!_.isBoolean(config.isSideNavFolded)) return false + if (!_.isNumber(config.listWidth) || config.listWidth <= 0) return false return true } @@ -22,7 +25,7 @@ function get () { try { config = JSON.parse(config) - if (!_validate(config)) throw new Error('INVALID CONFIG') + if (!validate(config)) throw new Error('INVALID CONFIG') } catch (err) { console.warn('Boostnote resets the malformed configuration.') config = defaultConfig @@ -35,11 +38,12 @@ function get () { function set (updates) { let currentConfig = get() let newConfig = Object.assign({}, defaultConfig, currentConfig, updates) - if (!_validate(newConfig)) throw new Error('INVALID CONFIG') + if (!validate(newConfig)) throw new Error('INVALID CONFIG') _save(newConfig) } export default { get, - set + set, + validate } diff --git a/browser/main/store.js b/browser/main/store.js index 0d37038b..012e9de6 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -30,7 +30,7 @@ import ConfigManager from 'browser/main/lib/ConfigManager' const initialRepositories = [] function repositories (state = initialRepositories, action) { - console.log(action) + console.info('REDUX >> ', action) switch (action.type) { case 'INIT_ALL': return action.data.slice() @@ -121,6 +121,11 @@ function config (state = defaultConfig, action) { case 'SET_ZOOM': state.zoom = action.zoom return Object.assign({}, state) + case 'SET_LIST_WIDTH': + state.listWidth = action.listWidth + return Object.assign({}, state) + case 'SET_CONFIG': + return Object.assign({}, state, action.config) } return state } diff --git a/browser/styles/index.styl b/browser/styles/index.styl index 3d39ba77..7d592146 100644 --- a/browser/styles/index.styl +++ b/browser/styles/index.styl @@ -7,6 +7,7 @@ $danger-lighten-color = #FFE5E6 $statusBar-height = 24px $sideNav-width = 200px $sideNav--folded-width = 44px +$topBar-height = 60px // UI default $ui-text-color = #515151 diff --git a/browser/styles/main/ArticleDetail.styl b/browser/styles/main/ArticleDetail.styl deleted file mode 100644 index bcf9edeb..00000000 --- a/browser/styles/main/ArticleDetail.styl +++ /dev/null @@ -1,393 +0,0 @@ -noTagsColor = #999 - -infoButton() - display inline-block - border-radius 16.5px - cursor pointer - height 33px - width 33px - line-height 33px - margin-right 5px - font-size 18px - color inactiveTextColor - background-color white - padding 0 - border 1px solid white - &:focus - border-color focusBorderColor - &:hover - color inherit - -.ArticleDetail - absolute right bottom - top 60px - left 450px - padding 10px - background-color #E6E6E6 - border-top 1px solid borderColor - &.empty - .ArticleDetail-empty-box - line-height 72px - font-size 42px - height 320px - display flex - align-items center - .ArticleDetail-empty-box-message - text-align center - width 100% - color inactiveTextColor - .ArticleDetail-info - height 70px - width 100% - font-size 12px - user-select none - &>.tutorial - position fixed - z-index 35 - .ArticleDetail-info-folder - display inline-block - max-width 100px - overflow ellipsis - height 10px - width 150px - height 27px - outline none - background-color darken(white, 5%) - border 1px solid transparent - &:hover - background-color white - &:focus - border-color focusBorderColor - &>.tutorial - position fixed - z-index 35 - .ArticleDetail-info-status - padding 0 5px - .unsaved-mark - color brandColor - .ArticleDetail-info-control - float right - clearfix - .ShareButton - display block - float left - &>button, .ShareButton-open-button - infoButton() - .tooltip - tooltip() - margin-top 30px - &:hover - .tooltip - opacity 1 - &>button - float left - &:nth-child(1) .tooltip - margin-left -65px - .ArticleDetail-info-control-delete-button - .tooltip - right 5px - .ArticleDetail-info-control-save - float left - width 80px - margin-right 5px - overflow hidden - transition width 0.15s ease-in-out - border-radius 16.5px - &.hide - width 0px - opacity 0.2 - .ArticleDetail-info-control-save-button - infoButton() - background-color brandColor - color white - font-size 12px - width 100% - border 1px solid brandBorderColor - white-space nowrap - .fa - font-size 18px - &:hover - color white - background-color lighten(brandColor, 15%) - &:focus - color white - background-color lighten(brandColor, 15%) - .tooltip - tooltip() - margin-top 30px - margin-left -90px - &:hover .tooltip - opacity 1 - - .ShareButton-open-button .tooltip - margin-left -40px - .ShareButton-dropdown - position fixed - width 185px - z-index 35 - background-color #F0F0F0 - padding 4px 0 - border-radius 5px - right 5px - top 95px - box-shadow 0px 0px 10px 1px alpha(#bbb, 0.8) - border 1px solid #bcbcbc - &.hide - display none - &>button - background-color transparent - height 21px - width 100% - border none - padding-left 20px - text-align left - font-size 13px - font-family '.HelveticaNeueDeskInterface-Regular', sans-serif - &:hover - background-color #4297FE - color white - .ShareButton-url - height 40px - width 100% - position relative - padding 0 5px - .ShareButton-url-input - height 21px - border none - width 143px - float left - border-top-left-radius 3px - border-bottom-left-radius 3px - border 1px solid borderColor - border-right none - .ShareButton-url-button - height 21px - border none - width 30px - float left - background-color #F0F0F0 - border-top-right-radius 3px - border-bottom-right-radius 3px - border 1px solid borderColor - .ShareButton-url-button-tooltip - tooltip() - right 10px - margin-top 5px - &:hover - .ShareButton-url-button-tooltip - opacity 1 - &:active - background-color #4297FE - color white - .ShareButton-url-alert - padding 10px - line-height 16px - - - .ArticleDetail-info-row2 - .tutorial - position fixed - z-index 35 - font-style italic - .TagSelect - margin-top 5px - .TagSelect-tags - white-space nowrap - overflow-x auto - position relative - noSelect() - z-index 30 - background-color #E6E6E6 - clearfix() - .TagSelect-tags-item - background-color transparent - color white - margin 0 2px - padding 0 - height 17px - float left - button.TagSelect-tags-item-remove - display block - float left - background-color transparent - border none - font-size 8px - color white - width 15px - height 17px - text-align center - line-height 12px - padding 0 - margin 0 - border-top solid 1px darken(brandColor, 5%) - border-bottom solid 1px darken(brandColor, 5%) - border-left solid 1px darken(brandColor, 5%) - border-right solid 1px transparent - border-radius left 2px - background-color brandColor - &:hover - background-color lighten(brandColor, 10%) - border-color lighten(brandColor, 10%) - &:focus - background-color lighten(brandColor, 10%) - border-color focusBorderColor - .TagSelect-tags-item-label - background-color brandColor - float left - font-size 12px - border-top solid 1px darken(brandColor, 5%) - border-bottom solid 1px darken(brandColor, 5%) - border-right solid 1px darken(brandColor, 5%) - line-height 15px - padding 0 5px - border-radius right 2px - input.TagSelect-input - background-color transparent - border none - border-bottom 1px solid transparent - outline none - margin 0 2px - transition 0.15s - height 18px - &:focus - border-color focusBorderColor - .TagSelect-suggest - position fixed - width 150px - max-height 150px - background-color white - z-index 50 - border 1px solid borderColor - border-radius 5px - overflow-y auto - &>button - width 100% - display block - padding 0 15px - height 33px - line-height 33px - background-color transparent - border none - text-align left - font-size 14px - &:hover - background-color darken(white, 10%) - .ArticleDetail-panel - position absolute - top 70px - left 10px - right 10px - bottom 10px - overflow-x hidden - overflow-y auto - background-color white - border-radius 5px - border solid 1px lighten(borderColor, 15%) - &>.ArticleDetail-panel-header - display block - height 60px - &>.tutorial - fixed right - z-index 35 - font-style italic - .ArticleDetail-panel-header-mode - z-index 30 - background-color white - absolute top bottom - right 10px - display block - height 33px - margin-top 14px - width 120px - margin-right 15px - border solid 1px borderColor - border-radius 5px - transition width 0.15s - user-select none - &.idle - cursor pointer - &:hover - background-color darken(white, 5%) - .ModeIcon - padding 0 5px - line-height 33px - &.edit - border-color focusBorderColor - input - width 120px - line-height 31px - padding 0 10px - border none - outline none - background-color transparent - font-size 14px - .ModeSelect-options - position fixed - width 120px - z-index 10 - border 1px solid borderColor - border-radius 5px - background-color white - max-height 250px - overflow-y auto - margin-top 5px - .ModeSelect-options-item - height 33px - line-height 33px - cursor pointer - &.active, &:hover.active - background-color brandColor - color white - .ModeIcon - width 30px - text-align center - display inline-block - &:hover - background-color darken(white, 10%) - .ArticleDetail-panel-header-title - absolute left top - right 145px - padding 0 15px - background-color transparent - input - border none - line-height 60px - width 100% - font-size 24px - outline none - .ArticleEditor - absolute left right bottom - top 60px - .ArticleDetail-panel-content-tooltip - absolute bottom right - height 24px - background-color alpha(black, 0.5) - line-height 24px - color white - padding 0 15px - opacity 0 - transition 0.1s - z-index 35 - &:hover .ArticleDetail-panel-content-tooltip - opacity 1 - .MarkdownPreview - absolute top left right bottom - marked() - box-sizing border-box - padding 5px 15px - border-top solid 1px borderColor - overflow-y auto - user-select all - &.empty - color lighten(inactiveTextColor, 10%) - user-select none - font-size 14px - &.lineNumbered - .lineNumber - display block - .CodeEditor - absolute top left right bottom - border-top solid 1px borderColor - min-height 300px - border-bottom-left-radius 5px - border-bottom-right-radius 5px diff --git a/browser/styles/main/ArticleList.styl b/browser/styles/main/ArticleList.styl deleted file mode 100644 index 4e3a63f5..00000000 --- a/browser/styles/main/ArticleList.styl +++ /dev/null @@ -1,105 +0,0 @@ -articleItemHoverBgColor = darken(white, 5%) -articleItemColor = #777 - -.ArticleList - absolute bottom - top 60px - left 200px - width 250px - border-top 1px solid borderColor - border-right 1px solid borderColor - &:focus - border-color focusBorderColor - overflow-y auto - noSelect() - &>div - .ArticleList-item - border solid 2px transparent - position relative - min-height 110px - width 100% - cursor pointer - transition 0.1s - background-color white - padding 0 10px - font-size 12px - .ArticleList-item-top - clearfix() - padding-top 2px - line-height 18px - height 20px - color articleItemColor - font-size 11px - i - margin-right 4px - .folderName - overflow ellipsis - display inline-block - width 120px - .updatedAt - float right - line-height 18px - .unsaved-mark - color brandColor - .ArticleList-item-middle - font-size 16px - position relative - padding-top 6px - height 22px - .mode - position absolute - left 0 - font-size 12px - line-height 16px - .title - position absolute - left 19px - right 0 - overflow ellipsis - small - color #AAA - .ArticleList-item-middle2 - padding-top 8px - pre - color lighten(inactiveTextColor, 10%) - white-space pre-wrap - overflow hidden - height 33px - line-height 14px - font-size 10px - code - font-family Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace - .ArticleList-item-bottom - padding-bottom 5px - .tags - color articleItemColor - line-height 18px - word-wrap break-word - clearfix() - i.fa-tags - display inline - float left - padding 2px 2px 0 0 - height 14px - line-height 13px - a - background-color brandColor - float left - color white - border-radius 2px - padding 1px 5px - margin 2px - height 14px - line-height 13px - font-size 10px - opacity 0.8 - &:hover - opacity 1 - &:hover, &.hover - background-color articleItemHoverBgColor - &:active, &.active - background-color white - &:active, &.active - border-color brandBorderColor - .divider - border-bottom solid 1px borderColor diff --git a/browser/styles/main/ArticleNavigator.styl b/browser/styles/main/ArticleNavigator.styl deleted file mode 100644 index 90835f51..00000000 --- a/browser/styles/main/ArticleNavigator.styl +++ /dev/null @@ -1,213 +0,0 @@ -articleNavBgColor = #353535 -articleCount = #999 - -.ArticleNavigator - background-color articleNavBgColor - absolute top bottom left - width 200px - border-right 1px solid borderColor - color white - user-select none - .userInfo - height 60px - display block - box-sizing content-box - border-bottom 1px solid borderColor - .userProfileName - color brandColor - font-size 28px - padding 6px 37px 0 10px - white-space nowrap - text-overflow ellipsis - overflow hidden - .userName - color white - padding-left 20px - margin-top 3px - .tutorial - position fixed - z-index 35 - top 0 - left 0 - pointer-event none - font-style italic - transition 0.1s - &.hide - opacity 0 - .settingBtn - width 22px - height 22px - line-height 22px - border-radius 11px - position absolute - top 19px - right 14px - color white - padding 0 - background-color transparent - border 1px solid white - z-index 31 - .tooltip - tooltip() - margin-top -5px - margin-left 10px - &:hover - .tooltip - opacity 1 - &:active - background-color brandColor - border-color brandColor - .ArticleNavigator-unsaved - position absolute - top 100px - width 100% - height 225px - transition opacity 0.2s ease-in-out - &.hide - opacity 0.2 - .ArticleNavigator-unsaved-header - border-bottom 1px solid alpha(borderColor, 0.5) - padding-bottom 5px - clearfix() - position relative - padding-left 10px - font-size 18px - line-height 22px - .ArticleNavigator-unsaved-list - height 165px - padding 5px 0 - overflow-y scroll - .ArticleNavigator-unsaved-list-item - height 33px - padding-left 15px - clearfix() - transition 0.1s - cursor pointer - overflow hidden - &:hover - background-color alpha(white, 0.05) - &.active, &:active - background-color alpha(lighten(brandColor, 25%), 70%) - .ArticleNavigator-unsaved-list-item-label - float left - width 151px - line-height 33px - overflow ellipsis - .ArticleNavigator-unsaved-list-item-label-untitled - color inactiveTextColor - .ArticleNavigator-unsaved-list-item-discard-button - float right - width 33px - line-height 30px - height 33px - border none - background-color transparent - color white - font-size 18px - opacity 0.5 - &:hover - opacity 1 - .ArticleNavigator-unsaved-list-empty - height 33px - padding-left 15px - color alpha(white, 0.4) - transition 0.1s - line-height 33px - &:hover - color alpha(white, 0.6) - .ArticleNavigator-unsaved-control - absolute bottom - height 33px - border-top 1px solid alpha(borderColor, 0.5) - width 100% - .ArticleNavigator-unsaved-control-save-all-button - border none - background-color transparent - font-size 14px - color brandColor - padding-left 15px - width 100% - height 33px - text-align left - &:hover - color lighten(brandColor, 15%) - background-color alpha(white, 0.05) - &:active - color white - &:disabled - color alpha(brandColor, 0.5) - &:hover - color alpha(lighten(brandColor, 25%), 0.5) - background-color transparent - - - .ArticleNavigator-folders - absolute bottom - top 365px - width 100% - transition top 0.15s ease-in-out - background-color articleNavBgColor - .tutorial - position fixed - z-index 35 - font-style italic - &.expand - top 100px - .ArticleNavigator-folders-header - border-bottom 1px solid alpha(borderColor, 0.5) - padding-bottom 5px - clearfix() - position relative - z-index 30 - .title - float left - padding-left 10px - font-size 18px - line-height 22px - .addBtn - float right - margin-right 15px - width 22px - height 22px - font-size 10px - padding 0 - line-height 22px - border 1px solid white - border-radius 11px - background-color transparent - color white - padding 0 - font-weight bold - .tooltip - tooltip() - margin-top -6px - margin-left 11px - &:hover - .tooltip - opacity 1 - &:active - background-color brandColor - border-color brandColor - .folderList - absolute bottom - top 33px - overflow-y auto - .folderList button - height 33px - width 199px - border none - text-align left - font-size 14px - background-color transparent - color white - padding-left 15px - overflow ellipsis - &:hover - background-color alpha(white, 0.05) - &.active, &:active - background-color alpha(lighten(brandColor, 25%), 70%) - .articleCount - color white - .articleCount - color articleCount - font-size 12px diff --git a/browser/styles/main/index.styl b/browser/styles/main/index.styl index 3c532b11..46d6b19c 100644 --- a/browser/styles/main/index.styl +++ b/browser/styles/main/index.styl @@ -2,9 +2,6 @@ @import '../mixins/*' global-reset() @import '../shared/*' -@import './ArticleNavigator' -@import './ArticleList' -@import './ArticleDetail' @import './modal/*' @import '../theme/*' @@ -89,19 +86,3 @@ textarea.block-input #content fullsize() - -.Main - .appUpdateButton - position fixed - z-index 2000 - bottom 5px - right 53px - padding 10px 15px - border none - border-radius 5px - background-color brandColor - color white - opacity 0.7 - &:hover - opacity 1 - background-color lighten(brandColor, 10%)