1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-14 10:16:26 +00:00

Compare commits

...

40 Commits

Author SHA1 Message Date
Dick Choi
fd3d1607a4 Merge pull request #11 from brpaz/master
Fix case on style import
2016-04-02 23:38:26 +09:00
Bruno Paz
abbc0fbcf1 Fix case on style import 2016-04-02 14:09:23 +01:00
Rokt33r
499c3f2e13 bump up version to 0.5.8 and upgrade electron packager 2016-04-02 20:45:45 +09:00
Rokt33r
627845f6e4 fix file drop behaviour 2016-04-02 20:15:14 +09:00
Rokt33r
07eea76057 fix editor selection bug 2016-04-02 20:14:47 +09:00
Rokt33r
fecc4e9b79 bump up to v0.5.7 2016-03-28 01:26:11 +09:00
Rokt33r
58e9302f15 remove email address 2016-03-28 01:09:43 +09:00
Rokt33r
86f649fab1 v0.5.6 2016-03-27 23:18:54 +09:00
Dick Choi
9ac0becfb2 Update readme.md 2016-03-26 03:53:13 +09:00
Rokt33r
f75e872415 configuring zoomfactor with Ctrl + Wheelscroll only works on windows and linux 2016-03-16 08:08:42 +09:00
Rokt33r
aef0712165 fix style bug of TagSelect 2016-03-16 08:02:46 +09:00
Rokt33r
bed4b7fd27 bump up electron version to 0.36.11 2016-03-15 16:17:39 +09:00
Rokt33r
b53ff5daf3 fix again(never break long tag) 2016-03-15 16:09:17 +09:00
Rokt33r
bb0872b4fc tags in ArticleList will be wrapped properly 2016-03-15 15:51:35 +09:00
Rokt33r
b65101f4be fix emacs key binding 2016-03-15 14:05:33 +09:00
Rokt33r
593d242a4c ctrl + wheel to change zoom factor 2016-03-15 02:24:28 +09:00
Rokt33r
db7f339c34 set Editor fontFamily to Title input 2016-03-15 01:32:31 +09:00
Rokt33r
9f3575a874 Merge branch 'master' into v0.5.5
* master:
  add Link of Trello Kanban to readme.md
2016-03-13 23:04:08 +09:00
Rokt33r
1c9c59c512 add Link of Trello Kanban to readme.md 2016-03-13 23:03:50 +09:00
Rokt33r
127202b831 Update contributing 2016-03-10 20:32:59 +09:00
Dick Choi
4f8a04ed21 Merge pull request #1 from dojineko/quick-search
Top search will be focused when Main window showed by hotkey.
2016-03-10 19:44:57 +09:00
dojineko
63b2e0560b Focus to search box, when hotkey pushed 2016-03-10 08:49:44 +09:00
Rokt33r
6907cf9972 The notification of 'Copy to Clipboard' must be slient 2016-03-09 19:43:34 +09:00
Rokt33r
d4f8d1498d modify window API to fit the new version of electron 2016-03-09 19:42:45 +09:00
Rokt33r
0952e4a664 bump up version of electron 2016-03-09 03:16:40 +09:00
Rokt33r
983bfb7adf fix contributing 2016-03-09 02:50:33 +09:00
Rokt33r
d7aaf5e210 add contributing 2016-03-09 02:45:07 +09:00
Rokt33r
50281132ad modify readme 2016-03-09 02:44:57 +09:00
Rokt33r
6a2b22015e modify LICENSE and readme 2016-03-09 02:44:38 +09:00
Rokt33r
0fe83a0583 fix anchor target 2016-01-25 10:28:46 +09:00
Rokt33r
ce74e69480 check href exists 2016-01-22 08:00:26 +09:00
Rokt33r
ddea2aeb22 fix verticla-align of img in anchor 2016-01-22 07:58:25 +09:00
Rokt33r
7bbe69cce9 Merge branch 'v0.5.4'
* v0.5.4:
  bump up version to v0.5.4
  emit ARTICLE_CREATE when new post clicked
  update h1 style of markdown
  fix go to line end
  clean old code
  fix sanitizing bug in Code block
  done but bugged

Conflicts:
	package.json
2016-01-22 03:01:13 +09:00
Rokt33r
e921e30d64 bump up version to v0.5.4 2016-01-22 02:59:35 +09:00
Rokt33r
cd4f9d8bb4 emit ARTICLE_CREATE when new post clicked 2016-01-22 02:58:06 +09:00
Rokt33r
a0553788b6 update h1 style of markdown 2016-01-22 02:55:02 +09:00
Rokt33r
1a183d78af fix go to line end 2016-01-21 08:29:09 +09:00
Rokt33r
cabcaa892c clean old code 2016-01-21 05:50:53 +09:00
Rokt33r
01c9d62a2b fix sanitizing bug in Code block 2016-01-21 05:50:40 +09:00
Rokt33r
81441a0895 done but bugged 2016-01-19 20:11:38 +09:00
27 changed files with 325 additions and 246 deletions

