From 9785df8bfbe4e5c048c9538de5ccf3dfdfb07ae4 Mon Sep 17 00:00:00 2001 From: Clive Young Date: Mon, 2 May 2016 21:59:49 +0800 Subject: [PATCH] add a form to set password --- app/index.js | 16 ++ dist/bar.js | 258 +++++++++++++++++++++++++++++--- package.json | 9 +- src/actions/index.jsx | 12 +- src/bar.jsx | 42 +++++- src/components/App.jsx | 27 +++- src/components/SettingsForm.jsx | 28 ++++ src/containers/SettingsForm.jsx | 28 ++++ src/reducers/index.jsx | 3 +- src/reducers/settings.jsx | 14 ++ 10 files changed, 406 insertions(+), 31 deletions(-) create mode 100644 src/components/SettingsForm.jsx create mode 100644 src/containers/SettingsForm.jsx create mode 100644 src/reducers/settings.jsx diff --git a/app/index.js b/app/index.js index 8f67bbc..b021e30 100644 --- a/app/index.js +++ b/app/index.js @@ -23,6 +23,22 @@ menu.on('ready', () => { globalShortcut.register('Control+3', () => { menu.window.webContents.send('key', 2); }); + + globalShortcut.register('Option+1', () => { + menu.window.webContents.send('keyPassword', 0); + }); + + globalShortcut.register('Option+2', () => { + menu.window.webContents.send('keyPassword', 1); + }); + + globalShortcut.register('Option+3', () => { + menu.window.webContents.send('keyPassword', 2); + }); + + globalShortcut.register('Control+0', () => { + menu.window.webContents.send('password', ''); + }); }); ipcMain.on('copy', (event, arg) => { diff --git a/dist/bar.js b/dist/bar.js index b99ad10..cbe1cf8 100644 --- a/dist/bar.js +++ b/dist/bar.js @@ -72,7 +72,11 @@ var _KeyForm2 = _interopRequireDefault(_KeyForm); - var _reducers = __webpack_require__(295); + var _SettingsForm = __webpack_require__(295); + + var _SettingsForm2 = _interopRequireDefault(_SettingsForm); + + var _reducers = __webpack_require__(297); var _reducers2 = _interopRequireDefault(_reducers); @@ -85,7 +89,7 @@ var store = (0, _redux.createStore)(_reducers2.default, state); store.subscribe(function () { - state = store.getState(); + var state = store.getState(); localStorage.setItem('state', JSON.stringify(state)); }); @@ -99,13 +103,14 @@ _reactRouter.Route, { path: '/', component: _App2.default }, _react2.default.createElement(_reactRouter.IndexRoute, { component: _Dashboard2.default }), - _react2.default.createElement(_reactRouter.Route, { path: 'add', component: _KeyForm2.default }) + _react2.default.createElement(_reactRouter.Route, { path: 'add', component: _KeyForm2.default }), + _react2.default.createElement(_reactRouter.Route, { path: 'settings', component: _SettingsForm2.default }) ) ) ), document.getElementById('app')); electron.ipcRenderer.on('key', function (event, message) { - state = store.getState(); + var state = store.getState(); var key = state.keys[message]; if (!key) { @@ -116,6 +121,42 @@ electron.ipcRenderer.send('copy', token); }); + electron.ipcRenderer.on('keyPassword', function (event, message) { + var state = store.getState(); + var key = state.keys[message]; + + if (!key) { + return; + } + + if (!state.settings) { + return; + } + + if (!state.settings.password) { + return; + } + + var password = state.settings.password; + var token = (0, _helpers.getToken)(state.keys[message].key); + electron.ipcRenderer.send('copy', password + token); + }); + + electron.ipcRenderer.on('password', function (event, message) { + var state = store.getState(); + + if (!state.settings) { + return; + } + + if (!state.settings.password) { + return; + } + + var password = state.settings.password; + electron.ipcRenderer.send('copy', password); + }); + /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { @@ -27652,6 +27693,28 @@ 'h1', { className: 'title' }, '两步验证' + ), + _react2.default.createElement( + 'div', + { className: 'toolbar-actions' }, + _react2.default.createElement( + 'button', + { className: 'btn btn-default', + onClick: function onClick() { + _reactRouter.hashHistory.push('/settings'); + } }, + _react2.default.createElement('span', { className: 'icon icon-home' }), + '设置' + ), + _react2.default.createElement( + 'button', + { className: 'btn btn-default pull-right', + onClick: function onClick() { + _reactRouter.hashHistory.push('/add'); + } }, + _react2.default.createElement('span', { className: 'icon icon-plus' }), + '增加' + ) ) ), _react2.default.createElement( @@ -27667,19 +27730,11 @@ { className: 'toolbar-actions' }, _react2.default.createElement( 'button', - { type: 'button', className: 'btn btn-default', + { type: 'button', className: 'btn btn-default pull-right', onClick: function onClick() { electron.ipcRenderer.send('exit'); } }, '退出' - ), - _react2.default.createElement( - 'button', - { type: 'button', className: 'btn btn-primary pull-right', - onClick: function onClick() { - _reactRouter.hashHistory.push('/add'); - } }, - '增加' ) ) ) @@ -34082,7 +34137,6 @@ value: true }); var ADD_KEY = exports.ADD_KEY = 'ADD_KEY'; - var REMOVE_KEY = exports.REMOVE_KEY = 'REMOVE_KEY'; var addKey = exports.addKey = function addKey(key, comment) { return { @@ -34092,6 +34146,8 @@ }; }; + var REMOVE_KEY = exports.REMOVE_KEY = 'REMOVE_KEY'; + var removeKey = exports.removeKey = function removeKey(id) { return { type: REMOVE_KEY, @@ -34099,6 +34155,15 @@ }; }; + var SET_PASSWORD = exports.SET_PASSWORD = 'SET_PASSWORD'; + + var setPassword = exports.setPassword = function setPassword(password) { + return { + type: SET_PASSWORD, + password: password + }; + }; + /***/ }, /* 293 */ /***/ function(module, exports, __webpack_require__) { @@ -34237,22 +34302,149 @@ 'use strict'; + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _SettingsForm = __webpack_require__(296); + + var _SettingsForm2 = _interopRequireDefault(_SettingsForm); + + var _reactRedux = __webpack_require__(246); + + var _reactRouter = __webpack_require__(172); + + var _actions = __webpack_require__(292); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + var mapStateToProps = function mapStateToProps(state) { + return { + password: state.settings.password + }; + }; + + var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + onSubmit: function onSubmit(password) { + dispatch((0, _actions.setPassword)(password)); + _reactRouter.hashHistory.push('/'); + }, + onCancel: function onCancel() { + _reactRouter.hashHistory.push('/'); + } + }; + }; + + exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(_SettingsForm2.default); + +/***/ }, +/* 296 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + var _react = __webpack_require__(5); + + var _react2 = _interopRequireDefault(_react); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + var SettingsForm = function (_React$Component) { + _inherits(SettingsForm, _React$Component); + + function SettingsForm() { + _classCallCheck(this, SettingsForm); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(SettingsForm).apply(this, arguments)); + } + + _createClass(SettingsForm, [{ + key: 'render', + value: function render() { + var _this2 = this; + + return _react2.default.createElement( + 'form', + { style: { padding: '10px' }, onSubmit: function onSubmit(e) { + e.preventDefault(); + _this2.props.onSubmit(_this2.refs.password.value); + } }, + _react2.default.createElement( + 'div', + { className: 'form-group' }, + _react2.default.createElement( + 'label', + null, + '密码' + ), + _react2.default.createElement('input', { type: 'password', + className: 'form-control', + defaultValue: this.props.password, + ref: 'password' }) + ), + _react2.default.createElement( + 'div', + { className: 'form-actions' }, + _react2.default.createElement( + 'button', + { onClick: this.props.onCancel, type: 'button', + className: 'btn btn-form btn-default' }, + '取消' + ), + _react2.default.createElement( + 'button', + { type: 'submit', className: 'btn btn-form btn-primary' }, + '保存' + ) + ) + ); + } + }]); + + return SettingsForm; + }(_react2.default.Component); + + exports.default = SettingsForm; + +/***/ }, +/* 297 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + Object.defineProperty(exports, "__esModule", { value: true }); var _redux = __webpack_require__(233); - var _keys = __webpack_require__(296); + var _keys = __webpack_require__(298); var _keys2 = _interopRequireDefault(_keys); + var _settings = __webpack_require__(299); + + var _settings2 = _interopRequireDefault(_settings); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - exports.default = (0, _redux.combineReducers)({ keys: _keys2.default }); + exports.default = (0, _redux.combineReducers)({ keys: _keys2.default, settings: _settings2.default }); /***/ }, -/* 296 */ +/* 298 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; @@ -34291,5 +34483,37 @@ exports.default = keys; +/***/ }, +/* 299 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _actions = __webpack_require__(292); + + var actions = _interopRequireWildcard(_actions); + + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + + var settings = function settings() { + var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + case actions.SET_PASSWORD: + return { + password: action.password + }; + default: + return state; + } + }; + + exports.default = settings; + /***/ } /******/ ]); \ No newline at end of file diff --git a/package.json b/package.json index 61b292d..2de7bfb 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,13 @@ "scripts": { "test": "mocha", "start": "electron ./", - "build": "webpack && electron-packager . Authenticator --platform=darwin --arch=x64", - "dev": "webpack-dev-server --inline" + "build": "webpack", + "dev": "webpack-dev-server --inline", + "package": "electron-packager . Authenticator --platform=darwin --arch=x64" + }, + "repository": { + "type": "git", + "url": "https://github.com/yangmls/authenticator" }, "author": "Clive Young", "license": "MIT", diff --git a/src/actions/index.jsx b/src/actions/index.jsx index eed9987..722b5c8 100644 --- a/src/actions/index.jsx +++ b/src/actions/index.jsx @@ -1,5 +1,4 @@ export const ADD_KEY = 'ADD_KEY'; -export const REMOVE_KEY = 'REMOVE_KEY'; export const addKey = (key, comment) => { return { @@ -9,9 +8,20 @@ export const addKey = (key, comment) => { } } +export const REMOVE_KEY = 'REMOVE_KEY'; + export const removeKey = (id) => { return { type: REMOVE_KEY, id } } + +export const SET_PASSWORD = 'SET_PASSWORD'; + +export const setPassword = (password) => { + return { + type: SET_PASSWORD, + password + } +} diff --git a/src/bar.jsx b/src/bar.jsx index 6db704c..ee54543 100644 --- a/src/bar.jsx +++ b/src/bar.jsx @@ -9,6 +9,7 @@ import { Provider } from 'react-redux' import App from './components/App' import Dashboard from './containers/Dashboard' import KeyForm from './containers/KeyForm' +import SettingsForm from './containers/SettingsForm' import reducers from './reducers' @@ -19,7 +20,7 @@ let state = JSON.parse(localStorage.getItem('state') || '{}') const store = createStore(reducers, state) store.subscribe(() => { - state = store.getState() + let state = store.getState() localStorage.setItem('state', JSON.stringify(state)) }); @@ -29,6 +30,7 @@ render( + , @@ -36,7 +38,7 @@ render( ); electron.ipcRenderer.on('key', (event, message) => { - state = store.getState(); + let state = store.getState(); let key = state.keys[message]; if (!key) { @@ -46,3 +48,39 @@ electron.ipcRenderer.on('key', (event, message) => { let token = getToken(state.keys[message].key) electron.ipcRenderer.send('copy', token) }); + +electron.ipcRenderer.on('keyPassword', (event, message) => { + let state = store.getState(); + let key = state.keys[message]; + + if (!key) { + return + } + + if (!state.settings) { + return + } + + if (!state.settings.password) { + return + } + + let password = state.settings.password + let token = getToken(state.keys[message].key) + electron.ipcRenderer.send('copy', password + token) +}); + +electron.ipcRenderer.on('password', (event, message) => { + let state = store.getState(); + + if (!state.settings) { + return + } + + if (!state.settings.password) { + return + } + + let password = state.settings.password + electron.ipcRenderer.send('copy', password) +}); diff --git a/src/components/App.jsx b/src/components/App.jsx index ff7c727..28b48a9 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -9,6 +9,24 @@ export default class App extends React.Component {

两步验证

+ +
+ + + +
@@ -17,19 +35,12 @@ export default class App extends React.Component {
- - -
diff --git a/src/components/SettingsForm.jsx b/src/components/SettingsForm.jsx new file mode 100644 index 0000000..df47b5f --- /dev/null +++ b/src/components/SettingsForm.jsx @@ -0,0 +1,28 @@ +import React from 'react'; + +export default class SettingsForm extends React.Component { + + render() { + return ( +
{ + e.preventDefault() + this.props.onSubmit(this.refs.password.value) + }}> +
+ + +
+ +
+ + +
+
+ ); + } + +} diff --git a/src/containers/SettingsForm.jsx b/src/containers/SettingsForm.jsx new file mode 100644 index 0000000..8de8b70 --- /dev/null +++ b/src/containers/SettingsForm.jsx @@ -0,0 +1,28 @@ +import SettingsForm from '../components/SettingsForm'; + +import { connect } from 'react-redux'; +import { hashHistory } from 'react-router'; +import { setPassword } from '../actions'; + +const mapStateToProps = (state) => { + return { + password: state.settings.password + }; +} + +const mapDispatchToProps = (dispatch) => { + return { + + onSubmit(password) { + dispatch(setPassword(password)) + hashHistory.push('/') + }, + + onCancel() { + hashHistory.push('/') + } + + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(SettingsForm); diff --git a/src/reducers/index.jsx b/src/reducers/index.jsx index 3c0c1f5..fb7884b 100644 --- a/src/reducers/index.jsx +++ b/src/reducers/index.jsx @@ -1,5 +1,6 @@ import { combineReducers } from 'redux'; import keys from './keys'; +import settings from './settings'; -export default combineReducers({keys}); +export default combineReducers({keys, settings}); diff --git a/src/reducers/settings.jsx b/src/reducers/settings.jsx new file mode 100644 index 0000000..3d4d954 --- /dev/null +++ b/src/reducers/settings.jsx @@ -0,0 +1,14 @@ +import * as actions from '../actions'; + +const settings = (state = {}, action) => { + switch (action.type) { + case actions.SET_PASSWORD: + return { + password: action.password + } + default: + return state; + } +}; + +export default settings;