Skip to content

Commit

Permalink
chore: adding basic example of usage in raw scenario + moving integra…
Browse files Browse the repository at this point in the history
…tion tests (#299)

* chore: adding basic example of usage in raw scenario

* chore: work in progress

* chore: trying to add tests

* chore: fixing e2e tests and making them runnable

* fix package.json

* chore: code review comments addressed
  • Loading branch information
matmalkowski authored Feb 22, 2021
1 parent b48f338 commit 2d05fa7
Show file tree
Hide file tree
Showing 23 changed files with 2,943 additions and 3,110 deletions.
6 changes: 1 addition & 5 deletions .babelrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,5 @@ module.exports = {
},
],
],
plugins: [
'@babel/proposal-object-rest-spread',
'@babel/plugin-proposal-optional-chaining',
NODE_ENV === 'test' && '@babel/transform-modules-commonjs',
].filter(Boolean),
plugins: [NODE_ENV === 'test' && '@babel/transform-modules-commonjs'].filter(Boolean),
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
"**/es": true,
"**/lib": true,
"**/types": true
}
},
"typescript.tsdk": "node_modules\\typescript\\lib"
}
26 changes: 26 additions & 0 deletions examples/basic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@electron-redux-examples/basic",
"version": "0.0.0",
"license": "MIT",
"private": true,
"scripts": {
"postinstall": "yarn build",
"start": "electron ./dist/main.js",
"build": "rimraf dist && yarn type-check && yarn build:main && yarn build:renderer",
"build:main": "webpack -c ./webpack.main.js",
"build:renderer": "webpack -c ./webpack.renderer.js",
"type-check": "tsc --noEmit"
},
"devDependencies": {
"@babel/core": "^7.12.17",
"electron": "^9.2.0",
"electron-redux": "link:../..",
"html-webpack-plugin": "^5.2.0",
"redux": "^4.0.5",
"rimraf": "3.0.2",
"ts-loader": "^8.0.17",
"typescript": "^4.1.5",
"webpack": "5.23.0",
"webpack-cli": "^4.5.0"
}
}
67 changes: 67 additions & 0 deletions examples/basic/src/main/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import url from 'url'
import { app, BrowserWindow } from 'electron'
import { stateSyncEnhancer } from 'electron-redux'
import { createStore } from 'redux'
import { rootReducer } from '../store'

// ==================================================================
// electron related boiler-plate to create window with singe renderer
let mainWindow: BrowserWindow | null
async function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
})
await mainWindow.loadURL(
url.format({
pathname: `${__dirname}/index.html`,
protocol: 'file',
slashes: true,
})
)

render()

mainWindow.on('closed', () => {
mainWindow = null
})
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

// Boilerplate code ends here
// ==================================================================
// And here is electron-redux example usage

// This will create the new Redux Store for main process - as third argument (or 2nd, if you would not pass initial state)
// we have passed the store enhancer responsible for the synchronization

const initialState = {
globalCounter: 1,
localCounter: 1,
}

const store = createStore(rootReducer, initialState, stateSyncEnhancer())

const render = () => {
if (mainWindow) {
const { globalCounter, localCounter } = store.getState()
mainWindow.setTitle(`Global counter: [${globalCounter}] | Local counter: [${localCounter}]`)
}
}

store.subscribe(render)
16 changes: 16 additions & 0 deletions examples/basic/src/renderer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
Global Counter: <span id="globalCounter">#</span>
<button id="incrementGlobalCounter">+</button>
<button id="decrementGlobalCounter">-</button>
<br />
Local Counter (with stopForwarding): <span id="localCounter">#</span>
<button id="incrementLocalCounter">+</button>
<button id="decrementLocalCounter">-</button>
<br />
</body>
</html>
36 changes: 36 additions & 0 deletions examples/basic/src/renderer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import { createStore } from 'redux'
import { rootReducer } from '../store'
import { stateSyncEnhancer } from 'electron-redux'
import {
decrementGlobalCounter,
decrementLocalCounter,
incrementGlobalCounter,
incrementLocalCounter,
} from '../store/actions'

const store = createStore(rootReducer, stateSyncEnhancer())

const registerClickHandler = (id: string, handler: () => void) =>
document.getElementById(id)!.addEventListener('click', handler)

const registerEvents = () => {
registerClickHandler('incrementGlobalCounter', () => store.dispatch(incrementGlobalCounter()))
registerClickHandler('decrementGlobalCounter', () => store.dispatch(decrementGlobalCounter()))
registerClickHandler('incrementLocalCounter', () => store.dispatch(incrementLocalCounter()))
registerClickHandler('decrementLocalCounter', () => store.dispatch(decrementLocalCounter()))
}

