diff --git a/browser/finder/actions.js b/browser/finder/actions.js index 35ad4a3c..111a10c0 100644 --- a/browser/finder/actions.js +++ b/browser/finder/actions.js @@ -28,3 +28,12 @@ export function refreshData (data) { } } } + +export default { + SELECT_ARTICLE, + SEARCH_ARTICLE, + REFRESH_DATA, + selectArticle, + searchArticle, + refreshData +} diff --git a/browser/finder/index.js b/browser/finder/index.js index 311a1547..f845bbcf 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -6,12 +6,12 @@ import { createStore } from 'redux' import FinderInput from './FinderInput' import FinderList from './FinderList' import FinderDetail from './FinderDetail' -import { selectArticle, searchArticle, refreshData } from './actions' +import actions, { selectArticle, searchArticle } from './actions' import _ from 'lodash' +import dataStore from 'boost/dataStore' const electron = require('electron') const { remote, clipboard } = electron -const ipc = electron.ipcRenderer var hideFinder = remote.getGlobal('hideFinder') @@ -212,16 +212,19 @@ function remap (state) { var Finder = connect(remap)(FinderMain) var store = createStore(reducer) -window.onfocus = e => { - ipc.send('request-data') +function refreshData () { + let data = dataStore.getData() + store.dispatch(actions.refreshData(data)) } -ipc.on('refresh-data', function (e, data) { - store.dispatch(refreshData(data)) -}) +window.onfocus = e => { + refreshData() +} ReactDOM.render(( -), document.getElementById('content')) +), document.getElementById('content'), function () { + refreshData() +}) diff --git a/browser/main/index.js b/browser/main/index.js index c18e3008..a7958fad 100644 --- a/browser/main/index.js +++ b/browser/main/index.js @@ -11,7 +11,6 @@ require('../styles/main/index.styl') import { openModal } from 'boost/modal' import Tutorial from 'boost/components/modal/Tutorial' import activityRecord from 'boost/activityRecord' -import dataStore from 'boost/dataStore' const electron = require('electron') const ipc = electron.ipcRenderer @@ -30,10 +29,6 @@ ipc.on('notify', function (e, payload) { }) }) -ipc.on('request-data', function () { - ipc.send('refresh-data', dataStore.getData()) -}) - let routes = ( diff --git a/finder.js b/finder.js index 963f265e..3ec97b6a 100755 --- a/finder.js +++ b/finder.js @@ -3,7 +3,6 @@ const app = electron.app const Tray = electron.Tray const Menu = electron.Menu const MenuItem = electron.MenuItem -const ipc = electron.ipcMain process.stdin.setEncoding('utf8') @@ -11,14 +10,14 @@ console.log = function () { process.stdout.write(JSON.stringify({ type: 'log', data: JSON.stringify(Array.prototype.slice.call(arguments).join(' ')) - })) + }), 'utf-8') } function emit (type, data) { process.stdout.write(JSON.stringify({ type: type, data: JSON.stringify(data) - })) + }), 'utf-8') } var finderWindow @@ -50,10 +49,6 @@ app.on('ready', function () { })) appIcon.setContextMenu(trayMenu) - ipc.on('request-data', function () { - emit('request-data') - }) - process.stdin.on('data', function (payload) { try { payload = JSON.parse(payload) @@ -66,13 +61,8 @@ app.on('ready', function () { case 'open-finder': finderWindow.show() break - case 'refresh-data': - finderWindow.webContents.send('refresh-data', payload.data) - break } }) - - emit('request-data') }) global.hideFinder = function () { diff --git a/index.js b/index.js index dea5635b..4f2ea96e 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,9 @@ -var argv = process.argv.slice(1) -if (argv.some(arg => arg.match(/--finder/))) { +function isFinderCalled () { + var argv = process.argv.slice(1) + return argv.some(arg => arg.match(/--finder/)) +} + +if (isFinderCalled()) { require('./finder.js') } else { require('./main.js') diff --git a/lib/components/modal/Preferences.js b/lib/components/modal/Preferences.js index c2a34d0c..51813751 100644 --- a/lib/components/modal/Preferences.js +++ b/lib/components/modal/Preferences.js @@ -83,158 +83,6 @@ class Preferences extends React.Component { return () } } - - // handleProfileSaveButtonClick (e) { - // let profileState = this.state.profile - // profileState.userInfo.alert = { - // type: 'info', - // message: 'Sending...' - // } - // this.setState({profile: profileState}, () => { - // let input = { - // profileName: profileState.userInfo.profileName, - // email: profileState.userInfo.email - // } - // api.updateUserInfo(input) - // .then(res => { - // let profileState = this.state.profile - // profileState.userInfo.alert = { - // type: 'success', - // message: 'Successfully done!' - // } - // this.setState({profile: profileState}) - // }) - // .catch(err => { - // var message - // if (err.status != null) { - // message = err.response.body.message - // } else if (err.code === 'ECONNREFUSED') { - // message = 'Can\'t connect to API server.' - // } else throw err - - // let profileState = this.state.profile - // profileState.userInfo.alert = { - // type: 'error', - // message: message - // } - - // this.setState({profile: profileState}) - // }) - // }) - // } - - // handlePasswordSaveButton (e) { - // let profileState = this.state.profile - - // if (profileState.password.newPassword !== profileState.password.confirmation) { - // profileState.password.alert = { - // type: 'error', - // message: 'Confirmation doesn\'t match' - // } - // this.setState({profile: profileState}) - // return - // } - - // profileState.password.alert = { - // type: 'info', - // message: 'Sending...' - // } - - // this.setState({profile: profileState}, () => { - // let input = { - // password: profileState.password.currentPassword, - // newPassword: profileState.password.newPassword - // } - // api.updatePassword(input) - // .then(res => { - // let profileState = this.state.profile - // profileState.password.alert = { - // type: 'success', - // message: 'Successfully done!' - // } - // profileState.password.currentPassword = '' - // profileState.password.newPassword = '' - // profileState.password.confirmation = '' - - // this.setState({profile: profileState}) - // }) - // .catch(err => { - // var message - // if (err.status != null) { - // message = err.response.body.message - // } else if (err.code === 'ECONNREFUSED') { - // message = 'Can\'t connect to API server.' - // } else throw err - - // let profileState = this.state.profile - // profileState.password.alert = { - // type: 'error', - // message: message - // } - // profileState.password.currentPassword = '' - // profileState.password.newPassword = '' - // profileState.password.confirmation = '' - - // this.setState({profile: profileState}, () => { - // if (this.refs.currentPassword != null) findDOMNode(this.refs.currentPassword).focus() - // }) - // }) - // }) - // } - - // renderProfile () { - // let profileState = this.state.profile - // return ( - //
- //
- //
User Info
- //
- // - // - //
- //
- // - // - //
- //
- // - - // {this.state.profile.userInfo.alert != null - // ? ( - //
{profileState.userInfo.alert.message}
- // ) - // : null} - //
- //
- - //
- //
Password
- //
- // - // - //
- //
- // - // - //
- //
- // - // - //
- //
- // - - // {profileState.password.alert != null - // ? ( - //
{profileState.password.alert.message}
- // ) - // : null} - //
- //
- //
- // ) - // } - } Preferences.propTypes = { diff --git a/lib/dataStore.js b/lib/dataStore.js index 3b8c772a..5bcc3d49 100644 --- a/lib/dataStore.js +++ b/lib/dataStore.js @@ -1,11 +1,26 @@ import keygen from 'boost/keygen' +const electron = require('electron') +const remote = electron.remote +const jetpack = require('fs-jetpack') +const path = require('path') let defaultContent = 'Boost is a brand new note App for programmers.\n\n> 下に日本語版があります。\n\n# \u25CEfeature\n\nBoost has some preponderant functions for efficient engineer\'s task.See some part of it.\n\n1. classify information by\u300CFolders\u300D\n2. deal with great variety of syntax\n3. Finder function\n\n\uFF0A\u3000\uFF0A\u3000\uFF0A\u3000\uFF0A\n\n# 1. classify information by \u300CFolders\u300D- access the information you needed easily.\n\n\u300CFolders\u300D which on the left side bar. Press plus button now. flexible way of classification.\n- Create Folder every language or flamework\n- Make Folder for your own casual memos\n\n# 2. Deal with a great variety of syntax \u2013 instead of your brain\nSave handy all information related with programming\n- Use markdown and gather api specification\n- Well using module and snippet\n\nSave them on Boost, you don\'t need to rewrite or re-search same code again.\n\n# 3. Load Finder function \u2013 now you don\'t need to spell command by hand typing.\n\n**Shift +ctrl+tab** press buttons at same time.\nThen, the window will show up for search Boost contents that instant.\n\nUsing cursor key to chose, press enter, cmd+v to paste and\u2026 please check it out by your own eye.\n\n- Such command spl or linux which programmers often use but troublesome to hand type\n\n- (Phrases commonly used for e-mail or customer support)\n\nWe support preponderant efficiency\n\n\uFF0A\u3000\uFF0A\u3000\uFF0A\u3000\uFF0A\n\n## \u25CEfor more information\nFrequently updated with this blog ( http:\/\/blog-jp.b00st.io )\n\nHave wonderful programmer life!\n\n## Hack your memory**\n\n\n\n# 日本語版\n\n**Boost**は全く新しいエンジニアライクのノートアプリです。\n\n# ◎特徴\nBoostはエンジニアの仕事を圧倒的に効率化するいくつかの機能を備えています。\nその一部をご紹介します。\n1. Folderで情報を分類\n2. 豊富なsyantaxに対応\n3. Finder機能\n\n\n* * * *\n\n# 1. Folderで情報を分類、欲しい情報にすぐアクセス。\n左側のバーに存在する「Folders」。\n今すぐプラスボタンを押しましょう。\n分類の仕方も自由自在です。\n- 言語やフレームワークごとにFolderを作成\n- 自分用のカジュアルなメモをまとめる場としてFolderを作成\n\n\n# 2. 豊富なsyntaxに対応、自分の脳の代わりに。\nプログラミングに関する情報を全て、手軽に保存しましょう。\n- mdで、apiの仕様をまとめる\n- よく使うモジュールやスニペット\n\nBoostに保存しておくことで、何度も同じコードを書いたり調べたりする必要がなくなります。\n\n# 3. Finder機能を搭載、もうコマンドを手打ちする必要はありません。\n**「shift+ctrl+tab」** を同時に押してみてください。\nここでは、一瞬でBoostの中身を検索するウィンドウを表示させることができます。\n\n矢印キーで選択、Enterを押し、cmd+vでペーストすると…続きはご自身の目でお確かめください。\n- sqlやlinux等の、よく使うが手打ちが面倒なコマンド\n- (メールやカスタマーサポート等でよく使うフレーズ)\n\n私たちは、圧倒的な効率性を支援します。\n\* * * *\n\n\n## ◎詳しくは\nこちらのブログ( http://blog-jp.b00st.io )にて随時更新しています。\n\nそれでは素晴らしいエンジニアライフを!\n\n## Hack your memory**' +function getLocalPath () { + return path.join(remote.app.getPath('userData'), 'local.json') +} + export function init () { console.log('initialize data store') - let data = JSON.parse(localStorage.getItem('local')) + let data = jetpack.read(getLocalPath(), 'json') + if (data == null) { + if (localStorage.getItem('local') != null) { + data = JSON.parse(localStorage.getItem('local')) + jetpack.write(getLocalPath(), data) + localStorage.removeItem('local') + } + let defaultFolder = { name: 'default', key: keygen() @@ -24,37 +39,35 @@ export function init () { folders: [defaultFolder], version: '0.4' } - localStorage.setItem('local', JSON.stringify(data)) + jetpack.write(getLocalPath(), data) } } -function getKey (teamId) { - return teamId == null - ? 'local' - : `team-${teamId}` +export function getData () { + return jetpack.read(getLocalPath(), 'json') } -export function getData (teamId) { - let key = getKey(teamId) - return JSON.parse(localStorage.getItem(key)) -} - -export function setArticles (teamId, articles) { - let key = getKey(teamId) - let data = JSON.parse(localStorage.getItem(key)) +export function setArticles (articles) { + let data = getData() data.articles = articles - localStorage.setItem(key, JSON.stringify(data)) + jetpack.write(getLocalPath(), data) } -export function setFolders (teamId, folders) { - let key = getKey(teamId) - let data = JSON.parse(localStorage.getItem(key)) +export function setFolders (folders) { + let data = getData() data.folders = folders - localStorage.setItem(key, JSON.stringify(data)) + jetpack.write(getLocalPath(), data) +} + +function isFinderCalled () { + var argv = process.argv.slice(1) + return argv.some(arg => arg.match(/--finder/)) } export default (function () { - init() + if (!isFinderCalled()) { + init() + } return { init, getData, diff --git a/lib/reducer.js b/lib/reducer.js index 0e138f0d..4ca9d268 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -67,7 +67,7 @@ function folders (state = initialFolders, action) { if (conflictFolder != null) throw new Error(`${newFolder.name} already exists!`) state.push(newFolder) - dataStore.setFolders(null, state) + dataStore.setFolders(state) activityRecord.emit('FOLDER_CREATE') return state } @@ -94,7 +94,7 @@ function folders (state = initialFolders, action) { updatedAt: new Date() }) - dataStore.setFolders(null, state) + dataStore.setFolders(state) activityRecord.emit('FOLDER_UPDATE') return state } @@ -107,7 +107,7 @@ function folders (state = initialFolders, action) { if (targetIndex >= 0) { state.splice(targetIndex, 1) } - dataStore.setFolders(null, state) + dataStore.setFolders(state) activityRecord.emit('FOLDER_DESTROY') return state } @@ -167,7 +167,7 @@ function articles (state = initialArticles, action) { if (targetIndex < 0) state.unshift(article) else state.splice(targetIndex, 1, article) - if (article.status !== 'NEW') dataStore.setArticles(null, state) + if (article.status !== 'NEW') dataStore.setArticles(state) else isCreatingNew = true return state } @@ -178,7 +178,7 @@ function articles (state = initialArticles, action) { let targetIndex = _.findIndex(state, _article => articleKey === _article.key) if (targetIndex >= 0) state.splice(targetIndex, 1) - dataStore.setArticles(null, state) + dataStore.setArticles(state) return state } case FOLDER_DESTROY: @@ -187,7 +187,7 @@ function articles (state = initialArticles, action) { state = state.filter(article => article.FolderKey !== folderKey) - dataStore.setArticles(null, state) + dataStore.setArticles(state) return state } default: diff --git a/main.js b/main.js index 1c1c9c19..3c0acb29 100644 --- a/main.js +++ b/main.js @@ -93,13 +93,14 @@ app.on('ready', function () { mainWindow.hide() }) mainWindow.webContents.on('did-finish-load', function () { - require('module')._load(path.resolve(__dirname, 'finder.js'), module, true) - finderProcess = ChildProcess - .execFile(process.execPath, [path.resolve(__dirname, 'finder.js'), '--finder'], { - stdio: 'pipe' - }) - finderProcess.stdout.on('data', format) - finderProcess.stderr.on('data', errorFormat) + if (finderProcess == null) { + finderProcess = ChildProcess + .execFile(process.execPath, [path.resolve(__dirname, 'finder.js'), '--finder']) + finderProcess.stdout.setEncoding('utf8') + finderProcess.stderr.setEncoding('utf8') + finderProcess.stdout.on('data', format) + finderProcess.stderr.on('data', errorFormat) + } if (update != null) { mainWindow.webContents.send('update-available', 'whoooooooh!') @@ -152,13 +153,9 @@ app.on('ready', function () { type: type, data: data } - finderProcess.stdin.write(JSON.stringify(payload)) + finderProcess.stdin.write(JSON.stringify(payload), 'utf-8') } - ipc.on('refresh-data', function (e, data) { - emitToFinder('refresh-data', data) - }) - var userDataPath = app.getPath('userData') if (!jetpack.cwd(userDataPath).exists('keymap.json')) { jetpack.cwd(userDataPath).file('keymap.json', {content: '{}'}) diff --git a/webpack.config.js b/webpack.config.js index 2a9b24fd..3c13ba14 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -50,7 +50,8 @@ var config = { 'markdown-it', 'moment', 'highlight.js', - 'markdown-it-emoji' + 'markdown-it-emoji', + 'fs-jetpack' ] } diff --git a/webpack.config.production.js b/webpack.config.production.js index b6ca6a32..b7077f66 100644 --- a/webpack.config.production.js +++ b/webpack.config.production.js @@ -47,7 +47,8 @@ module.exports = { 'markdown-it', 'moment', 'highlight.js', - 'markdown-it-emoji' + 'markdown-it-emoji', + 'fs-jetpack' ], resolve: { extensions: ['', '.js', '.jsx', 'styl']