18
LICENSE
View File

@@ -1,2 +1,16 @@
本製品をインストール、または使用することによって、お客様は利用規約( Boostnote - the simplest note app
https://b00st.io/regulations.htmlより拘束されることに承諾されたものとします。利用規約に同意されない場合、Boostnoteは、お客様に本製品のインストール、使用のいずれも許諾できません。
Copyright (C) 2016 MAISIN&CO.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@@ -35,6 +35,52 @@ export default class CodeEditor extends React.Component {
if (this.props.onBlur) this.props.onBlur(e) if (this.props.onBlur) this.props.onBlur(e)
} }
this.killedBuffer = ''
this.execHandler = (e) => {
console.log(e.command.name)
switch (e.command.name) {
case 'gotolinestart':
e.preventDefault()
{
let position = this.editor.getCursorPosition()
this.editor.navigateTo(position.row, 0)
}
break
case 'gotolineend':
e.preventDefault()
let position = this.editor.getCursorPosition()
this.editor.navigateTo(position.row, this.editor.getSession().getLine(position.row).length)
break
case 'jumptomatching':
e.preventDefault()
this.editor.navigateUp()
break
case 'removetolineend':
e.preventDefault()
let range = this.editor.getSelectionRange()
let session = this.editor.getSession()
if (range.isEmpty()) {
range.setEnd(range.start.row, session.getLine(range.start.row).length)
this.killedBuffer = session.getTextRange(range)
if (this.killedBuffer.length > 0) {
console.log('remove to lineend')
session.remove(range)
} else {
if (session.getLength() === range.start.row) {
return
}
range.setStart(range.start.row, range.end.col)
range.setEnd(range.start.row + 1, 0)
this.killedBuffer = '\n'
session.remove(range)
}
} else {
this.killedBuffer = session.getTextRange(range)
session.remove(range)
}
}
}
this.afterExecHandler = (e) => { this.afterExecHandler = (e) => {
switch (e.command.name) { switch (e.command.name) {
case 'find': case 'find':
@@ -42,6 +88,7 @@ export default class CodeEditor extends React.Component {
el.removeEventListener('blur', this.blurHandler) el.removeEventListener('blur', this.blurHandler)
el.addEventListener('blur', this.blurHandler) el.addEventListener('blur', this.blurHandler)
}) })
break
} }
} }
@@ -83,6 +130,14 @@ export default class CodeEditor extends React.Component {
}, },
readOnly: true readOnly: true
}) })
editor.commands.addCommand({
name: 'Emacs cursor up',
bindKey: {mac: 'Ctrl-Y'},
exec: function (editor) {
editor.insert(this.killedBuffer)
}.bind(this),
readOnly: true
})
editor.commands.addCommand({ editor.commands.addCommand({
name: 'Focus title', name: 'Focus title',
bindKey: {win: 'Esc', mac: 'Esc'}, bindKey: {win: 'Esc', mac: 'Esc'},
@@ -96,6 +151,7 @@ export default class CodeEditor extends React.Component {
readOnly: true readOnly: true
}) })
editor.commands.on('exec', this.execHandler)
editor.commands.on('afterExec', this.afterExecHandler) editor.commands.on('afterExec', this.afterExecHandler)
var session = editor.getSession() var session = editor.getSession()
@@ -120,6 +176,7 @@ export default class CodeEditor extends React.Component {
ipc.removeListener('config-apply', this.configApplyHandler) ipc.removeListener('config-apply', this.configApplyHandler)
this.editor.getSession().removeListener('change', this.changeHandler) this.editor.getSession().removeListener('change', this.changeHandler)
this.editor.removeListener('blur', this.blurHandler) this.editor.removeListener('blur', this.blurHandler)
this.editor.commands.removeListener('exec', this.execHandler)
this.editor.commands.removeListener('afterExec', this.afterExecHandler) this.editor.commands.removeListener('afterExec', this.afterExecHandler)
} }

View File

@@ -49,13 +49,13 @@ const sanitizeOpts = {
} }
function handleAnchorClick (e) { function handleAnchorClick (e) {
if (e.target.attributes.href && e.target.attributes.href.nodeValue.match(/#.+/)) { if (this.attributes.href && this.attributes.href.nodeValue.match(/^#.+/)) {
return return
} }
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
let href = e.target.href let href = this.href
if (href.match(/^http:\/\/|https:\/\/|mailto:\/\//)) { if (href && href.match(/^http:\/\/|https:\/\/|mailto:\/\//)) {
shell.openExternal(href) shell.openExternal(href)
} }
} }

View File