const globalCounterEl = document.getElementById('globalCounter')!
const localCounterEl = document.getElementById('localCounter')!

const render = () => {
const { globalCounter, localCounter } = store.getState()
globalCounterEl.innerHTML = globalCounter.toString()
localCounterEl.innerHTML = localCounter.toString()
}

store.subscribe(render)
render() // initial render
registerEvents() // register click events to dispatch actions
42 changes: 42 additions & 0 deletions examples/basic/src/store/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { stopForwarding } from 'electron-redux'

export interface ActionTypes {
type:
| typeof INCREMENT_GLOBAL
| typeof DECREMENT_GLOBAL
| typeof INCREMENT_LOCAL
| typeof DECREMENT_LOCAL
}

interface ActionWithMeta extends ActionTypes {
meta: {
scope: 'local'
}
}

export const INCREMENT_GLOBAL = 'INCREMENT_GLOBAL'
export const incrementGlobalCounter = (): ActionTypes => ({ type: INCREMENT_GLOBAL })

export const DECREMENT_GLOBAL = 'DECREMENT_GLOBAL'
export const decrementGlobalCounter = (): ActionTypes => ({ type: DECREMENT_GLOBAL })

/*
INCREMENT_LOCAL action is an Scoped Action - that means, that it will not get propagated to any other store in other processes:
it will only get handled by the middleware & reducers registered for the process it got dispatch in.
To create such an action, we have used the stopForwarding function wrapper on top of the action itself
*/
export const INCREMENT_LOCAL = 'INCREMENT_LOCAL'
export const incrementLocalCounter = (): ActionTypes => stopForwarding({ type: INCREMENT_LOCAL })

/*
DECREMENT_LOCAL action is an Scoped Action - that means, that it will not get propagated to any other store in other processes:
it will only get handled by the middleware & reducers registered for the process it got dispatch in.
Here, instead of using the helper function from electron-redux, we set the scoping property manually, by adding additional meta field with scope value set to local:
*/
export const DECREMENT_LOCAL = 'DECREMENT_LOCAL'
export const decrementLocalCounter = (): ActionWithMeta => ({
type: DECREMENT_LOCAL,
meta: { scope: 'local' },
})
9 changes: 9 additions & 0 deletions examples/basic/src/store/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { combineReducers } from 'redux'
import { globalCounterReducer, localCounterReducer } from './reducers'

export const rootReducer = combineReducers({
globalCounter: globalCounterReducer,
localCounter: localCounterReducer,
})

export type RootState = ReturnType<typeof rootReducer>
33 changes: 33 additions & 0 deletions examples/basic/src/store/reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
DECREMENT_GLOBAL,
INCREMENT_GLOBAL,
ActionTypes,
INCREMENT_LOCAL,
DECREMENT_LOCAL,
} from './actions'

export const globalCounterReducer = (state = 0, action: ActionTypes): number => {
switch (action.type) {
case INCREMENT_GLOBAL: {
return state + 1
}
case DECREMENT_GLOBAL: {
return state - 1
}
default:
return state
}
}

export const localCounterReducer = (state = 0, action: ActionTypes): number => {
switch (action.type) {
case INCREMENT_LOCAL: {
return state + 1
}
case DECREMENT_LOCAL: {
return state - 1
}
default:
return state
}
}
17 changes: 17 additions & 0 deletions examples/basic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compileOnSave": false,
"compilerOptions": {
"target": "es2015",
"moduleResolution": "node",
"pretty": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"sourceMap": true,
"skipLibCheck": true,
"allowJs": true,
"jsx": "preserve"
},
"exclude": ["node_modules"]
}
27 changes: 27 additions & 0 deletions examples/basic/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-undef */

module.exports = {
output: {
filename: '[name].js',
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.tsx?/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
exclude: /node_modules/,
},
],
},
}
16 changes: 16 additions & 0 deletions examples/basic/webpack.main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-undef */

const base = require('./webpack.config')

module.exports = {
...base,
mode: 'production',
entry: {
main: './src/main/index.ts',
},
target: 'electron-main',
node: {
__dirname: false,
},
}
20 changes: 20 additions & 0 deletions examples/basic/webpack.renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-undef */

const base = require('./webpack.config')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
...base,
mode: 'production',
entry: {
renderer: './src/renderer/index.ts',
},
target: 'electron-renderer',
plugins: [
new HtmlWebpackPlugin({
template: './src/renderer/index.html',
publicPath: './',
}),
],
}
Loading

0 comments on commit 2d05fa7

Please sign in to comment.