├── README.md ├── package.json ├── public ├── electron.js ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json ├── preload.js ├── renderer.js └── robots.txt ├── server.js ├── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js └── yarn.lock /README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `yarn electron` 8 | 9 | Runs the electron app in the development mode.
10 | Also view in Browser. 11 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 12 | 13 | The page will reload if you make edits.
14 | You will also see any lint errors in the console. 15 | 16 | ## Build insturctions for different platforms. 17 | 18 | You can install electron builder globally if you want. 19 | 20 | `npm install -g electron-builder` 21 | 22 | ## Build 23 | ``` 24 | Commands: 25 | electron-builder build Build [default] 26 | electron-builder install-app-deps Install app deps 27 | electron-builder node-gyp-rebuild Rebuild own native code 28 | electron-builder create-self-signed-cert Create self-signed code signing cert 29 | for Windows apps 30 | electron-builder start Run application in a development 31 | mode using electron-webpack 32 | 33 | Building: 34 | --mac, -m, -o, --macos Build for macOS, accepts target list (see 35 | https://goo.gl/5uHuzj). [array] 36 | --linux, -l Build for Linux, accepts target list (see 37 | https://goo.gl/4vwQad) [array] 38 | --win, -w, --windows Build for Windows, accepts target list (see 39 | https://goo.gl/jYsTEJ) [array] 40 | --x64 Build for x64 [boolean] 41 | --ia32 Build for ia32 [boolean] 42 | --armv7l Build for armv7l [boolean] 43 | --arm64 Build for arm64 [boolean] 44 | --dir Build unpacked dir. Useful to test. [boolean] 45 | --prepackaged, --pd The path to prepackaged app (to pack in a 46 | distributable format) 47 | --projectDir, --project The path to project directory. Defaults to current 48 | working directory. 49 | --config, -c The path to an electron-builder config. Defaults to 50 | `electron-builder.yml` (or `json`, or `json5`), see 51 | https://goo.gl/YFRJOM 52 | 53 | Publishing: 54 | --publish, -p Publish artifacts, see https://goo.gl/tSFycD 55 | [choices: "onTag", "onTagOrDraft", "always", "never", undefined] 56 | 57 | Other: 58 | --help Show help [boolean] 59 | --version Show version number [boolean] 60 | 61 | Examples: 62 | electron-builder -mwl build for macOS, Windows and Linux 63 | electron-builder --linux deb tar.xz build deb and tar.xz for Linux 64 | electron-builder --win --ia32 build for Windows ia32 65 | electron-builder set package.json property `foo` to 66 | -c.extraMetadata.foo=bar `bar` 67 | electron-builder configure unicode options for NSIS 68 | --config.nsis.unicode=false 69 | ``` 70 | See https://electron.build for more documentation. 71 | 72 | ### `yarn start` 73 | 74 | Runs the app in the development mode.
75 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 76 | 77 | The page will reload if you make edits.
78 | You will also see any lint errors in the console. 79 | 80 | ### `yarn test` 81 | 82 | Launches the test runner in the interactive watch mode.
83 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 84 | 85 | ### `yarn build` 86 | 87 | Builds the app for production to the `build` folder.
88 | It correctly bundles React in production mode and optimizes the build for the best performance. 89 | 90 | The build is minified and the filenames include the hashes.
91 | Your app is ready to be deployed! 92 | 93 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 94 | 95 | ### `yarn eject` 96 | 97 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 98 | 99 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 100 | 101 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 102 | 103 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 104 | 105 | ## Learn More 106 | 107 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 108 | 109 | To learn React, check out the [React documentation](https://reactjs.org/). 110 | 111 | ### Code Splitting 112 | 113 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 114 | 115 | ### Analyzing the Bundle Size 116 | 117 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 118 | 119 | ### Making a Progressive Web App 120 | 121 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 122 | 123 | ### Advanced Configuration 124 | 125 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 126 | 127 | ### Deployment 128 | 129 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 130 | 131 | ### `yarn build` fails to minify 132 | 133 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 134 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-react-app", 3 | "author": "Bilal Haider (https://fast.bearshares.com/@bilalhaider)", 4 | "description": "An electron React Application", 5 | "homepage": "./", 6 | "version": "0.1.0", 7 | "private": true, 8 | "main": "public/electron.js", 9 | "dependencies": { 10 | "concurrently": "^5.0.0", 11 | "electron-is-dev": "^1.1.0", 12 | "express": "^4.17.1", 13 | "express-favicon": "^2.0.1", 14 | "isomorphic-fetch": "^2.2.1", 15 | "path": "^0.12.7", 16 | "react": "^16.12.0", 17 | "react-dom": "^16.12.0", 18 | "react-scripts": "3.2.0", 19 | "reactstrap": "^8.1.1", 20 | "serialize-javascript": "^2.1.1", 21 | "url": "^0.11.0", 22 | "wait-on": "^3.3.0" 23 | }, 24 | "devDependencies": { 25 | "electron": "^7.1.1", 26 | "electron-builder": "^21.2.0", 27 | "electron-packager": "^14.1.0" 28 | }, 29 | "scripts": { 30 | "start": "react-scripts start", 31 | "build": "react-scripts build", 32 | "test": "react-scripts test", 33 | "eject": "react-scripts eject", 34 | "electron": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"", 35 | "build-all": "electron-builder -mwl", 36 | "build-linux": "electron-builder --linux", 37 | "build-linux64": "electron-builder --linux --x64", 38 | "build-linux-deb": "electron-builder --linux deb", 39 | "build-linux-tar": "electron-builder --linux tar.xz", 40 | "build-windows32": "electron-builder --win --ia32", 41 | "build-windows64": "electron-builder --win --x64", 42 | "build-mac": "electron-builder --mac" 43 | }, 44 | "build": { 45 | "appId": "com.bearshares.electronapp", 46 | "files": [ 47 | "build/**/*", 48 | "node_modules/**/*" 49 | ], 50 | "directories": { 51 | "buildResources": "assets" 52 | } 53 | }, 54 | "eslintConfig": { 55 | "extends": "react-app" 56 | }, 57 | "browserslist": { 58 | "production": [ 59 | ">0.2%", 60 | "not dead", 61 | "not op_mini all" 62 | ], 63 | "development": [ 64 | "last 1 chrome version", 65 | "last 1 firefox version", 66 | "last 1 safari version" 67 | ] 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /public/electron.js: -------------------------------------------------------------------------------- 1 | // Modules to control application life and create native browser window 2 | const {app, BrowserWindow} = require('electron') 3 | const path = require('path') 4 | const isDev = require('electron-is-dev'); 5 | const url = require('url'); 6 | // Keep a global reference of the window object, if you don't, the window will 7 | // be closed automatically when the JavaScript object is garbage collected. 8 | let mainWindow 9 | 10 | function createWindow () { 11 | // Create the browser window. 12 | mainWindow = new BrowserWindow({ 13 | width: 800, 14 | height: 600, 15 | webPreferences: { 16 | preload: path.join(__dirname, 'preload.js') 17 | } 18 | }) 19 | 20 | // and load the index.html of the app. 21 | mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`); 22 | 23 | // Open the DevTools. 24 | // mainWindow.webContents.openDevTools() 25 | 26 | // Emitted when the window is closed. 27 | mainWindow.on('closed', function () { 28 | // Dereference the window object, usually you would store windows 29 | // in an array if your app supports multi windows, this is the time 30 | // when you should delete the corresponding element. 31 | mainWindow = null 32 | }) 33 | } 34 | 35 | // This method will be called when Electron has finished 36 | // initialization and is ready to create browser windows. 37 | // Some APIs can only be used after this event occurs. 38 | app.on('ready', createWindow) 39 | 40 | // Quit when all windows are closed. 41 | app.on('window-all-closed', function () { 42 | // On macOS it is common for applications and their menu bar 43 | // to stay active until the user quits explicitly with Cmd + Q 44 | if (process.platform !== 'darwin') app.quit() 45 | }) 46 | 47 | app.on('activate', function () { 48 | // On macOS it's common to re-create a window in the app when the 49 | // dock icon is clicked and there are no other windows open. 50 | if (mainWindow === null) createWindow() 51 | }) 52 | 53 | // In this file you can include the rest of your app's specific main process 54 | // code. You can also put them in separate files and require them here. -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalpakistani/electron-react-app/2358bb99ad00f4b978584eef032c2d2313d7bdf1/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalpakistani/electron-react-app/2358bb99ad00f4b978584eef032c2d2313d7bdf1/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilalpakistani/electron-react-app/2358bb99ad00f4b978584eef032c2d2313d7bdf1/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/preload.js: -------------------------------------------------------------------------------- 1 | // All of the Node.js APIs are available in the preload process. 2 | // It has the same sandbox as a Chrome extension. 3 | window.addEventListener('DOMContentLoaded', () => { 4 | const replaceText = (selector, text) => { 5 | const element = document.getElementById(selector) 6 | if (element) element.innerText = text 7 | } 8 | 9 | for (const type of ['chrome', 'node', 'electron']) { 10 | replaceText(`${type}-version`, process.versions[type]) 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /public/renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // No Node.js APIs are available in this process because 4 | // `nodeIntegration` is turned off. Use `preload.js` to 5 | // selectively enable features needed in the rendering 6 | // process. 7 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const favicon = require('express-favicon'); 3 | const path = require('path'); 4 | const port = 8083; 5 | const app = express(); 6 | app.use(favicon(__dirname + '/build/favicon.ico')); 7 | // the __dirname is the current directory from where the script is running 8 | app.use(express.static(__dirname)); 9 | app.use(express.static(path.join(__dirname, 'build'))); 10 | app.get('/ping', function (req, res) { 11 | return res.send('pong'); 12 | }); 13 | app.get('/*', function (req, res) { 14 | res.sendFile(path.join(__dirname, 'build', 'index.html')); 15 | }); 16 | app.listen(port); -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | } 8 | 9 | .App-header { 10 | background-color: #282c34; 11 | min-height: 100vh; 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | justify-content: center; 16 | font-size: calc(10px + 2vmin); 17 | color: white; 18 | } 19 | 20 | .App-link { 21 | color: #09d3ac; 22 | } 23 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.js and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | --------------------------------------------------------------------------------