@@ -29,7 +29,6 @@ function hideFinder () {
function notify (title, options) { function notify (title, options) {
if (process.platform === 'win32') { if (process.platform === 'win32') {
options.icon = path.join('file://', global.__dirname, '../../resources/app.png') options.icon = path.join('file://', global.__dirname, '../../resources/app.png')
options.silent = false
} }
return new window.Notification(title, options) return new window.Notification(title, options)
} }
@@ -96,7 +95,8 @@ class FinderMain extends React.Component {
ipcRenderer.send('copy-finder') ipcRenderer.send('copy-finder')
notify('Saved to Clipboard!', { notify('Saved to Clipboard!', {
body: 'Paste it wherever you want!' body: 'Paste it wherever you want!',
silent: true
}) })
hideFinder() hideFinder()
} }

View File

@@ -108,7 +108,7 @@ export function emit (type, data = {}) {
} }
// Count ARTICLE_CREATE and ARTICLE_UPDATE again by syntax // Count ARTICLE_CREATE and ARTICLE_UPDATE again by syntax
if ((type === 'ARTICLE_CREATE' || type === 'ARTICLE_UPDATE') && data.mode != null) { if (type === 'ARTICLE_UPDATE' && data.mode != null) {
let recordKey = type + '_BY_SYNTAX' let recordKey = type + '_BY_SYNTAX'
if (todayRecord[recordKey] == null) todayRecord[recordKey] = {} if (todayRecord[recordKey] == null) todayRecord[recordKey] = {}

View File

@@ -14,7 +14,7 @@ var md = markdownit({
return hljs.highlight(lang, str).value return hljs.highlight(lang, str).value
} catch (e) {} } catch (e) {}
} }
return str return str.replace(/\&/g, '&amp;').replace(/\</g, '&lt;').replace(/\>/g, '&gt;').replace(/\"/g, '&quot;')
} }
}) })
md.use(emoji, { md.use(emoji, {

View File

@@ -32,7 +32,6 @@ export default class ArticleEditor extends React.Component {
} }
componentDidMount () { componentDidMount () {
console.log(this.state.switchPreview)
ipc.on('config-apply', this.configApplyHandler) ipc.on('config-apply', this.configApplyHandler)
} }
@@ -126,6 +125,12 @@ export default class ArticleEditor extends React.Component {
} }
handleMouseUp (e) { handleMouseUp (e) {
let { article } = this.props
let showPreview = article.mode === 'markdown' && this.state.status === PREVIEW_MODE
if (!showPreview) {
return false
}
switch (this.state.switchPreview) { switch (this.state.switchPreview) {
case 'blur': case 'blur':
switch (e.button) { switch (e.button) {
@@ -145,6 +150,12 @@ export default class ArticleEditor extends React.Component {
} }
handleMouseMove (e) { handleMouseMove (e) {
let { article } = this.props
let showPreview = article.mode === 'markdown' && this.state.status === PREVIEW_MODE
if (!showPreview) {
return false
}
if (this.state.switchPreview === 'blur' && this.isMouseDown) { if (this.state.switchPreview === 'blur' && this.isMouseDown) {
this.moveCount++ this.moveCount++
if (this.moveCount > 5) { if (this.moveCount > 5) {
@@ -154,6 +165,12 @@ export default class ArticleEditor extends React.Component {
} }
handleMouseDowm (e) { handleMouseDowm (e) {
let { article } = this.props
let showPreview = article.mode === 'markdown' && this.state.status === PREVIEW_MODE
if (!showPreview) {
return false
}
switch (this.state.switchPreview) { switch (this.state.switchPreview) {
case 'blur': case 'blur':
switch (e.button) { switch (e.button) {

View File

@@ -4,10 +4,7 @@ import moment from 'moment'
import _ from 'lodash' import _ from 'lodash'
import { import {
switchFolder, switchFolder,
updateArticle, updateArticle
// cacheArticle,
// saveArticle,
// uncacheArticle
} from '../../actions' } from '../../actions'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import TagSelect from 'browser/components/TagSelect' import TagSelect from 'browser/components/TagSelect'
@@ -18,22 +15,12 @@ import DeleteArticleModal from '../../modal/DeleteArticleModal'
import ArticleEditor from './ArticleEditor' import ArticleEditor from './ArticleEditor'
const electron = require('electron') const electron = require('electron')
const ipc = electron.ipcRenderer const ipc = electron.ipcRenderer
import fetchConfig from 'browser/lib/fetchConfig'
// const remote = electron.remote let config = fetchConfig()
// const { Menu, MenuItem } = remote ipc.on('config-apply', function (e, newConfig) {
// const othersMenu = new Menu() config = newConfig
// othersMenu.append(new MenuItem({ })
// label: 'Delete Post',
// click: function () {
// remote.getCurrentWebContents().send('detail-delete')
// }
// }))
// othersMenu.append(new MenuItem({
// label: 'Discard Change',
// click: function (item) {
// remote.getCurrentWebContents().send('detail-uncache')
// }
// }))
const BRAND_COLOR = '#18AF90' const BRAND_COLOR = '#18AF90'
const OSX = global.process.platform === 'darwin' const OSX = global.process.platform === 'darwin'
@@ -80,10 +67,6 @@ export default class ArticleDetail extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
this.saveHandler = e => {
if (isModalOpen()) return true
this.handleSaveButtonClick()
}
this.deleteHandler = e => { this.deleteHandler = e => {
if (isModalOpen()) return true if (isModalOpen()) return true
this.handleDeleteButtonClick() this.handleDeleteButtonClick()
@@ -106,10 +89,12 @@ export default class ArticleDetail extends React.Component {
if (isModalOpen()) return true if (isModalOpen()) return true
if (this.refs.editor) this.refs.editor.switchPreviewMode() if (this.refs.editor) this.refs.editor.switchPreviewMode()
} }
this.configApplyHandler = (e, config) => this.handleConfigApply(e, config)
this.state = { this.state = {
article: Object.assign({content: ''}, props.activeArticle), article: Object.assign({content: ''}, props.activeArticle),
openShareDropdown: false openShareDropdown: false,
fontFamily: config['editor-font-family']
} }
} }
@@ -119,18 +104,17 @@ export default class ArticleDetail extends React.Component {
e.stopPropagation() e.stopPropagation()
} }
// ipc.on('detail-save', this.saveHandler)
ipc.on('detail-delete', this.deleteHandler) ipc.on('detail-delete', this.deleteHandler)
ipc.on('detail-uncache', this.uncacheHandler) ipc.on('detail-uncache', this.uncacheHandler)
ipc.on('detail-title', this.titleHandler) ipc.on('detail-title', this.titleHandler)
ipc.on('detail-edit', this.editHandler) ipc.on('detail-edit', this.editHandler)
ipc.on('detail-preview', this.previewHandler) ipc.on('detail-preview', this.previewHandler)
ipc.on('config-apply', this.configApplyHandler)
} }
componentWillUnmount () { componentWillUnmount () {
clearInterval(this.refreshTimer) clearInterval(this.refreshTimer)
// ipc.removeListener('detail-save', this.saveHandler)
ipc.removeListener('detail-delete', this.deleteHandler) ipc.removeListener('detail-delete', this.deleteHandler)
ipc.removeListener('detail-uncache', this.uncacheHandler) ipc.removeListener('detail-uncache', this.uncacheHandler)
ipc.removeListener('detail-title', this.titleHandler) ipc.removeListener('detail-title', this.titleHandler)
@@ -148,6 +132,12 @@ export default class ArticleDetail extends React.Component {
} }
} }
handleConfigApply (e, config) {
this.setState({
fontFamily: config['editor-font-family']
})
}
renderEmpty () { renderEmpty () {
return ( return (
<div className='ArticleDetail empty'> <div className='ArticleDetail empty'>
@@ -334,6 +324,9 @@ export default class ArticleDetail extends React.Component {
ref='title' ref='title'
value={activeArticle.title} value={activeArticle.title}
onChange={e => this.handleTitleChange(e)} onChange={e => this.handleTitleChange(e)}
style={{
fontFamily: this.state.fontFamily
}}
/> />
</div> </div>
<ModeSelect <ModeSelect

View File

@@ -4,6 +4,7 @@ import ExternalLink from 'browser/components/ExternalLink'
import { setSearchFilter, clearSearch, toggleTutorial, saveArticle, switchFolder } from '../actions' import { setSearchFilter, clearSearch, toggleTutorial, saveArticle, switchFolder } from '../actions'
import { isModalOpen } from 'browser/lib/modal' import { isModalOpen } from 'browser/lib/modal'
import keygen from 'browser/lib/keygen' import keygen from 'browser/lib/keygen'
import activityRecord from 'browser/lib/activityRecord'
const electron = require('electron') const electron = require('electron')
const remote = electron.remote const remote = electron.remote
@@ -167,6 +168,7 @@ export default class ArticleTopBar extends React.Component {
dispatch(saveArticle(newArticle.key, newArticle, true)) dispatch(saveArticle(newArticle.key, newArticle, true))
if (isFolderFilterApplied) dispatch(switchFolder(targetFolders[0].name)) if (isFolderFilterApplied) dispatch(switchFolder(targetFolders[0].name))
remote.getCurrentWebContents().send('detail-title') remote.getCurrentWebContents().send('detail-title')
activityRecord.emit('ARTICLE_CREATE')
} }
handleTutorialButtonClick (e) { handleTutorialButtonClick (e) {
@@ -229,8 +231,8 @@ export default class ArticleTopBar extends React.Component {
<ExternalLink className='ArticleTopBar-right-links-button-dropdown-item' href='https://b00st.io'> <ExternalLink className='ArticleTopBar-right-links-button-dropdown-item' href='https://b00st.io'>
<i className='fa fa-fw fa-home'/>Boost official page <i className='fa fa-fw fa-home'/>Boost official page
</ExternalLink> </ExternalLink>
<ExternalLink className='ArticleTopBar-right-links-button-dropdown-item' href='https://github.com/BoostIO/boost-app-discussions/issues'> <ExternalLink className='ArticleTopBar-right-links-button-dropdown-item' href='https://github.com/BoostIO/Boostnote/issues'>
<i className='fa fa-fw fa-bullhorn'/> Discuss <i className='fa fa-fw fa-github'/> Issues
</ExternalLink> </ExternalLink>
</div> </div>
) )

View File

@@ -19,9 +19,27 @@ export default class MainContainer extends React.Component {
ipc.send('update-app', 'Deal with it.') ipc.send('update-app', 'Deal with it.')
} }
handleWheel (e) {
if (e.ctrlKey && global.process.platform !== 'darwin') {
if (window.document.body.style.zoom == null) {
window.document.body.style.zoom = 1
}
let zoom = Number(window.document.body.style.zoom)
if (e.deltaY > 0 && zoom < 4) {
document.body.style.zoom = zoom + 0.05
} else if (e.deltaY < 0 && zoom > 0.5) {
document.body.style.zoom = zoom - 0.05
}
}
}
render () { render () {
return ( return (
<div className='Main'> <div
className='Main'
onWheel={(e) => this.handleWheel(e)}
>
{this.state.updateAvailable ? ( {this.state.updateAvailable ? (
<button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button> <button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button>
) : null} ) : null}

View File

@@ -5,7 +5,7 @@ import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
require('../styles/main/index.styl') require('../styles/main/index.styl')
import { openModal } from 'browser/lib/modal' import { openModal } from 'browser/lib/modal'
import Tutorial from './modal/Tutorial' import OSSAnnounceModal from './modal/OSSAnnounceModal'
import activityRecord from 'browser/lib/activityRecord' import activityRecord from 'browser/lib/activityRecord'
const electron = require('electron') const electron = require('electron')
const ipc = electron.ipcRenderer const ipc = electron.ipcRenderer
@@ -25,6 +25,15 @@ window.addEventListener('online', function () {
ipc.send('check-update', 'check-update') ipc.send('check-update', 'check-update')
}) })
document.addEventListener('drop', function (e) {
e.preventDefault()
e.stopPropagation()
})
document.addEventListener('dragover', function (e) {
e.preventDefault()
e.stopPropagation()
})
function notify (title, options) { function notify (title, options) {
if (process.platform === 'win32') { if (process.platform === 'win32') {
options.icon = path.join('file://', global.__dirname, '../../resources/app.png') options.icon = path.join('file://', global.__dirname, '../../resources/app.png')
@@ -59,9 +68,10 @@ ReactDOM.render((
loadingCover.parentNode.removeChild(loadingCover) loadingCover.parentNode.removeChild(loadingCover)
let status = JSON.parse(localStorage.getItem('status')) let status = JSON.parse(localStorage.getItem('status'))
if (status == null) status = {} if (status == null) status = {}
if (!status.introWatched) {
openModal(Tutorial) if (!status.ossAnnounceWatched) {
status.introWatched = true openModal(OSSAnnounceModal)
status.ossAnnounceWatched = true
localStorage.setItem('status', JSON.stringify(status)) localStorage.setItem('status', JSON.stringify(status))
} }
}) })

View File

@@ -0,0 +1,29 @@
import React, { PropTypes } from 'react'
import ExternalLink from 'browser/components/ExternalLink'
export default class OSSAnnounceModal extends React.Component {
handleCloseBtnClick (e) {
this.props.close()
}
render () {
return (
<div className='OSSAnnounceModal modal'>
<div className='OSSAnnounceModal-title'>Boostnote has been Open-sourced</div>
<ExternalLink className='OSSAnnounceModal-link' href='https://github.com/BoostIO/Boostnote'>
https://github.com/BoostIO/Boostnote
</ExternalLink>
<button
className='OSSAnnounceModal-closeBtn'
onClick={(e) => this.handleCloseBtnClick(e)}
>Close</button>
</div>
)
}
}
OSSAnnounceModal.propTypes = {
close: PropTypes.func
}

View File

@@ -1,122 +1,23 @@
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import clientKey from 'browser/lib/clientKey'
import linkState from 'browser/lib/linkState' import linkState from 'browser/lib/linkState'
import _ from 'lodash' import ExternalLink from 'browser/components/ExternalLink'
import { request, SERVER_URL } from 'browser/lib/api'
const FORM_MODE = 'FORM_MODE'
const DONE_MODE = 'DONE_MODE'
export default class ContactTab extends React.Component { export default class ContactTab extends React.Component {
constructor (props) {
super(props)
this.state = {
title: '',
content: '',
email: '',
mode: FORM_MODE,
alert: null
}
}
componentDidMount () { componentDidMount () {
let titleInput = ReactDOM.findDOMNode(this.refs.title) let titleInput = ReactDOM.findDOMNode(this.refs.title)
if (titleInput != null) titleInput.focus() if (titleInput != null) titleInput.focus()
} }
handleBackButtonClick (e) {
this.setState({
mode: FORM_MODE
})
}
handleSendButtonClick (e) {
let input = _.pick(this.state, ['title', 'content', 'email'])
input.clientKey = clientKey.get()
this.setState({
alert: {
type: 'info',
message: 'Sending...'
}
}, () => {
request.post(SERVER_URL + 'apis/inquiry')
.send(input)
.then(res => {
console.log('sent')
this.setState({
title: '',
content: '',
mode: DONE_MODE,
alert: null
})
})
.catch(err => {
if (err.code === 'ECONNREFUSED') {
this.setState({
alert: {
type: 'error',
message: 'Can\'t connect to API server.'
}
})
} else {
console.error(err)
this.setState({
alert: {
type: 'error',
message: err.message
}
})
}
})
})
}
render () { render () {
switch (this.state.mode) { return (
case DONE_MODE: <div className='ContactTab content'>
return ( <div className='title'>Contact</div>
<div className='ContactTab content done'> <p>
<div className='message'> - Issues: <ExternalLink href='https://github.com/BoostIO/Boostnote/issues'>https://github.com/BoostIO/Boostnote/issues</ExternalLink>
<i className='checkIcon fa fa-check-circle'/><br/> </p>
Your message has been sent successfully!! </div>
</div> )
<div className='control'>
<button onClick={e => this.handleBackButtonClick(e)}>Back to Contact form</button>
</div>
</div>
)
case FORM_MODE:
default:
let alertElement = this.state.alert != null
? (
<div className={'alert ' + this.state.alert.type}>{this.state.alert.message}</div>
)
: null
return (
<div className='ContactTab content form'>
<div className='title'>Contact form</div>
<div className='description'>
Your feedback is highly appreciated and will help us to improve our app. :D
</div>
<div className='iptGroup'>
<input ref='title' valueLink={this.linkState('title')} placeholder='Title' type='text'/>
</div>
<div className='iptGroup'>
<textarea valueLink={this.linkState('content')} placeholder='Content'/>
</div>
<div className='iptGroup'>
<input valueLink={this.linkState('email')} placeholder='E-mail (Optional)' type='email'/>
</div>
<div className='formControl'>
<button onClick={e => this.handleSendButtonClick(e)} className='primary'>Send</button>
{alertElement}
</div>
</div>
)
}
} }
} }

View File

@@ -257,9 +257,10 @@ infoButton()
width 150px width 150px
max-height 150px max-height 150px
background-color white background-color white
z-index 5 z-index 50
border 1px solid borderColor border 1px solid borderColor
border-radius 5px border-radius 5px
overflow-y auto
&>button &>button
width 100% width 100%
display block display block

View File

@@ -16,7 +16,7 @@ articleItemColor = #777
.ArticleList-item .ArticleList-item
border solid 2px transparent border solid 2px transparent
position relative position relative
height 110px min-height 110px
width 100% width 100%
cursor pointer cursor pointer
transition 0.1s transition 0.1s
@@ -68,18 +68,27 @@ articleItemColor = #777
code code
font-family Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace font-family Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace
.ArticleList-item-bottom .ArticleList-item-bottom
overflow-x auto padding-bottom 5px
white-space nowrap
padding-top 6px
.tags .tags
color articleItemColor color articleItemColor
height 14px 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 a
background-color brandColor background-color brandColor
float left
color white color white
border-radius 2px border-radius 2px
padding 1px 5px padding 1px 5px
margin 2px margin 2px
height 14px
line-height 13px
font-size 10px font-size 10px
opacity 0.8 opacity 0.8
&:hover &:hover

View File

@@ -4,7 +4,7 @@
global-reset() global-reset()
@import '../shared/*' @import '../shared/*'
@import './ArticleNavigator' @import './ArticleNavigator'
@import './ArticleTopbar' @import './ArticleTopBar'
@import './ArticleList' @import './ArticleList'
@import './ArticleDetail' @import './ArticleDetail'
@import './modal/*' @import './modal/*'
@@ -126,3 +126,28 @@ textarea.block-input
margin-left -107px margin-left -107px
&:hover .tooltip &:hover .tooltip
opacity 1 opacity 1
.OSSAnnounceModal
height 250
text-align center
.OSSAnnounceModal-title
font-size 32px
padding 45px 0
.OSSAnnounceModal-link
display block
font-size 20px
margin 25px 0 65px
.OSSAnnounceModal-closeBtn
display block
margin 0 auto
border none
border-radius 5px
width 150px
height 33px
background-color brandColor
color white
opacity 0.7
&:hover
opacity 1
background-color lighten(brandColor, 10%)

View File

@@ -177,69 +177,14 @@ iptFocusBorderColor = #369DCD
color errorTextColor color errorTextColor
background-color errorBackgroundColor background-color errorBackgroundColor
&.ContactTab &.ContactTab
&.done padding 10px
.message .title
margin-top 75px font-size 18px
margin-bottom 15px color brandColor
text-align center margin-top 10px
font-size 22px margin-bottom 10px
.checkIcon p
margin-bottom 15px line-height 2
font-size 144px
color brandColor
text-align center
.control
text-align center
button
border solid 1px borderColor
border-radius 5px
background-color white
padding 15px 15px
font-size 14px
&:hover
background-color darken(white, 10%)
&.form
padding 10px
.title
font-size 18px
color brandColor
margin-top 10px
margin-bottom 10px
.description
margin-bottom 15px
.iptGroup
margin-bottom 10px
input, textarea
border-radius 5px
border 1px solid borderColor
font-size 14px
outline none
padding 10px 15px
width 100%
&:focus
border-color iptFocusBorderColor
textarea
resize vertical
min-height 150px
.formControl
clearfix()
.alert
float right
padding 10px 15px
margin 0 5px 0
font-size 14px
line-height normal
button
padding 10px 15px
background-color brandColor
color white
font-size 14px
border-radius 5px
border none
float right
&:hover
background-color lighten(brandColor, 10%)
&.AppSettingTab &.AppSettingTab
.description .description
marked() marked()

View File

@@ -26,6 +26,8 @@ marked()
margin -5px margin -5px
transition .1s transition .1s
display inline-block display inline-block
img
vertical-align sub
&:hover &:hover
color lighten(brandColor, 5%) color lighten(brandColor, 5%)
text-decoration underline text-decoration underline
@@ -48,12 +50,12 @@ marked()
*:not(a.lineAnchor) + h1, *:not(a.lineAnchor) + h2, *:not(a.lineAnchor) + h3, *:not(a.lineAnchor) + h4, *:not(a.lineAnchor) + h5, *:not(a.lineAnchor) + h6 *:not(a.lineAnchor) + h1, *:not(a.lineAnchor) + h2, *:not(a.lineAnchor) + h3, *:not(a.lineAnchor) + h4, *:not(a.lineAnchor) + h5, *:not(a.lineAnchor) + h6
margin-top 25px margin-top 25px
h1 h1
font-size 2em font-size 1.8em
border-bottom solid 2px borderColor border-bottom solid 2px borderColor
line-height 2.333em line-height 2em
h2 h2
font-size 1.66em font-size 1.66em
line-height 2.07em line-height 1.8em
h3 h3
font-size 1.33em font-size 1.33em
line-height 1.6625em line-height 1.6625em

35
contributing.md Normal file
View File

@@ -0,0 +1,35 @@
# Contributing to Boostnote
> English below.
## About Pull Request
### やり方
現状特に`dev`ブランチを用意しないつもりなので、最新VersionのブランチにPullrequestを送ってください。
### Pull requsetの著作権
Pull requestをすることはその変化分のコードの著作権をMAISIN&CO.に譲渡することに同意することになります。
アプリケーションのLicenseのをいつでも変える選択肢を残したいからです。
しかし、これはいずれかBoostnoteが有料の商用アプリになる可能性がある話ではありません。
もし、このアプリケーションで金を稼ごうとするならBoostnote専用のCloud storageの提供やMobile appとの連動、何か特殊なプレミアム機能の提供など形になると思います。
現在考えられているのは、GPL v3の場合、他のライセンスとの互換が不可能であるため、もしより自由なLicense(BSD, MIT)に変える時に改めて著作権者としてライセンスし直す選択肢を残したいぐらいのイメージです。
---
# Contributing to Boostnote(ENG)
## About Pull Request
### How to
Make a new PR to the branch named latest version. This is because there is no `dev` branch currently.
### Copyright of Pull Request
If you make a pull request, It means you agree to transfer the copyright of the code changes to MAISIN&CO.
It doesn't mean Boostnote will become a paid app. If we want to earn some money, We will try other way, which is some kind of cloud storage, Mobile app integration or some SPECIAL features.
Because GPL v3 is too strict to be compatible with any other License, We thought this is needed to replace the license with much freer one(like BSD, MIT) somewhen.

View File

@@ -79,12 +79,12 @@ var config = {
show: false, show: false,
frame: false, frame: false,
resizable: false, resizable: false,
'zoom-factor': 1.0, zoomFactor: 1.0,
'web-preferences': { webPreferences: {
'overlay-scrollbars': true, blinkFeatures: 'OverlayScrollbars'
'skip-taskbar': true
}, },
'standard-window': false skipTaskbar: true,
standardWindow: false
} }
if (process.platform === 'darwin') { if (process.platform === 'darwin') {

View File

@@ -39,7 +39,7 @@
var scriptEl=document.createElement('script') var scriptEl=document.createElement('script')
scriptEl.setAttribute("type","text/javascript") scriptEl.setAttribute("type","text/javascript")
scriptEl.setAttribute("src", scriptUrl) scriptEl.setAttribute("src", scriptUrl)
document.getElementsByTagName("head")[0].appendChild(scriptEl) document.body.appendChild(scriptEl)
</script> </script>
</body> </body>
</html> </html>

View File

@@ -67,7 +67,7 @@ function toggleMain () {
mainWindow.minimize() mainWindow.minimize()
mainWindow.restore() mainWindow.restore()
} }
mainWindow.webContents.send('list-focus') mainWindow.webContents.send('top-focus-search')
} }
} }
@@ -114,4 +114,3 @@ ipc.on('hotkeyUpdated', function (event, newKeymap) {
globalShortcut.unregisterAll() globalShortcut.unregisterAll()
registerAllKeys() registerAllKeys()
}) })

View File

@@ -6,11 +6,11 @@ const path = require('path')
var mainWindow = new BrowserWindow({ var mainWindow = new BrowserWindow({
width: 1080, width: 1080,
height: 720, height: 720,
'zoom-factor': 1.0, zoomFactor: 1.0,
'web-preferences': { webPreferences: {
'overlay-scrollbars': true blinkFeatures: 'OverlayScrollbars'
}, },
'standard-window': false standardWindow: false
}) })
const url = path.resolve(__dirname, './main.html') const url = path.resolve(__dirname, './main.html')

View File

@@ -68,7 +68,7 @@
var scriptEl = document.createElement('script') var scriptEl = document.createElement('script')
scriptEl.setAttribute("type","text/javascript") scriptEl.setAttribute("type","text/javascript")
scriptEl.setAttribute("src", scriptUrl) scriptEl.setAttribute("src", scriptUrl)
document.getElementsByTagName("head")[0].appendChild(scriptEl) document.body.appendChild(scriptEl)
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,6 +1,6 @@
{ {
"name": "boost", "name": "boost",
"version": "0.5.3", "version": "0.5.8",
"description": "Boostnote", "description": "Boostnote",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -9,7 +9,7 @@
"webpack": "webpack-dev-server --hot --inline --config webpack.config.js" "webpack": "webpack-dev-server --hot --inline --config webpack.config.js"
}, },
"config": { "config": {
"electron-version": "0.35.4" "electron-version": "0.36.11"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -55,8 +55,8 @@
"babel-preset-react": "^6.3.13", "babel-preset-react": "^6.3.13",
"babel-preset-react-hmre": "^1.0.1", "babel-preset-react-hmre": "^1.0.1",
"css-loader": "^0.19.0", "css-loader": "^0.19.0",
"electron-packager": "^5.1.0", "electron-packager": "^6.0.0",
"electron-prebuilt": "^0.35.1", "electron-prebuilt": "^0.36.11",
"electron-release": "^2.2.0", "electron-release": "^2.2.0",
"grunt": "^0.4.5", "grunt": "^0.4.5",
"grunt-electron-installer": "^1.2.0", "grunt-electron-installer": "^1.2.0",

View File

@@ -1,8 +1,23 @@
# Boostnote # Boostnote
Hack your memory Simple note app
## Develope ## Progress Kanban
https://trello.com/b/wJlinZJx/boostnote-todo-list
This is a public Kanban board. Also everyone can comment here.
If you want to join us, ask me to add you.
## Live coding
I've been broadcasting my work. You can check it from the below links. :smile:
- [Live Stream](https://www.livecoding.tv/rokt33r/videos/)
- [Recorded Videos](https://www.livecoding.tv/rokt33r/videos/)
## Develop
1. turn on HMR server 1. turn on HMR server
@@ -18,8 +33,12 @@ npm run hot
> `npm start` is using compiled scripts. see [Build](#Build) to compile scripts. > `npm start` is using compiled scripts. see [Build](#Build) to compile scripts.
## Build ## Build
> '3. Codesign' and '4. Create' installer are needed to deploy this app.
> You can skip these steps.
1. Compile scripts 1. Compile scripts
compile all browser stuff(Javascript, Stylus). compile all browser stuff(Javascript, Stylus).
@@ -78,15 +97,18 @@ grunt zip:osx
- Webpack - Webpack
... check [`package.json`](./package.json) ... check [`package.json`](./package.json)
## Codestyle ## Codestyle
[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
## Author ## Author
[Rokt33r(Dick Choi)](https://github.com/rokt33r) [Rokt33r(Dick Choi of MAISIN&CO.)](https://github.com/rokt33r)
## License ## Copyright & License
Copyright (C) 2016 MAISIN&CO.
[Check here](./LICENSE). [Check here](./LICENSE).