mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 09:46:22 +00:00
move ipc server to main process
This commit is contained in:
@@ -133,7 +133,7 @@ class NoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<button styleName='tabView-top-mode'
|
<button styleName='tabView-top-mode'
|
||||||
>
|
>
|
||||||
{mode.label}
|
{mode == null ? null : mode}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{snippet.mode === 'markdown'
|
{snippet.mode === 'markdown'
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function killFinder () {
|
|||||||
finderWindow.removeAllListeners()
|
finderWindow.removeAllListeners()
|
||||||
if (global.process.platform === 'darwin') {
|
if (global.process.platform === 'darwin') {
|
||||||
// Only OSX has another app process.
|
// Only OSX has another app process.
|
||||||
app.quit()
|
nodeIpc.of.node.emit('quit-from-finder')
|
||||||
} else {
|
} else {
|
||||||
finderWindow.close()
|
finderWindow.close()
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ function toggleFinder () {
|
|||||||
finderWindow.hide()
|
finderWindow.hide()
|
||||||
Menu.sendActionToFirstResponder('hide:')
|
Menu.sendActionToFirstResponder('hide:')
|
||||||
} else {
|
} else {
|
||||||
nodeIpc.of.node.emit('request-data')
|
nodeIpc.of.node.emit('request-data-from-finder')
|
||||||
finderWindow.show()
|
finderWindow.show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -34,17 +34,10 @@ function toggleFinder () {
|
|||||||
finderWindow.blur()
|
finderWindow.blur()
|
||||||
finderWindow.hide()
|
finderWindow.hide()
|
||||||
} else {
|
} else {
|
||||||
nodeIpc.of.node.emit('request-data')
|
nodeIpc.of.node.emit('request-data-from-finder')
|
||||||
finderWindow.show()
|
finderWindow.show()
|
||||||
finderWindow.focus()
|
finderWindow.focus()
|
||||||
}
|
}
|
||||||
// if (!finderWindow.isMinimized()) {
|
|
||||||
// finderWindow.minimize()
|
|
||||||
// } else {
|
|
||||||
// nodeIpc.of.node.emit('request-data')
|
|
||||||
// finderWindow.restore()
|
|
||||||
// finderWindow.focus()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +55,10 @@ nodeIpc.connectTo(
|
|||||||
console.log('disconnected')
|
console.log('disconnected')
|
||||||
})
|
})
|
||||||
|
|
||||||
nodeIpc.of.node.on('open-finder', function (payload) {
|
nodeIpc.of.node.on('open-finder', function () {
|
||||||
toggleFinder()
|
toggleFinder()
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('open-finder-from-tray', function () {
|
ipcRenderer.on('open-finder-from-tray', function () {
|
||||||
toggleFinder()
|
toggleFinder()
|
||||||
})
|
})
|
||||||
@@ -87,15 +81,15 @@ nodeIpc.connectTo(
|
|||||||
})
|
})
|
||||||
|
|
||||||
nodeIpc.of.node.on('config-renew', function (payload) {
|
nodeIpc.of.node.on('config-renew', function (payload) {
|
||||||
console.log('config', payload)
|
const { config } = payload
|
||||||
if (payload.ui.theme === 'dark') {
|
if (config.ui.theme === 'dark') {
|
||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
store.default.dispatch({
|
store.default.dispatch({
|
||||||
type: 'SET_CONFIG',
|
type: 'SET_CONFIG',
|
||||||
config: payload
|
config: config
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
import _ from 'lodash'
|
|
||||||
import moment from 'moment'
|
|
||||||
import dataStore from './dataStore'
|
|
||||||
import { request, SERVER_URL } from './api'
|
|
||||||
import clientKey from './clientKey'
|
|
||||||
|
|
||||||
const electron = require('electron')
|
|
||||||
const version = electron.remote.app.getVersion()
|
|
||||||
|
|
||||||
function isSameDate (a, b) {
|
|
||||||
a = moment(a).utcOffset(+540).format('YYYYMMDD')
|
|
||||||
b = moment(b).utcOffset(+540).format('YYYYMMDD')
|
|
||||||
|
|
||||||
return a === b
|
|
||||||
}
|
|
||||||
|
|
||||||
export function init () {
|
|
||||||
let records = getAllRecords()
|
|
||||||
if (records == null) {
|
|
||||||
saveAllRecords([])
|
|
||||||
}
|
|
||||||
emit(null)
|
|
||||||
|
|
||||||
postRecords()
|
|
||||||
if (window != null) {
|
|
||||||
window.addEventListener('online', postRecords)
|
|
||||||
window.setInterval(postRecords, 1000 * 60 * 60 * 24)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAllRecords () {
|
|
||||||
return JSON.parse(localStorage.getItem('activityRecords'))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function saveAllRecords (records) {
|
|
||||||
localStorage.setItem('activityRecords', JSON.stringify(records))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Post all records(except today)
|
|
||||||
and remove all posted records
|
|
||||||
*/
|
|
||||||
export function postRecords (data) {
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
|
||||||
console.log('post failed - NOT PRODUCTION ')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let records = getAllRecords()
|
|
||||||
records = records.filter(record => {
|
|
||||||
return !isSameDate(new Date(), record.date)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (records.length === 0) {
|
|
||||||
console.log('No records to post')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('posting...', records)
|
|
||||||
let input = {
|
|
||||||
clientKey: clientKey.get(),
|
|
||||||
records
|
|
||||||
}
|
|
||||||
return request.post(SERVER_URL + 'apis/activity')
|
|
||||||
.send(input)
|
|
||||||
.then(res => {
|
|
||||||
let records = getAllRecords()
|
|
||||||
let todayRecord = _.find(records, record => {
|
|
||||||
return isSameDate(new Date(), record.date)
|
|
||||||
})
|
|
||||||
if (todayRecord != null) saveAllRecords([todayRecord])
|
|
||||||
else saveAllRecords([])
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function emit (type, data = {}) {
|
|
||||||
let records = getAllRecords()
|
|
||||||
|
|
||||||
let index = _.findIndex(records, record => {
|
|
||||||
return isSameDate(new Date(), record.date)
|
|
||||||
})
|
|
||||||
|
|
||||||
let todayRecord
|
|
||||||
if (index < 0) {
|
|
||||||
todayRecord = {date: new Date()}
|
|
||||||
records.push(todayRecord)
|
|
||||||
}
|
|
||||||
else todayRecord = records[index]
|
|
||||||
switch (type) {
|
|
||||||
case 'ARTICLE_CREATE':
|
|
||||||
case 'ARTICLE_UPDATE':
|
|
||||||
case 'ARTICLE_DESTROY':
|
|
||||||
case 'FOLDER_CREATE':
|
|
||||||
case 'FOLDER_UPDATE':
|
|
||||||
case 'FOLDER_DESTROY':
|
|
||||||
case 'FINDER_OPEN':
|
|
||||||
case 'FINDER_COPY':
|
|
||||||
case 'MAIN_DETAIL_COPY':
|
|
||||||
case 'ARTICLE_SHARE':
|
|
||||||
todayRecord[type] = todayRecord[type] == null
|
|
||||||
? 1
|
|
||||||
: todayRecord[type] + 1
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count ARTICLE_CREATE and ARTICLE_UPDATE again by syntax
|
|
||||||
if (type === 'ARTICLE_UPDATE' && data.mode != null) {
|
|
||||||
let recordKey = type + '_BY_SYNTAX'
|
|
||||||
if (todayRecord[recordKey] == null) todayRecord[recordKey] = {}
|
|
||||||
|
|
||||||
todayRecord[recordKey][data.mode] = todayRecord[recordKey][data.mode] == null
|
|
||||||
? 1
|
|
||||||
: todayRecord[recordKey][data.mode] + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
let storeData = dataStore.getData()
|
|
||||||
todayRecord.FOLDER_COUNT = storeData && _.isArray(storeData.folders) ? storeData.folders.length : 0
|
|
||||||
todayRecord.ARTICLE_COUNT = storeData && _.isArray(storeData.articles) ? storeData.articles.length : 0
|
|
||||||
todayRecord.CLIENT_VERSION = version
|
|
||||||
|
|
||||||
todayRecord.SYNTAX_COUNT = storeData && _.isArray(storeData.articles) ? storeData.articles.reduce((sum, article) => {
|
|
||||||
if (sum[article.mode] == null) sum[article.mode] = 1
|
|
||||||
else sum[article.mode]++
|
|
||||||
return sum
|
|
||||||
}, {}) : 0
|
|
||||||
|
|
||||||
saveAllRecords(records)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
init,
|
|
||||||
emit,
|
|
||||||
postRecords
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
import keygen from './keygen'
|
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
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**'
|
|
||||||
|
|
||||||
let data = null
|
|
||||||
|
|
||||||
function getLocalPath () {
|
|
||||||
return path.join(remote.app.getPath('userData'), 'local.json')
|
|
||||||
}
|
|
||||||
|
|
||||||
function forgeInitialRepositories () {
|
|
||||||
let defaultRepo = {
|
|
||||||
key: keygen(),
|
|
||||||
name: 'local',
|
|
||||||
type: 'userData',
|
|
||||||
user: {
|
|
||||||
name: 'New user'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
defaultRepo.user.name = remote.process.env.USER
|
|
||||||
} else if (process.platform === 'win32') {
|
|
||||||
defaultRepo.user.name = remote.process.env.USERNAME
|
|
||||||
}
|
|
||||||
|
|
||||||
return [defaultRepo]
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRepositories () {
|
|
||||||
let raw = localStorage.getItem('repositories')
|
|
||||||
try {
|
|
||||||
let parsed = JSON.parse(raw)
|
|
||||||
if (!_.isArray(parsed)) {
|
|
||||||
throw new Error('repositories data is corrupted. re-init data.')
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
let newRepos = forgeInitialRepositories()
|
|
||||||
saveRepositories(newRepos)
|
|
||||||
return newRepos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveRepositories (repos) {
|
|
||||||
localStorage.setItem('repositories', JSON.stringify(repos))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUser (repoName) {
|
|
||||||
if (repoName == null) {
|
|
||||||
return getRepositories()[0]
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export function saveUser (repoName, user) {
|
|
||||||
let repos = getRepositories()
|
|
||||||
if (repoName == null) {
|
|
||||||
Object.assign(repos[0].user, user)
|
|
||||||
}
|
|
||||||
saveRepositories(repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function init () {
|
|
||||||
// set repositories info
|
|
||||||
getRepositories()
|
|
||||||
data = jetpack.read(getLocalPath(), 'json')
|
|
||||||
if (data == null) {
|
|
||||||
let defaultFolder = {
|
|
||||||
name: 'default',
|
|
||||||
key: keygen()
|
|
||||||
}
|
|
||||||
let defaultArticle = {
|
|
||||||
title: 'About Boost',
|
|
||||||
tags: ['boost', 'intro'],
|
|
||||||
content: defaultContent,
|
|
||||||
mode: 'markdown',
|
|
||||||
key: keygen(),
|
|
||||||
FolderKey: defaultFolder.key,
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
articles: [defaultArticle],
|
|
||||||
folders: [defaultFolder],
|
|
||||||
version: '0.4'
|
|
||||||
}
|
|
||||||
saveData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getData (forceRead) {
|
|
||||||
if (forceRead) {
|
|
||||||
try {
|
|
||||||
data = jetpack.read(getLocalPath(), 'json')
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
let timer = null
|
|
||||||
let isSaving = false
|
|
||||||
let saveAgain = false
|
|
||||||
function saveData () {
|
|
||||||
timer = null
|
|
||||||
isSaving = true
|
|
||||||
jetpack.writeAsync(getLocalPath(), data)
|
|
||||||
.then(function () {
|
|
||||||
isSaving = false
|
|
||||||
if (saveAgain) {
|
|
||||||
saveAgain = false
|
|
||||||
queueSave()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function queueSave () {
|
|
||||||
if (!isSaving) {
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer)
|
|
||||||
}
|
|
||||||
timer = setTimeout(saveData, 500)
|
|
||||||
} else {
|
|
||||||
saveAgain = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setArticles (articles) {
|
|
||||||
if (!_.isArray(articles)) throw new Error('Articles must be an array')
|
|
||||||
let data = getData()
|
|
||||||
data.articles = articles
|
|
||||||
queueSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setFolders (folders) {
|
|
||||||
if (!_.isArray(folders)) throw new Error('Folders must be an array')
|
|
||||||
let data = getData()
|
|
||||||
data.folders = folders
|
|
||||||
queueSave()
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getUser,
|
|
||||||
saveUser,
|
|
||||||
init,
|
|
||||||
getData,
|
|
||||||
setArticles,
|
|
||||||
setFolders
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@ import _ from 'lodash'
|
|||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import modal from 'browser/main/lib/modal'
|
import modal from 'browser/main/lib/modal'
|
||||||
import InitModal from 'browser/main/modals/InitModal'
|
import InitModal from 'browser/main/modals/InitModal'
|
||||||
import ipc from 'browser/main/lib/ipc'
|
|
||||||
|
|
||||||
class Main extends React.Component {
|
class Main extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
|||||||
@@ -4,14 +4,12 @@ import store from './store'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
require('!!style!css!stylus?sourceMap!./global.styl')
|
require('!!style!css!stylus?sourceMap!./global.styl')
|
||||||
import activityRecord from 'browser/lib/activityRecord'
|
|
||||||
import { Router, Route, IndexRoute, IndexRedirect, hashHistory } from 'react-router'
|
import { Router, Route, IndexRoute, IndexRedirect, hashHistory } from 'react-router'
|
||||||
import { syncHistoryWithStore } from 'react-router-redux'
|
import { syncHistoryWithStore } from 'react-router-redux'
|
||||||
|
require('./lib/ipcClient')
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const ipc = electron.ipcRenderer
|
const ipc = electron.ipcRenderer
|
||||||
|
|
||||||
activityRecord.init()
|
|
||||||
ipc.send('check-update', 'check-update')
|
ipc.send('check-update', 'check-update')
|
||||||
window.addEventListener('online', function () {
|
window.addEventListener('online', function () {
|
||||||
ipc.send('check-update', 'check-update')
|
ipc.send('check-update', 'check-update')
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import _ from 'lodash'
|
|||||||
|
|
||||||
const OSX = global.process.platform === 'darwin'
|
const OSX = global.process.platform === 'darwin'
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote } = electron
|
const { ipcRenderer } = electron
|
||||||
|
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
@@ -73,9 +73,8 @@ function set (updates) {
|
|||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
|
|
||||||
remote.getCurrentWindow().webContents.send('config-renew', {
|
ipcRenderer.send('config-renew', {
|
||||||
config: get(),
|
config: get()
|
||||||
silent: false
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,139 +0,0 @@
|
|||||||
import store from 'browser/main/store'
|
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
|
||||||
|
|
||||||
const nodeIpc = require('node-ipc')
|
|
||||||
const { remote, ipcRenderer } = require('electron')
|
|
||||||
const { app, Menu } = remote
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
nodeIpc.config.id = 'node'
|
|
||||||
nodeIpc.config.retry = 1500
|
|
||||||
nodeIpc.config.silent = true
|
|
||||||
console.log('Initializing IPC Server')
|
|
||||||
|
|
||||||
// TODO: IPC SERVER WILL BE MOVED TO MAIN PROCESS FROM MAIN WINDOW PROCESS(RENDERER)
|
|
||||||
nodeIpc.serve(
|
|
||||||
path.join(app.getPath('userData'), 'boostnote.service'),
|
|
||||||
function () {
|
|
||||||
console.log('IPC Server Started')
|
|
||||||
ipcRenderer.on('open-finder', function () {
|
|
||||||
console.log('Open finder')
|
|
||||||
nodeIpc.server.broadcast('open-finder')
|
|
||||||
})
|
|
||||||
|
|
||||||
/** Quit Sequence
|
|
||||||
1. `quit-app` Main process -> Main window by Electron IPC
|
|
||||||
2. `quit-finder-app` Main window -> Finder window by Node IPC(socket)
|
|
||||||
3. Finder window (and Finder main process: OSX only) killed by remote API
|
|
||||||
4. `quit-finder-app-confirm` Finder window -> Main window by NodeIPC
|
|
||||||
5. `quit-app-confirm` Main window -> Main process by Electron IPC
|
|
||||||
6. Main process discard close preventer and terminate Main window and itself.
|
|
||||||
|
|
||||||
If the platform is a linux without cinnamon, the app will skip 2.-4. because it doesn't launch finder window.
|
|
||||||
`quit-app` will fires directly `quit-app-confirm`.
|
|
||||||
*/
|
|
||||||
ipcRenderer.on('quit-app', function () {
|
|
||||||
// Finder app exists only in the linux with cinnamon.
|
|
||||||
if (global.process.env.platform === 'linux' && global.process.env.DESKTOP_SESSION !== 'cinnamon') {
|
|
||||||
ipcRenderer.send('quit-app-confirm')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let confirmHandler = function () {
|
|
||||||
ipcRenderer.send('quit-app-confirm')
|
|
||||||
}
|
|
||||||
nodeIpc.server.on('quit-finder-app-confirm', confirmHandler)
|
|
||||||
setTimeout(() => {
|
|
||||||
nodeIpc.server.removeListener('quit-finder-app-confirm', confirmHandler)
|
|
||||||
}, 1000)
|
|
||||||
nodeIpc.server.broadcast('quit-finder-app')
|
|
||||||
})
|
|
||||||
|
|
||||||
/** Update Sequence
|
|
||||||
1. `update-ready` Main process -> Main window by Electron IPC
|
|
||||||
2. `update-app` Main window -> Main window by Electron IPC
|
|
||||||
3. `quit-finder-app` Main window -> Finder window by Node IPC
|
|
||||||
4. Finder window (and Finder main process: OSX only) killed by remote API
|
|
||||||
5. `quit-finder-app-confirm` Finder window -> Main window by NodeIPC
|
|
||||||
6. `update-app-confirm` Main window -> Main process by Electron IPC
|
|
||||||
7. Main process discard close preventer and start updating.
|
|
||||||
|
|
||||||
Handlers of 1. and 2. can be found in StatusBar component.
|
|
||||||
*/
|
|
||||||
ipcRenderer.on('update-app', function () {
|
|
||||||
// Linux app doesn't support auto updater
|
|
||||||
if (global.process.env.platform === 'linux') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let confirmHandler = function () {
|
|
||||||
ipcRenderer.send('update-app-confirm')
|
|
||||||
}
|
|
||||||
nodeIpc.server.on('quit-finder-app-confirm', confirmHandler)
|
|
||||||
setTimeout(() => {
|
|
||||||
nodeIpc.server.removeListener('quit-finder-app-confirm', confirmHandler)
|
|
||||||
}, 1000)
|
|
||||||
nodeIpc.server.broadcast('quit-finder-app')
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcRenderer.on('update-found', function () {
|
|
||||||
console.log('Update found')
|
|
||||||
})
|
|
||||||
|
|
||||||
let config = ConfigManager.get()
|
|
||||||
nodeIpc.server.broadcast('config-renew', config)
|
|
||||||
ipcRenderer.send('config-renew', {
|
|
||||||
config: config,
|
|
||||||
silent: true
|
|
||||||
})
|
|
||||||
ipcRenderer.on('config-renew', function (e, data) {
|
|
||||||
nodeIpc.server.broadcast('config-renew', data.config)
|
|
||||||
ipcRenderer.send('config-renew', data)
|
|
||||||
})
|
|
||||||
|
|
||||||
nodeIpc.server.on('open-main-from-finder', function () {
|
|
||||||
let mainWindow = remote.getCurrentWindow()
|
|
||||||
console.log('open main from finder')
|
|
||||||
if (mainWindow.isFocused()) {
|
|
||||||
if (global.process.platform === 'darwin') {
|
|
||||||
Menu.sendActionToFirstResponder('hide:')
|
|
||||||
} else {
|
|
||||||
mainWindow.minimize()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (global.process.platform === 'darwin') {
|
|
||||||
mainWindow.show()
|
|
||||||
} else {
|
|
||||||
mainWindow.minimize()
|
|
||||||
mainWindow.restore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
nodeIpc.server.on('quit-from-finder', function () {
|
|
||||||
ipcRenderer.send('quit-app-confirm')
|
|
||||||
})
|
|
||||||
|
|
||||||
nodeIpc.server.on('connect', function (socket) {
|
|
||||||
console.log('connected')
|
|
||||||
nodeIpc.server.broadcast('config-renew', ConfigManager.get())
|
|
||||||
socket.on('close', function () {
|
|
||||||
console.log('socket dead')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
nodeIpc.server.on('error', function (err) {
|
|
||||||
console.error('Node IPC error', err)
|
|
||||||
})
|
|
||||||
nodeIpc.server.on('request-data', function (data, socket) {
|
|
||||||
let state = store.getState()
|
|
||||||
nodeIpc.server.broadcast('throttle-data', {
|
|
||||||
storages: state.storages,
|
|
||||||
notes: state.notes
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const ipc = {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeIpc.server.start()
|
|
||||||
module.exports = ipc
|
|
||||||
39
browser/main/lib/ipcClient.js
Normal file
39
browser/main/lib/ipcClient.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import ConfigManager from './ConfigManager'
|
||||||
|
import store from 'browser/main/store'
|
||||||
|
|
||||||
|
const nodeIpc = require('node-ipc')
|
||||||
|
const { remote, ipcRenderer } = require('electron')
|
||||||
|
const { app } = remote
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
nodeIpc.config.id = 'main'
|
||||||
|
nodeIpc.config.retry = 1500
|
||||||
|
nodeIpc.config.silent = true
|
||||||
|
|
||||||
|
nodeIpc.connectTo(
|
||||||
|
'node',
|
||||||
|
path.join(app.getPath('userData'), 'boostnote.service'),
|
||||||
|
function () {
|
||||||
|
nodeIpc.of.node.on('error', function (err) {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
nodeIpc.of.node.on('connect', function () {
|
||||||
|
console.log('Conncted successfully')
|
||||||
|
ipcRenderer.send('config-renew', {config: ConfigManager.get()})
|
||||||
|
})
|
||||||
|
nodeIpc.of.node.on('disconnect', function () {
|
||||||
|
console.log('disconnected')
|
||||||
|
})
|
||||||
|
|
||||||
|
nodeIpc.of.node.on('request-data-from-finder', function () {
|
||||||
|
console.log('throttle')
|
||||||
|
var data = store.getState()
|
||||||
|
nodeIpc.of.node.emit('throttle-data', {
|
||||||
|
storages: data.storages,
|
||||||
|
notes: data.notes
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
module.exports = nodeIpc
|
||||||
@@ -54,6 +54,7 @@ trayMenu.append(new MenuItem({
|
|||||||
finderWindow.webContents.send('open-main-from-tray')
|
finderWindow.webContents.send('open-main-from-tray')
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (process.env.platform !== 'linux' || process.env.DESKTOP_SESSION === 'cinnamon') {
|
if (process.env.platform !== 'linux' || process.env.DESKTOP_SESSION === 'cinnamon') {
|
||||||
trayMenu.append(new MenuItem({
|
trayMenu.append(new MenuItem({
|
||||||
label: 'Open Finder window',
|
label: 'Open Finder window',
|
||||||
@@ -62,6 +63,7 @@ if (process.env.platform !== 'linux' || process.env.DESKTOP_SESSION === 'cinnamo
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
trayMenu.append(new MenuItem({
|
trayMenu.append(new MenuItem({
|
||||||
label: 'Quit',
|
label: 'Quit',
|
||||||
click: function () {
|
click: function () {
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
const electron = require('electron')
|
|
||||||
const ipc = electron.ipcMain
|
|
||||||
const Menu = electron.Menu
|
|
||||||
const globalShortcut = electron.globalShortcut
|
|
||||||
const mainWindow = require('./main-window')
|
|
||||||
|
|
||||||
function toggleFinder () {
|
|
||||||
mainWindow.webContents.send('open-finder', {})
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleMain () {
|
|
||||||
if (mainWindow.isFocused()) {
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
Menu.sendActionToFirstResponder('hide:')
|
|
||||||
} else {
|
|
||||||
mainWindow.minimize()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
mainWindow.show()
|
|
||||||
} else {
|
|
||||||
mainWindow.minimize()
|
|
||||||
mainWindow.restore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipc.on('config-renew', (e, payload) => {
|
|
||||||
globalShortcut.unregisterAll()
|
|
||||||
var { config } = payload
|
|
||||||
|
|
||||||
var errors = []
|
|
||||||
try {
|
|
||||||
globalShortcut.register(config.hotkey.toggleFinder, toggleFinder)
|
|
||||||
} catch (err) {
|
|
||||||
errors.push('toggleFinder')
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
globalShortcut.register(config.hotkey.toggleMain, toggleMain)
|
|
||||||
} catch (err) {
|
|
||||||
errors.push('toggleMain')
|
|
||||||
}
|
|
||||||
if (!config.silent) {
|
|
||||||
if (errors.length === 0) {
|
|
||||||
mainWindow.webContents.send('APP_SETTING_DONE', {})
|
|
||||||
} else {
|
|
||||||
mainWindow.webContents.send('APP_SETTING_ERROR', {
|
|
||||||
message: 'Failed to apply hotkey: ' + errors.join(' ')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
89
lib/ipcServer.js
Normal file
89
lib/ipcServer.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
const nodeIpc = require('node-ipc')
|
||||||
|
const { app, Menu, globalShortcut, ipcMain } = require('electron')
|
||||||
|
const path = require('path')
|
||||||
|
const mainWindow = require('./main-window')
|
||||||
|
|
||||||
|
nodeIpc.config.id = 'node'
|
||||||
|
nodeIpc.config.retry = 1500
|
||||||
|
nodeIpc.config.silent = true
|
||||||
|
|
||||||
|
function toggleMainWindow () {
|
||||||
|
switch (global.process.platform) {
|
||||||
|
case 'darwin':
|
||||||
|
if (mainWindow.isFocused()) {
|
||||||
|
Menu.sendActionToFirstResponder('hide:')
|
||||||
|
} else {
|
||||||
|
mainWindow.show()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
if (mainWindow.isFocused()) {
|
||||||
|
mainWindow.minimize()
|
||||||
|
} else {
|
||||||
|
mainWindow.minimize()
|
||||||
|
mainWindow.restore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleFinder () {
|
||||||
|
nodeIpc.server.broadcast('open-finder')
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcMain.on('config-renew', (e, payload) => {
|
||||||
|
nodeIpc.server.broadcast('config-renew', payload)
|
||||||
|
|
||||||
|
globalShortcut.unregisterAll()
|
||||||
|
var { config } = payload
|
||||||
|
|
||||||
|
var errors = []
|
||||||
|
try {
|
||||||
|
globalShortcut.register(config.hotkey.toggleFinder, toggleFinder)
|
||||||
|
} catch (err) {
|
||||||
|
errors.push('toggleFinder')
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
globalShortcut.register(config.hotkey.toggleMain, toggleMainWindow)
|
||||||
|
} catch (err) {
|
||||||
|
errors.push('toggleMain')
|
||||||
|
}
|
||||||
|
if (!config.silent) {
|
||||||
|
if (errors.length === 0) {
|
||||||
|
mainWindow.webContents.send('APP_SETTING_DONE', {})
|
||||||
|
} else {
|
||||||
|
mainWindow.webContents.send('APP_SETTING_ERROR', {
|
||||||
|
message: 'Failed to apply hotkey: ' + errors.join(' ')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
nodeIpc.serve(
|
||||||
|
path.join(app.getPath('userData'), 'boostnote.service'),
|
||||||
|
function () {
|
||||||
|
nodeIpc.server.on('open-main-from-finder', toggleMainWindow)
|
||||||
|
|
||||||
|
nodeIpc.server.on('quit-from-finder', function () {
|
||||||
|
app.quit()
|
||||||
|
})
|
||||||
|
|
||||||
|
nodeIpc.server.on('connect', function (socket) {
|
||||||
|
nodeIpc.log('ipc server >> socket joinned'.rainbow)
|
||||||
|
socket.on('close', function () {
|
||||||
|
nodeIpc.log('ipc server >> socket closed'.rainbow)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
nodeIpc.server.on('error', function (err) {
|
||||||
|
nodeIpc.log('Node IPC error'.rainbow, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
nodeIpc.server.on('request-data-from-finder', function () {
|
||||||
|
nodeIpc.server.broadcast('request-data-from-finder')
|
||||||
|
})
|
||||||
|
nodeIpc.server.on('throttle-data', function (payload) {
|
||||||
|
nodeIpc.server.broadcast('throttle-data', payload)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
module.exports = nodeIpc
|
||||||
@@ -8,7 +8,7 @@ const ChildProcess = require('child_process')
|
|||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const GhReleases = require('electron-gh-releases')
|
const GhReleases = require('electron-gh-releases')
|
||||||
// electron.crashReporter.start()
|
// electron.crashReporter.start()
|
||||||
require('./ipc')
|
var ipcServer = null
|
||||||
|
|
||||||
var mainWindow = null
|
var mainWindow = null
|
||||||
var finderWindow = null
|
var finderWindow = null
|
||||||
@@ -112,8 +112,8 @@ app.on('ready', function () {
|
|||||||
}, 1000 * 60 * 60)
|
}, 1000 * 60 * 60)
|
||||||
|
|
||||||
checkUpdate()
|
checkUpdate()
|
||||||
|
ipcServer = require('./ipcServer')
|
||||||
require('./hotkey')
|
ipcServer.server.start()
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = app
|
module.exports = app
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ const electron = require('electron')
|
|||||||
const app = electron.app
|
const app = electron.app
|
||||||
const BrowserWindow = electron.BrowserWindow
|
const BrowserWindow = electron.BrowserWindow
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const ipc = require('./ipc')
|
|
||||||
|
|
||||||
var mainWindow = new BrowserWindow({
|
var mainWindow = new BrowserWindow({
|
||||||
width: 1080,
|
width: 1080,
|
||||||
|
|||||||
Reference in New Issue
Block a user