├── .babelrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── app
├── app.jsx
├── footer.jsx
├── header.jsx
└── sidebar.jsx
├── assets
├── epp.icns
├── epp.ico
├── epp.png
└── screenshot.png
├── config.js
├── dev.html
├── index.html
├── index.js
├── index.scss
├── license
├── package.json
├── readme.md
├── scripts
├── menu.js
└── watcher.js
├── starter.js
├── styles
└── theme.scss
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "es2015"]
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [{package.json,*.yml}]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /dist
3 | *.swp
4 | app.js
5 | /out
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/app/app.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDom from "react-dom";
3 | import { Window, Content, PaneGroup ,Pane } from "react-photonkit";
4 |
5 | import Header from "./header.jsx"
6 | import Footer from "./footer.jsx";
7 | import Sidebar from "./sidebar.jsx"
8 |
9 | require('../index.scss');
10 |
11 | ReactDom.render(
12 |
13 |
14 |
15 |
16 |
17 |
18 | Hello, react-photonkit!!!
19 |
20 |
21 |
22 |
23 |
24 | , document.querySelector("#main"));
25 |
--------------------------------------------------------------------------------
/app/footer.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Toolbar } from "react-photonkit";
3 |
4 | class Footer extends React.Component {
5 | render() {
6 | return (
7 |
8 | );
9 | }
10 | }
11 |
12 | export default Footer;
13 |
--------------------------------------------------------------------------------
/app/header.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Toolbar, Actionbar, Button, ButtonGroup } from "react-photonkit";
3 |
4 | class Header extends React.Component {
5 | render() {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | );
16 | }
17 | }
18 |
19 | export default Header;
20 |
--------------------------------------------------------------------------------
/app/sidebar.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Pane, NavGroup, NavTitle, NavGroupItem } from "react-photonkit";
3 |
4 | class Sidebar extends React.Component {
5 | onSelect(index) {
6 | console.log(`sidebar clicked with ${index}`)
7 | }
8 |
9 | render() {
10 | return (
11 |
12 |
13 | nav group icon & text
14 |
15 |
16 |
17 |
18 | );
19 | }
20 | }
21 |
22 | export default Sidebar;
23 |
--------------------------------------------------------------------------------
/assets/epp.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-photonkit/epp/913c71a6c32625cec0bedcc47db85afbe9f93d01/assets/epp.icns
--------------------------------------------------------------------------------
/assets/epp.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-photonkit/epp/913c71a6c32625cec0bedcc47db85afbe9f93d01/assets/epp.ico
--------------------------------------------------------------------------------
/assets/epp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-photonkit/epp/913c71a6c32625cec0bedcc47db85afbe9f93d01/assets/epp.png
--------------------------------------------------------------------------------
/assets/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-photonkit/epp/913c71a6c32625cec0bedcc47db85afbe9f93d01/assets/screenshot.png
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | 'port': 8576
5 | };
6 |
--------------------------------------------------------------------------------
/dev.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | epp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | epp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const app = require('app');
3 | const BrowserWindow = require('browser-window');
4 | const Menu = require('menu')
5 | const template = require('./scripts/menu')
6 |
7 | // report crashes to the Electron project
8 | require('crash-reporter').start();
9 |
10 | // adds debug features like hotkeys for triggering dev tools and reload
11 | require('electron-debug')();
12 |
13 | // prevent window being garbage collected
14 | let mainWindow;
15 | var menu = Menu.buildFromTemplate(template);
16 |
17 | function onClosed() {
18 | // dereference the window
19 | // for multiple windows store them in an array
20 | mainWindow = null;
21 | }
22 |
23 | function createMainWindow() {
24 | const is2nd = process.argv.indexOf('--2nd') >= 0;
25 | var opts = {
26 | width: 1200,
27 | height: 600,
28 | 'accept-first-mouse': true,
29 | 'title-bar-style': 'hidden'
30 | };
31 | if (is2nd) {
32 | setOptsForDualScreen(opts);
33 | }
34 |
35 | const win = new BrowserWindow(opts);
36 | if (process.env.DEV) {
37 | win.loadUrl('http://localhost:8000/dev.html');
38 | win.openDevTools();
39 | } else {
40 | win.loadUrl(`file://${__dirname}/index.html`);
41 | }
42 | win.on('closed', onClosed);
43 |
44 | if (menu) {
45 | Menu.setApplicationMenu(menu);
46 | menu = null;
47 | }
48 |
49 | return win;
50 | }
51 |
52 | function setOptsForDualScreen(opts) {
53 | var atomScreen = require('screen');
54 | var displays = atomScreen.getAllDisplays();
55 | var d2 = displays.length > 1 ? displays[1] : null;
56 | if (d2) {
57 | opts.x = d2.bounds.x + (d2.size.width - opts.width) / 2;
58 | opts.y = d2.bounds.y + (d2.size.height - opts.height) / 2;
59 | }
60 | }
61 |
62 | app.on('window-all-closed', () => {
63 | app.quit();
64 | });
65 |
66 | app.on('activate-with-no-open-windows', () => {
67 | if (!mainWindow) {
68 | mainWindow = createMainWindow();
69 | }
70 | });
71 |
72 | app.on('ready', () => {
73 | mainWindow = createMainWindow();
74 |
75 | if (process.env.DEV) {
76 | const watcher = require('./scripts/watcher.js');
77 | watcher.watch(app, ['./index.js', './scripts']);
78 | }
79 | });
80 |
--------------------------------------------------------------------------------
/index.scss:
--------------------------------------------------------------------------------
1 | @import 'styles/theme.scss';
2 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) react-photon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "epp",
3 | "productName": "Epp",
4 | "version": "0.0.0",
5 | "description": "Electron Application",
6 | "license": "MIT",
7 | "repository": "react-photonkit/epp",
8 | "author": {
9 | "name": "Jaewe Heo",
10 | "email": "jaeweheo@gmail.com",
11 | "url": "import.re"
12 | },
13 | "engines": {
14 | "node": ">=4"
15 | },
16 | "electronVersion": "0.34.1",
17 | "scripts": {
18 | "test": "xo",
19 | "start": "node starter.js --2nd",
20 | "start-1st": "node starter.js",
21 | "build": "npm run build-osx && npm run build-win",
22 | "build-osx": "NODE_ENV=production webpack -p --config webpack.config.js && electron-packager . $npm_package_productName --overwrite --out=dist --ignore='^/dist$' --prune --asar --platform=darwin --arch=x64 --version=$npm_package_electronVersion --icon=assets/epp.icns",
23 | "build-win": "NODE_ENV=production webpack -p --config webpack.config.js && electron-packager . $npm_package_productName --overwrite --out=dist --ignore='^/dist$' --prune --asar --platform=win32 --arch=all --version=$npm_package_electronVersion --icon=assets/epp.ico"
24 | },
25 | "keywords": [
26 | "electron",
27 | "webpack",
28 | "react",
29 | "electron-app"
30 | ],
31 | "dependencies": {
32 | "electron-debug": "^0.2.1",
33 | "history": "^1.12.3",
34 | "object-assign": "^4.0.1",
35 | "react": "^0.14.1",
36 | "react-dom": "^0.14.1",
37 | "react-photonkit": "^0.3.2"
38 | },
39 | "devDependencies": {
40 | "babel-core": "^6.4.0",
41 | "babel-loader": "^6.2.1",
42 | "babel-preset-es2015": "^6.3.13",
43 | "babel-preset-react": "^6.3.13",
44 | "css-loader": "^0.19.0",
45 | "electron-packager": "^5.2.0",
46 | "electron-prebuilt": "^0.36.4",
47 | "file-loader": "^0.8.5",
48 | "json-loader": "^0.5.4",
49 | "node-sass": "^3.4.2",
50 | "sass-loader": "^3.0.0",
51 | "sleep": "^3.0.0",
52 | "style-loader": "^0.12.4",
53 | "url-loader": "^0.5.7",
54 | "webpack": "^1.12.2",
55 | "webpack-dev-server": "^1.12.0",
56 | "xo": "^0.9.0"
57 | },
58 | "xo": {
59 | "esnext": true,
60 | "envs": [
61 | "node",
62 | "browser"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # epp
2 |
3 |
4 |
5 | Electron aPPlication
6 |
7 | - photon
8 | - coffeescrirpt (cjsx)
9 | - electron
10 | - react
11 | - react-router
12 | - webpack
13 |
14 | ![screenshot]
15 |
16 |
17 | ## Dev
18 |
19 | ```sh
20 | # install dependencies
21 | $ npm install
22 |
23 | # support for reloading views, restarting electron
24 | # if app/* and/or index.js, electron/* are changed
25 | $ npm start
26 | ```
27 |
28 |
29 | ### Build
30 |
31 | ```sh
32 | $ npm run build # all
33 | $ npm run build-osx # osx(64)
34 | $ npm run build-win # win(32, 64)
35 | ```
36 |
37 |
38 | ## License
39 |
40 | MIT © react-photonkit
41 |
42 |
43 |
44 | [screenshot]: assets/screenshot.png
45 |
--------------------------------------------------------------------------------
/scripts/menu.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const app = require('app');
4 | const path = require('path');
5 | const dialog = require('dialog');
6 | const NativeImage = require('native-image');
7 |
8 | const appName = app.getName();
9 | const template = [{
10 | label: 'Edit',
11 | submenu: [{
12 | label: 'Undo',
13 | accelerator: 'CmdOrCtrl+Z',
14 | role: 'undo'
15 | }, {
16 | label: 'Redo',
17 | accelerator: 'Shift+CmdOrCtrl+Z',
18 | role: 'redo'
19 | }, {
20 | type: 'separator'
21 | }, {
22 | label: 'Cut',
23 | accelerator: 'CmdOrCtrl+X',
24 | role: 'cut'
25 | }, {
26 | label: 'Copy',
27 | accelerator: 'CmdOrCtrl+C',
28 | role: 'copy'
29 | }, {
30 | label: 'Paste',
31 | accelerator: 'CmdOrCtrl+V',
32 | role: 'paste'
33 | }, {
34 | label: 'Select All',
35 | accelerator: 'CmdOrCtrl+A',
36 | role: 'selectall'
37 | },
38 | ]}, {
39 | label: 'View',
40 | submenu: [{
41 | label: 'Reload',
42 | accelerator: 'CmdOrCtrl+R',
43 | click: function(item, focusedWindow) {
44 | if (focusedWindow)
45 | focusedWindow.reload();
46 | }
47 | }, {
48 | label: 'Toggle Full Screen',
49 | accelerator: (function() {
50 | if (process.platform == 'darwin')
51 | return 'Ctrl+Command+F';
52 | else
53 | return 'F11';
54 | })(),
55 | click: function(item, focusedWindow) {
56 | if (focusedWindow)
57 | focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
58 | }
59 | }, {
60 | label: 'Toggle Developer Tools',
61 | accelerator: (function() {
62 | if (process.platform == 'darwin')
63 | return 'Alt+Command+I';
64 | else
65 | return 'Ctrl+Shift+I';
66 | })(),
67 | click: function(item, focusedWindow) {
68 | if (focusedWindow)
69 | focusedWindow.toggleDevTools();
70 | }
71 | },
72 | ]}, {
73 | label: 'Window',
74 | role: 'window',
75 | submenu: [{
76 | label: 'Minimize',
77 | accelerator: 'CmdOrCtrl+M',
78 | role: 'minimize'
79 | }, {
80 | label: 'Close',
81 | accelerator: 'CmdOrCtrl+W',
82 | role: 'close'
83 | },
84 | ]}, {
85 | label: 'Help',
86 | role: 'help',
87 | submenu: [{
88 | label: 'Learn More',
89 | click: function() {
90 | require('shell').openExternal('https://github.com/importre/epp')
91 | }
92 | },
93 | ]}];
94 |
95 | var darwinMenu = [{
96 | label: appName,
97 | submenu: [{
98 | label: 'About ' + app.getName(),
99 | click: function(item, focusedWindow) {
100 | var file = path.resolve(__dirname, 'assets/epp.png');
101 | var appIcon = NativeImage.createFromPath(file);
102 | dialog.showMessageBox(focusedWindow, {
103 | 'type': 'info',
104 | 'title': app.getName(),
105 | 'message': app.getName() + ' ' + app.getVersion(),
106 | 'icon': appIcon,
107 | 'buttons': ['ok']
108 | });
109 | }
110 | }, {
111 | type: 'separator'
112 | }, {
113 | label: 'Hide',
114 | accelerator: 'Esc',
115 | selector: 'hide:'
116 | }, {
117 | type: 'separator'
118 | }, {
119 | label: 'Quit',
120 | accelerator: 'Cmd+Q',
121 | click() {
122 | app.quit();
123 | }
124 | }]
125 | }]
126 |
127 | var menu = template;
128 | if (process.platform == 'darwin') {
129 | menu = darwinMenu.concat(template)
130 | }
131 |
132 | module.exports = menu;
133 |
--------------------------------------------------------------------------------
/scripts/watcher.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const cp = require('child_process');
5 | const net = require('net');
6 | const config = require('../config');
7 |
8 | var client = null;
9 |
10 | function connect() {
11 | return net.connect({port: config.port}, function () {
12 | if (client !== null) {
13 | client.write('hello');
14 | }
15 | });
16 | }
17 |
18 | function start(app) {
19 | if (client === null) {
20 | client = connect();
21 | client.on('data', function (data) {
22 | app.quit();
23 | client.end();
24 | client = null;
25 | });
26 | }
27 | }
28 |
29 | function watch(app, files) {
30 | const opts = { persistent: true, recursive: true };
31 | files.forEach(file => {
32 | fs.watch(file, opts, function (event, filename) {
33 | start(app);
34 | });
35 | });
36 | }
37 |
38 | module.exports = {
39 | 'watch': watch
40 | };
41 |
--------------------------------------------------------------------------------
/starter.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | 'use strict';
4 |
5 | const net = require('net');
6 | const path = require('path');
7 | const spawn = require('child_process').spawn;
8 | const sleep = require('sleep').sleep;
9 | const config = require('./config');
10 | const win32 = process.platform === 'win32';
11 |
12 | var child = null;
13 |
14 | function getElectronArgs() {
15 | var args = ['.'];
16 | if (process.argv.indexOf('--2nd') != -1) {
17 | args.push('--2nd');
18 | }
19 | return args
20 | }
21 |
22 | const server = net.createServer(function (c) {
23 | if (child) {
24 | if (win32) {
25 | spawn("taskkill", ["/pid", child.pid, '/f', '/t']);
26 | } else {
27 | child.kill();
28 | }
29 |
30 | delete process.env.DEV;
31 | }
32 |
33 | process.env.DEV = 1
34 | var cmd = win32 ? 'electron.cmd' : 'electron';
35 | child = spawn(cmd, getElectronArgs());
36 | child.stdout.on('data', function (data) {
37 | console.log(data + '');
38 | });
39 |
40 | child.stderr.on('data', function (data) {
41 | console.log(data + '');
42 | });
43 |
44 | child.on('close', function (code) {
45 | console.log('child process exited with code ' + code);
46 | });
47 |
48 | c.write('world');
49 | });
50 |
51 | server.listen(config.port, function (e) {
52 | const client = net.connect({port: config.port}, function () {
53 | const args = ['--config', 'webpack.config.js', '--hot',
54 | '--port', 8000, '--inline'];
55 | spawn('webpack-dev-server', args, {
56 | stdio: 'inherit'
57 | });
58 | sleep(1);
59 | client.write('hello');
60 | });
61 |
62 | client.on('data', function (data) {
63 | client.end();
64 | });
65 | });
66 |
67 | server.on('error', function (e) {
68 | });
69 |
--------------------------------------------------------------------------------
/styles/theme.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-photonkit/epp/913c71a6c32625cec0bedcc47db85afbe9f93d01/styles/theme.scss
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | module.exports = {
4 | entry: path.resolve(__dirname, 'app/app.jsx'),
5 | output: {
6 | path: path.resolve(__dirname, 'out'),
7 | publicPath: 'out/',
8 | filename: 'app.js'
9 | },
10 | module: {
11 | loaders: [
12 | { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader'] },
13 | { test: /\.css$/, loader: 'style-loader!css-loader' },
14 | { test: /\.scss$/, loaders: ['style', 'css', 'sass']},
15 |
16 | { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
17 | { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff' },
18 | { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' },
19 | { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' },
20 | { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' },
21 |
22 | { test: /\.json$/, loader: 'json-loader' }
23 | ]
24 | }
25 | };
26 |
--------------------------------------------------------------------------------