diff --git a/atom-lib/finder-window.js b/atom-lib/finder-window.js index 01bc6eac..466c40b5 100644 --- a/atom-lib/finder-window.js +++ b/atom-lib/finder-window.js @@ -25,4 +25,6 @@ finderWindow.on('blur', function () { finderWindow.hide() }) +finderWindow.setVisibleOnAllWorkspaces(true) + module.exports = finderWindow diff --git a/browser/finder/index.js b/browser/finder/index.js index f845bbcf..c72987f2 100644 --- a/browser/finder/index.js +++ b/browser/finder/index.js @@ -11,7 +11,7 @@ import _ from 'lodash' import dataStore from 'boost/dataStore' const electron = require('electron') -const { remote, clipboard } = electron +const { remote, clipboard, ipcRenderer } = electron var hideFinder = remote.getGlobal('hideFinder') @@ -64,6 +64,7 @@ class FinderMain extends React.Component { let { activeArticle } = this.props clipboard.writeText(activeArticle.content) + ipcRenderer.send('copy-finder') notify('Saved to Clipboard!', { body: 'Paste it wherever you want!' }) @@ -152,6 +153,14 @@ function buildFilter (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) { let { articles, folders, status } = state @@ -168,10 +177,10 @@ function remap (state) { let targetFolders if (folders != null) { 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 => { - 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) @@ -184,7 +193,7 @@ function remap (state) { if (textFilters.length > 0) { articles = textFilters.reduce((articles, textFilter) => { 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) } @@ -192,7 +201,7 @@ function remap (state) { if (tagFilters.length > 0) { articles = tagFilters.reduce((articles, tagFilter) => { 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) } @@ -201,7 +210,6 @@ function remap (state) { let activeArticle = _.findWhere(articles, {key: status.articleKey}) if (activeArticle == null) activeArticle = articles[0] - console.log(status.search) return { articles, activeArticle, diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index 69c65948..cc0c127a 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -1,13 +1,13 @@ import React, { PropTypes} from 'react' import { connect } from 'react-redux' -import { EDIT_MODE, IDLE_MODE, NEW, toggleTutorial } from 'boost/actions' -// import UserNavigator from './HomePage/UserNavigator' +import { EDIT_MODE, IDLE_MODE, toggleTutorial } from 'boost/actions' import ArticleNavigator from './HomePage/ArticleNavigator' import ArticleTopBar from './HomePage/ArticleTopBar' import ArticleList from './HomePage/ArticleList' import ArticleDetail from './HomePage/ArticleDetail' import _ from 'lodash' import { isModalOpen, closeModal } from 'boost/modal' + const electron = require('electron') const BrowserWindow = electron.remote.BrowserWindow @@ -114,13 +114,14 @@ class HomePage extends React.Component { } 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 (
{ @@ -199,10 +208,10 @@ function remap (state) { let targetFolders if (folders != null) { 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 => { - 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) @@ -215,7 +224,7 @@ function remap (state) { if (textFilters.length > 0) { articles = textFilters.reduce((articles, textFilter) => { 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) } @@ -223,7 +232,7 @@ function remap (state) { if (tagFilters.length > 0) { articles = tagFilters.reduce((articles, tagFilter) => { 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) } @@ -234,6 +243,7 @@ function remap (state) { if (activeArticle == null) activeArticle = articles[0] return { + user, folders, status, allArticles, @@ -249,11 +259,9 @@ function remap (state) { } HomePage.propTypes = { - params: PropTypes.shape({ - userId: PropTypes.string - }), - status: PropTypes.shape({ - userId: PropTypes.string + status: PropTypes.shape(), + user: PropTypes.shape({ + name: PropTypes.string }), articles: PropTypes.array, allArticles: PropTypes.array, diff --git a/browser/main/HomePage/ArticleNavigator.js b/browser/main/HomePage/ArticleNavigator.js index 269d528f..a2f6755f 100644 --- a/browser/main/HomePage/ArticleNavigator.js +++ b/browser/main/HomePage/ArticleNavigator.js @@ -7,10 +7,6 @@ import Preferences from 'boost/components/modal/Preferences' import CreateNewFolder from 'boost/components/modal/CreateNewFolder' 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 preferenceTutorialElement = ( @@ -109,7 +105,7 @@ export default class ArticleNavigator extends React.Component { } render () { - let { status, folders, allArticles } = this.props + let { status, user, folders, allArticles } = this.props let { targetFolders } = status if (targetFolders == null) targetFolders = [] @@ -127,7 +123,7 @@ export default class ArticleNavigator extends React.Component { return (
-
{userName}
+
{user.name}
localStorage
+ {userAlertElement} +
+
Hotkey
- this.handleKeyDown(e)} valueLink={this.linkState('toggleFinder')} type='text'/> + this.handleKeyDown(e)} valueLink={this.linkState('keymap.toggleFinder')} type='text'/>
- {alertElement} + {keymapAlertElement}
    @@ -101,3 +141,6 @@ export default class AppSettingTab extends React.Component { } AppSettingTab.prototype.linkState = linkState +AppSettingTab.propTypes = { + dispatch: PropTypes.func +} diff --git a/lib/components/modal/Preferences.js b/lib/components/modal/Preferences.js index 51813751..a1b4f4a2 100644 --- a/lib/components/modal/Preferences.js +++ b/lib/components/modal/Preferences.js @@ -62,7 +62,7 @@ class Preferences extends React.Component { } renderContent () { - let { folders, dispatch } = this.props + let { user, folders, dispatch } = this.props switch (this.state.currentTab) { case HELP: @@ -80,12 +80,20 @@ class Preferences extends React.Component { ) case APP: default: - return () + return ( + + ) } } } Preferences.propTypes = { + user: PropTypes.shape({ + name: PropTypes.string + }), folders: PropTypes.array, dispatch: PropTypes.func } @@ -93,9 +101,10 @@ Preferences.propTypes = { Preferences.prototype.linkState = linkState function remap (state) { - let { folders, status } = state + let { user, folders, status } = state return { + user, folders, status } diff --git a/lib/dataStore.js b/lib/dataStore.js index 128c634d..e8b62af4 100644 --- a/lib/dataStore.js +++ b/lib/dataStore.js @@ -1,4 +1,6 @@ import keygen from 'boost/keygen' +import _ from 'lodash' + const electron = require('electron') const remote = electron.remote const jetpack = require('fs-jetpack') @@ -10,15 +12,66 @@ function getLocalPath () { 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 () { - console.log('initialize data store') + // set repositories info + getRepositories() + + // set local.json let data = jetpack.read(getLocalPath(), 'json') if (data == null) { + // for 0.4.1 -> 0.4.2 if (localStorage.getItem('local') != null) { data = JSON.parse(localStorage.getItem('local')) jetpack.write(getLocalPath(), data) localStorage.removeItem('local') + console.log('update 0.4.1 => 0.4.2') return } @@ -70,6 +123,8 @@ export default (function () { init() } return { + getUser, + saveUser, init, getData, setArticles, diff --git a/lib/keygen.js b/lib/keygen.js index 4cc04385..da8cf6b1 100644 --- a/lib/keygen.js +++ b/lib/keygen.js @@ -2,6 +2,6 @@ var crypto = require('crypto') module.exports = function () { 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') } diff --git a/lib/reducer.js b/lib/reducer.js index 4ca9d268..e125848b 100644 --- a/lib/reducer.js +++ b/lib/reducer.js @@ -12,6 +12,9 @@ import { UNLOCK_STATUS, TOGGLE_TUTORIAL, + // user + USER_UPDATE, + // Article action type ARTICLE_UPDATE, ARTICLE_DESTROY, @@ -42,10 +45,22 @@ const initialStatus = { let data = dataStore.getData() let initialArticles = data.articles let initialFolders = data.folders +let initialUser = dataStore.getUser().user let isStatusLocked = 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) { state = state.slice() switch (action.type) { @@ -250,6 +265,7 @@ function status (state = initialStatus, action) { } export default combineReducers({ + user, folders, articles, status diff --git a/main.js b/main.js index f55d7c70..205f60a5 100644 --- a/main.js +++ b/main.js @@ -128,9 +128,10 @@ app.on('ready', function () { console.log('FINDER(stdout): ' + payload.data) break case 'show-main-window': - if (mainWindow != null) { - mainWindow.show() - } + mainWindow.show() + break + case 'copy-finder': + mainWindow.webContents.send('copy-finder') break case 'request-data': mainWindow.webContents.send('request-data') @@ -173,6 +174,7 @@ app.on('ready', function () { try { globalShortcut.register(toggleFinderKey, function () { emitToFinder('open-finder') + mainWindow.webContents.send('open-finder', {}) }) } catch (err) { console.log(err.name) @@ -189,6 +191,7 @@ app.on('ready', function () { try { globalShortcut.register(toggleFinderKey, function () { emitToFinder('open-finder') + mainWindow.webContents.send('open-finder', {}) }) mainWindow.webContents.send('APP_SETTING_DONE', {}) } catch (err) { diff --git a/package.json b/package.json index 827a3e4d..7bc93958 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "boost", - "version": "0.4.3", + "version": "0.4.4", "description": "Boost App", "main": "index.js", "scripts": {