mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 10:16:26 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fcaaa297a | ||
|
|
7c2d2044a9 | ||
|
|
aa32f59dc6 | ||
|
|
182af99e7c | ||
|
|
5b520a7a81 | ||
|
|
364917c910 | ||
|
|
ca7b9c786a | ||
|
|
15c2363098 | ||
|
|
1a11095121 |
@@ -25,4 +25,6 @@ finderWindow.on('blur', function () {
|
|||||||
finderWindow.hide()
|
finderWindow.hide()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
finderWindow.setVisibleOnAllWorkspaces(true)
|
||||||
|
|
||||||
module.exports = finderWindow
|
module.exports = finderWindow
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import _ from 'lodash'
|
|||||||
import dataStore from 'boost/dataStore'
|
import dataStore from 'boost/dataStore'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote, clipboard } = electron
|
const { remote, clipboard, ipcRenderer } = electron
|
||||||
|
|
||||||
var hideFinder = remote.getGlobal('hideFinder')
|
var hideFinder = remote.getGlobal('hideFinder')
|
||||||
|
|
||||||
@@ -64,6 +64,7 @@ class FinderMain extends React.Component {
|
|||||||
let { activeArticle } = this.props
|
let { activeArticle } = this.props
|
||||||
clipboard.writeText(activeArticle.content)
|
clipboard.writeText(activeArticle.content)
|
||||||
|
|
||||||
|
ipcRenderer.send('copy-finder')
|
||||||
notify('Saved to Clipboard!', {
|
notify('Saved to Clipboard!', {
|
||||||
body: 'Paste it wherever you want!'
|
body: 'Paste it wherever you want!'
|
||||||
})
|
})
|
||||||
@@ -152,6 +153,14 @@ function buildFilter (key) {
|
|||||||
return {type: TEXT_FILTER, value: key}
|
return {type: TEXT_FILTER, value: key}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isContaining (target, needle) {
|
||||||
|
return target.match(new RegExp(_.escapeRegExp(needle)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsWith (target, needle) {
|
||||||
|
return target.match(new RegExp('^' + _.escapeRegExp(needle)))
|
||||||
|
}
|
||||||
|
|
||||||
function remap (state) {
|
function remap (state) {
|
||||||
let { articles, folders, status } = state
|
let { articles, folders, status } = state
|
||||||
|
|
||||||
@@ -168,10 +177,10 @@ function remap (state) {
|
|||||||
let targetFolders
|
let targetFolders
|
||||||
if (folders != null) {
|
if (folders != null) {
|
||||||
let exactTargetFolders = folders.filter(folder => {
|
let exactTargetFolders = folders.filter(folder => {
|
||||||
return _.find(folderExactFilters, filter => folder.name.match(new RegExp(`^${filter.value}$`)))
|
return _.find(folderExactFilters, filter => isContaining(folder.name, filter.value))
|
||||||
})
|
})
|
||||||
let fuzzyTargetFolders = folders.filter(folder => {
|
let fuzzyTargetFolders = folders.filter(folder => {
|
||||||
return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`)))
|
return _.find(folderFilters, filter => startsWith(folder.name, filter.value))
|
||||||
})
|
})
|
||||||
targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders)
|
targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders)
|
||||||
|
|
||||||
@@ -184,7 +193,7 @@ function remap (state) {
|
|||||||
if (textFilters.length > 0) {
|
if (textFilters.length > 0) {
|
||||||
articles = textFilters.reduce((articles, textFilter) => {
|
articles = textFilters.reduce((articles, textFilter) => {
|
||||||
return articles.filter(article => {
|
return articles.filter(article => {
|
||||||
return article.title.match(new RegExp(textFilter.value, 'i')) || article.content.match(new RegExp(textFilter.value, 'i'))
|
return isContaining(article.title, textFilter.value) || isContaining(article.content, textFilter.value)
|
||||||
})
|
})
|
||||||
}, articles)
|
}, articles)
|
||||||
}
|
}
|
||||||
@@ -192,7 +201,7 @@ function remap (state) {
|
|||||||
if (tagFilters.length > 0) {
|
if (tagFilters.length > 0) {
|
||||||
articles = tagFilters.reduce((articles, tagFilter) => {
|
articles = tagFilters.reduce((articles, tagFilter) => {
|
||||||
return articles.filter(article => {
|
return articles.filter(article => {
|
||||||
return _.find(article.tags, tag => tag.match(new RegExp(tagFilter.value, 'i')))
|
return _.find(article.tags, tag => isContaining(tag, tagFilter.value))
|
||||||
})
|
})
|
||||||
}, articles)
|
}, articles)
|
||||||
}
|
}
|
||||||
@@ -201,7 +210,6 @@ function remap (state) {
|
|||||||
let activeArticle = _.findWhere(articles, {key: status.articleKey})
|
let activeArticle = _.findWhere(articles, {key: status.articleKey})
|
||||||
if (activeArticle == null) activeArticle = articles[0]
|
if (activeArticle == null) activeArticle = articles[0]
|
||||||
|
|
||||||
console.log(status.search)
|
|
||||||
return {
|
return {
|
||||||
articles,
|
articles,
|
||||||
activeArticle,
|
activeArticle,
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React, { PropTypes} from 'react'
|
import React, { PropTypes} from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { EDIT_MODE, IDLE_MODE, NEW, toggleTutorial } from 'boost/actions'
|
import { EDIT_MODE, IDLE_MODE, toggleTutorial } from 'boost/actions'
|
||||||
// import UserNavigator from './HomePage/UserNavigator'
|
|
||||||
import ArticleNavigator from './HomePage/ArticleNavigator'
|
import ArticleNavigator from './HomePage/ArticleNavigator'
|
||||||
import ArticleTopBar from './HomePage/ArticleTopBar'
|
import ArticleTopBar from './HomePage/ArticleTopBar'
|
||||||
import ArticleList from './HomePage/ArticleList'
|
import ArticleList from './HomePage/ArticleList'
|
||||||
import ArticleDetail from './HomePage/ArticleDetail'
|
import ArticleDetail from './HomePage/ArticleDetail'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { isModalOpen, closeModal } from 'boost/modal'
|
import { isModalOpen, closeModal } from 'boost/modal'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const BrowserWindow = electron.remote.BrowserWindow
|
const BrowserWindow = electron.remote.BrowserWindow
|
||||||
|
|
||||||
@@ -114,13 +114,14 @@ class HomePage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { dispatch, status, articles, allArticles, activeArticle, folders, tags, filters } = this.props
|
let { dispatch, status, user, articles, allArticles, activeArticle, folders, tags, filters } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='HomePage'>
|
<div className='HomePage'>
|
||||||
<ArticleNavigator
|
<ArticleNavigator
|
||||||
ref='nav'
|
ref='nav'
|
||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
|
user={user}
|
||||||
folders={folders}
|
folders={folders}
|
||||||
status={status}
|
status={status}
|
||||||
allArticles={allArticles}
|
allArticles={allArticles}
|
||||||
@@ -171,8 +172,16 @@ function buildFilter (key) {
|
|||||||
return {type: TEXT_FILTER, value: key}
|
return {type: TEXT_FILTER, value: key}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isContaining (target, needle) {
|
||||||
|
return target.match(new RegExp(_.escapeRegExp(needle)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function startsWith (target, needle) {
|
||||||
|
return target.match(new RegExp('^' + _.escapeRegExp(needle)))
|
||||||
|
}
|
||||||
|
|
||||||
function remap (state) {
|
function remap (state) {
|
||||||
let { folders, articles, status } = state
|
let { user, folders, articles, status } = state
|
||||||
|
|
||||||
if (articles == null) articles = []
|
if (articles == null) articles = []
|
||||||
articles.sort((a, b) => {
|
articles.sort((a, b) => {
|
||||||
@@ -199,10 +208,10 @@ function remap (state) {
|
|||||||
let targetFolders
|
let targetFolders
|
||||||
if (folders != null) {
|
if (folders != null) {
|
||||||
let exactTargetFolders = folders.filter(folder => {
|
let exactTargetFolders = folders.filter(folder => {
|
||||||
return _.find(folderExactFilters, filter => folder.name.match(new RegExp(`^${filter.value}$`)))
|
return _.findWhere(folderExactFilters, {value: folder.name})
|
||||||
})
|
})
|
||||||
let fuzzyTargetFolders = folders.filter(folder => {
|
let fuzzyTargetFolders = folders.filter(folder => {
|
||||||
return _.find(folderFilters, filter => folder.name.match(new RegExp(`^${filter.value}`)))
|
return _.find(folderFilters, filter => startsWith(folder.name, filter.value))
|
||||||
})
|
})
|
||||||
targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders)
|
targetFolders = status.targetFolders = exactTargetFolders.concat(fuzzyTargetFolders)
|
||||||
|
|
||||||
@@ -215,7 +224,7 @@ function remap (state) {
|
|||||||
if (textFilters.length > 0) {
|
if (textFilters.length > 0) {
|
||||||
articles = textFilters.reduce((articles, textFilter) => {
|
articles = textFilters.reduce((articles, textFilter) => {
|
||||||
return articles.filter(article => {
|
return articles.filter(article => {
|
||||||
return article.title.match(new RegExp(textFilter.value, 'i')) || article.content.match(new RegExp(textFilter.value, 'i'))
|
return isContaining(article.title, textFilter.value) || isContaining(article.content, textFilter.value)
|
||||||
})
|
})
|
||||||
}, articles)
|
}, articles)
|
||||||
}
|
}
|
||||||
@@ -223,7 +232,7 @@ function remap (state) {
|
|||||||
if (tagFilters.length > 0) {
|
if (tagFilters.length > 0) {
|
||||||
articles = tagFilters.reduce((articles, tagFilter) => {
|
articles = tagFilters.reduce((articles, tagFilter) => {
|
||||||
return articles.filter(article => {
|
return articles.filter(article => {
|
||||||
return _.find(article.tags, tag => tag.match(new RegExp(tagFilter.value, 'i')))
|
return _.find(article.tags, tag => isContaining(tag, tagFilter.value))
|
||||||
})
|
})
|
||||||
}, articles)
|
}, articles)
|
||||||
}
|
}
|
||||||
@@ -234,6 +243,7 @@ function remap (state) {
|
|||||||
if (activeArticle == null) activeArticle = articles[0]
|
if (activeArticle == null) activeArticle = articles[0]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
user,
|
||||||
folders,
|
folders,
|
||||||
status,
|
status,
|
||||||
allArticles,
|
allArticles,
|
||||||
@@ -249,11 +259,9 @@ function remap (state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HomePage.propTypes = {
|
HomePage.propTypes = {
|
||||||
params: PropTypes.shape({
|
status: PropTypes.shape(),
|
||||||
userId: PropTypes.string
|
user: PropTypes.shape({
|
||||||
}),
|
name: PropTypes.string
|
||||||
status: PropTypes.shape({
|
|
||||||
userId: PropTypes.string
|
|
||||||
}),
|
}),
|
||||||
articles: PropTypes.array,
|
articles: PropTypes.array,
|
||||||
allArticles: PropTypes.array,
|
allArticles: PropTypes.array,
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ import Preferences from 'boost/components/modal/Preferences'
|
|||||||
import CreateNewFolder from 'boost/components/modal/CreateNewFolder'
|
import CreateNewFolder from 'boost/components/modal/CreateNewFolder'
|
||||||
import keygen from 'boost/keygen'
|
import keygen from 'boost/keygen'
|
||||||
|
|
||||||
const electron = require('electron')
|
|
||||||
const remote = electron.remote
|
|
||||||
let userName = remote.getGlobal('process').env.USER
|
|
||||||
|
|
||||||
const BRAND_COLOR = '#18AF90'
|
const BRAND_COLOR = '#18AF90'
|
||||||
|
|
||||||
const preferenceTutorialElement = (
|
const preferenceTutorialElement = (
|
||||||
@@ -109,7 +105,7 @@ export default class ArticleNavigator extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { status, folders, allArticles } = this.props
|
let { status, user, folders, allArticles } = this.props
|
||||||
let { targetFolders } = status
|
let { targetFolders } = status
|
||||||
if (targetFolders == null) targetFolders = []
|
if (targetFolders == null) targetFolders = []
|
||||||
|
|
||||||
@@ -127,7 +123,7 @@ export default class ArticleNavigator extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className='ArticleNavigator'>
|
<div className='ArticleNavigator'>
|
||||||
<div className='userInfo'>
|
<div className='userInfo'>
|
||||||
<div className='userProfileName'>{userName}</div>
|
<div className='userProfileName'>{user.name}</div>
|
||||||
<div className='userName'>localStorage</div>
|
<div className='userName'>localStorage</div>
|
||||||
<button onClick={e => this.handlePreferencesButtonClick(e)} className='settingBtn'>
|
<button onClick={e => this.handlePreferencesButtonClick(e)} className='settingBtn'>
|
||||||
<i className='fa fa-fw fa-chevron-down'/>
|
<i className='fa fa-fw fa-chevron-down'/>
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ ipc.on('notify', function (e, payload) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipc.on('copy-finder', function () {
|
||||||
|
activityRecord.emit('FINDER_COPY')
|
||||||
|
})
|
||||||
|
ipc.on('open-finder', function () {
|
||||||
|
activityRecord.emit('FINDER_OPEN')
|
||||||
|
})
|
||||||
|
|
||||||
let routes = (
|
let routes = (
|
||||||
<Route path='/' component={MainPage}>
|
<Route path='/' component={MainPage}>
|
||||||
<IndexRoute name='home' component={HomePage}/>
|
<IndexRoute name='home' component={HomePage}/>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ body
|
|||||||
width 100%
|
width 100%
|
||||||
height 100%
|
height 100%
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
button, input
|
||||||
|
font-family "Lato"
|
||||||
|
|
||||||
.Finder
|
.Finder
|
||||||
absolute top bottom left right
|
absolute top bottom left right
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const app = electron.app
|
|||||||
const Tray = electron.Tray
|
const Tray = electron.Tray
|
||||||
const Menu = electron.Menu
|
const Menu = electron.Menu
|
||||||
const MenuItem = electron.MenuItem
|
const MenuItem = electron.MenuItem
|
||||||
|
const ipcMain = electron.ipcMain
|
||||||
|
|
||||||
process.stdin.setEncoding('utf8')
|
process.stdin.setEncoding('utf8')
|
||||||
|
|
||||||
@@ -63,6 +64,10 @@ app.on('ready', function () {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('copy-finder', function () {
|
||||||
|
emit('copy-finder')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
global.hideFinder = function () {
|
global.hideFinder = function () {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
// Action types
|
// Action types
|
||||||
|
export const USER_UPDATE = 'USER_UPDATE'
|
||||||
|
|
||||||
export const CLEAR_NEW_ARTICLE = 'CLEAR_NEW_ARTICLE'
|
export const CLEAR_NEW_ARTICLE = 'CLEAR_NEW_ARTICLE'
|
||||||
export const ARTICLE_UPDATE = 'ARTICLE_UPDATE'
|
export const ARTICLE_UPDATE = 'ARTICLE_UPDATE'
|
||||||
export const ARTICLE_DESTROY = 'ARTICLE_DESTROY'
|
export const ARTICLE_DESTROY = 'ARTICLE_DESTROY'
|
||||||
@@ -24,6 +26,13 @@ export const EDIT_MODE = 'EDIT_MODE'
|
|||||||
// Article status
|
// Article status
|
||||||
export const NEW = 'NEW'
|
export const NEW = 'NEW'
|
||||||
|
|
||||||
|
export function updateUser (input) {
|
||||||
|
return {
|
||||||
|
type: USER_UPDATE,
|
||||||
|
data: input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DB
|
// DB
|
||||||
export function clearNewArticle () {
|
export function clearNewArticle () {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React, { PropTypes } from 'react'
|
||||||
import linkState from 'boost/linkState'
|
import linkState from 'boost/linkState'
|
||||||
|
import { updateUser } from 'boost/actions'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const ipc = electron.ipcRenderer
|
const ipc = electron.ipcRenderer
|
||||||
@@ -9,24 +10,32 @@ export default class AppSettingTab extends React.Component {
|
|||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
let keymap = remote.getGlobal('keymap')
|
let keymap = remote.getGlobal('keymap')
|
||||||
|
let userName = props.user != null ? props.user.name : null
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
toggleFinder: keymap.toggleFinder,
|
user: {
|
||||||
alert: null
|
name: userName,
|
||||||
|
alert: null
|
||||||
|
},
|
||||||
|
userAlert: null,
|
||||||
|
keymap: {
|
||||||
|
toggleFinder: keymap.toggleFinder
|
||||||
|
},
|
||||||
|
keymapAlert: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.handleSettingDone = () => {
|
this.handleSettingDone = () => {
|
||||||
this.setState({alert: {
|
this.setState({keymapAlert: {
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: 'Successfully done!'
|
message: 'Successfully done!'
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
this.handleSettingError = err => {
|
this.handleSettingError = err => {
|
||||||
this.setState({alert: {
|
this.setState({keymapAlert: {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: err.message
|
message: err.message != null ? err.message : 'Error occurs!'
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||||
@@ -40,7 +49,7 @@ export default class AppSettingTab extends React.Component {
|
|||||||
|
|
||||||
submitHotKey () {
|
submitHotKey () {
|
||||||
ipc.send('hotkeyUpdated', {
|
ipc.send('hotkeyUpdated', {
|
||||||
toggleFinder: this.state.toggleFinder
|
toggleFinder: this.state.keymap.toggleFinder
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,25 +63,56 @@ export default class AppSettingTab extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNameSaveButtonClick (e) {
|
||||||
|
let { dispatch } = this.props
|
||||||
|
|
||||||
|
dispatch(updateUser({name: this.state.user.name}))
|
||||||
|
this.setState({
|
||||||
|
userAlert: {
|
||||||
|
type: 'success',
|
||||||
|
message: 'Successfully done!'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let alert = this.state.alert
|
let keymapAlert = this.state.keymapAlert
|
||||||
let alertElement = alert != null ? (
|
let keymapAlertElement = keymapAlert != null
|
||||||
<p className={`alert ${alert.type}`}>
|
? (
|
||||||
{alert.message}
|
<p className={`alert ${keymapAlert.type}`}>
|
||||||
|
{keymapAlert.message}
|
||||||
|
</p>
|
||||||
|
) : null
|
||||||
|
let userAlert = this.state.userAlert
|
||||||
|
let userAlertElement = userAlert != null
|
||||||
|
? (
|
||||||
|
<p className={`alert ${userAlert.type}`}>
|
||||||
|
{userAlert.message}
|
||||||
</p>
|
</p>
|
||||||
) : null
|
) : null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='AppSettingTab content'>
|
<div className='AppSettingTab content'>
|
||||||
|
<div className='section'>
|
||||||
|
<div className='sectionTitle'>User's info</div>
|
||||||
|
<div className='sectionInput'>
|
||||||
|
<label>User name</label>
|
||||||
|
<input valueLink={this.linkState('user.name')} type='text'/>
|
||||||
|
</div>
|
||||||
|
<div className='sectionConfirm'>
|
||||||
|
<button onClick={e => this.handleNameSaveButtonClick(e)}>Save</button>
|
||||||
|
{userAlertElement}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className='section'>
|
<div className='section'>
|
||||||
<div className='sectionTitle'>Hotkey</div>
|
<div className='sectionTitle'>Hotkey</div>
|
||||||
<div className='sectionInput'>
|
<div className='sectionInput'>
|
||||||
<label>Toggle Finder(popup)</label>
|
<label>Toggle Finder(popup)</label>
|
||||||
<input onKeyDown={e => this.handleKeyDown(e)} valueLink={this.linkState('toggleFinder')} type='text'/>
|
<input onKeyDown={e => this.handleKeyDown(e)} valueLink={this.linkState('keymap.toggleFinder')} type='text'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='sectionConfirm'>
|
<div className='sectionConfirm'>
|
||||||
<button onClick={e => this.handleSaveButtonClick(e)}>Save</button>
|
<button onClick={e => this.handleSaveButtonClick(e)}>Save</button>
|
||||||
{alertElement}
|
{keymapAlertElement}
|
||||||
</div>
|
</div>
|
||||||
<div className='description'>
|
<div className='description'>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -101,3 +141,6 @@ export default class AppSettingTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppSettingTab.prototype.linkState = linkState
|
AppSettingTab.prototype.linkState = linkState
|
||||||
|
AppSettingTab.propTypes = {
|
||||||
|
dispatch: PropTypes.func
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class Preferences extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderContent () {
|
renderContent () {
|
||||||
let { folders, dispatch } = this.props
|
let { user, folders, dispatch } = this.props
|
||||||
|
|
||||||
switch (this.state.currentTab) {
|
switch (this.state.currentTab) {
|
||||||
case HELP:
|
case HELP:
|
||||||
@@ -80,12 +80,20 @@ class Preferences extends React.Component {
|
|||||||
)
|
)
|
||||||
case APP:
|
case APP:
|
||||||
default:
|
default:
|
||||||
return (<AppSettingTab/>)
|
return (
|
||||||
|
<AppSettingTab
|
||||||
|
user={user}
|
||||||
|
dispatch={dispatch}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Preferences.propTypes = {
|
Preferences.propTypes = {
|
||||||
|
user: PropTypes.shape({
|
||||||
|
name: PropTypes.string
|
||||||
|
}),
|
||||||
folders: PropTypes.array,
|
folders: PropTypes.array,
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func
|
||||||
}
|
}
|
||||||
@@ -93,9 +101,10 @@ Preferences.propTypes = {
|
|||||||
Preferences.prototype.linkState = linkState
|
Preferences.prototype.linkState = linkState
|
||||||
|
|
||||||
function remap (state) {
|
function remap (state) {
|
||||||
let { folders, status } = state
|
let { user, folders, status } = state
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
user,
|
||||||
folders,
|
folders,
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import keygen from 'boost/keygen'
|
import keygen from 'boost/keygen'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const remote = electron.remote
|
const remote = electron.remote
|
||||||
const jetpack = require('fs-jetpack')
|
const jetpack = require('fs-jetpack')
|
||||||
@@ -10,15 +12,66 @@ function getLocalPath () {
|
|||||||
return path.join(remote.app.getPath('userData'), 'local.json')
|
return path.join(remote.app.getPath('userData'), 'local.json')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function forgeInitialRepositories () {
|
||||||
|
return [{
|
||||||
|
key: keygen(),
|
||||||
|
name: 'local',
|
||||||
|
type: 'userData',
|
||||||
|
user: {
|
||||||
|
name: remote.getGlobal('process').env.USER
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRepositories () {
|
||||||
|
let raw = localStorage.getItem('repositories')
|
||||||
|
try {
|
||||||
|
let parsed = JSON.parse(raw)
|
||||||
|
if (!_.isArray(parsed)) {
|
||||||
|
throw new Error('repositories data is currupte. 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 () {
|
export function init () {
|
||||||
console.log('initialize data store')
|
// set repositories info
|
||||||
|
getRepositories()
|
||||||
|
|
||||||
|
// set local.json
|
||||||
let data = jetpack.read(getLocalPath(), 'json')
|
let data = jetpack.read(getLocalPath(), 'json')
|
||||||
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
|
// for 0.4.1 -> 0.4.2
|
||||||
if (localStorage.getItem('local') != null) {
|
if (localStorage.getItem('local') != null) {
|
||||||
data = JSON.parse(localStorage.getItem('local'))
|
data = JSON.parse(localStorage.getItem('local'))
|
||||||
jetpack.write(getLocalPath(), data)
|
jetpack.write(getLocalPath(), data)
|
||||||
localStorage.removeItem('local')
|
localStorage.removeItem('local')
|
||||||
|
console.log('update 0.4.1 => 0.4.2')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +123,8 @@ export default (function () {
|
|||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
getUser,
|
||||||
|
saveUser,
|
||||||
init,
|
init,
|
||||||
getData,
|
getData,
|
||||||
setArticles,
|
setArticles,
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ var crypto = require('crypto')
|
|||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
var shasum = crypto.createHash('sha1')
|
var shasum = crypto.createHash('sha1')
|
||||||
shasum.update(((new Date()).getTime()).toString())
|
shasum.update(((new Date()).getTime() + Math.round(Math.random()*1000)).toString())
|
||||||
return shasum.digest('hex')
|
return shasum.digest('hex')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import {
|
|||||||
UNLOCK_STATUS,
|
UNLOCK_STATUS,
|
||||||
TOGGLE_TUTORIAL,
|
TOGGLE_TUTORIAL,
|
||||||
|
|
||||||
|
// user
|
||||||
|
USER_UPDATE,
|
||||||
|
|
||||||
// Article action type
|
// Article action type
|
||||||
ARTICLE_UPDATE,
|
ARTICLE_UPDATE,
|
||||||
ARTICLE_DESTROY,
|
ARTICLE_DESTROY,
|
||||||
@@ -42,10 +45,22 @@ const initialStatus = {
|
|||||||
let data = dataStore.getData()
|
let data = dataStore.getData()
|
||||||
let initialArticles = data.articles
|
let initialArticles = data.articles
|
||||||
let initialFolders = data.folders
|
let initialFolders = data.folders
|
||||||
|
let initialUser = dataStore.getUser().user
|
||||||
|
|
||||||
let isStatusLocked = false
|
let isStatusLocked = false
|
||||||
let isCreatingNew = false
|
let isCreatingNew = false
|
||||||
|
|
||||||
|
function user (state = initialUser, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case USER_UPDATE:
|
||||||
|
let updated = Object.assign(state, action.data)
|
||||||
|
dataStore.saveUser(null, updated)
|
||||||
|
return updated
|
||||||
|
default:
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function folders (state = initialFolders, action) {
|
function folders (state = initialFolders, action) {
|
||||||
state = state.slice()
|
state = state.slice()
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@@ -250,6 +265,7 @@ function status (state = initialStatus, action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
|
user,
|
||||||
folders,
|
folders,
|
||||||
articles,
|
articles,
|
||||||
status
|
status
|
||||||
|
|||||||
9
main.js
9
main.js
@@ -128,9 +128,10 @@ app.on('ready', function () {
|
|||||||
console.log('FINDER(stdout): ' + payload.data)
|
console.log('FINDER(stdout): ' + payload.data)
|
||||||
break
|
break
|
||||||
case 'show-main-window':
|
case 'show-main-window':
|
||||||
if (mainWindow != null) {
|
mainWindow.show()
|
||||||
mainWindow.show()
|
break
|
||||||
}
|
case 'copy-finder':
|
||||||
|
mainWindow.webContents.send('copy-finder')
|
||||||
break
|
break
|
||||||
case 'request-data':
|
case 'request-data':
|
||||||
mainWindow.webContents.send('request-data')
|
mainWindow.webContents.send('request-data')
|
||||||
@@ -173,6 +174,7 @@ app.on('ready', function () {
|
|||||||
try {
|
try {
|
||||||
globalShortcut.register(toggleFinderKey, function () {
|
globalShortcut.register(toggleFinderKey, function () {
|
||||||
emitToFinder('open-finder')
|
emitToFinder('open-finder')
|
||||||
|
mainWindow.webContents.send('open-finder', {})
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err.name)
|
console.log(err.name)
|
||||||
@@ -189,6 +191,7 @@ app.on('ready', function () {
|
|||||||
try {
|
try {
|
||||||
globalShortcut.register(toggleFinderKey, function () {
|
globalShortcut.register(toggleFinderKey, function () {
|
||||||
emitToFinder('open-finder')
|
emitToFinder('open-finder')
|
||||||
|
mainWindow.webContents.send('open-finder', {})
|
||||||
})
|
})
|
||||||
mainWindow.webContents.send('APP_SETTING_DONE', {})
|
mainWindow.webContents.send('APP_SETTING_DONE', {})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "boost",
|
"name": "boost",
|
||||||
"version": "0.4.3",
|
"version": "0.4.4",
|
||||||
"description": "Boost App",
|
"description": "Boost App",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user