Merge pull request #10 from kremalicious/feature/touchbar-electron
Electron Touch Bar
18
README.md
@ -26,6 +26,7 @@
|
||||
- [Features](#features)
|
||||
- [Download](#download)
|
||||
- [Development](#development)
|
||||
- [Configuration](#configuration)
|
||||
- [Build packages](#build-packages)
|
||||
- [License](#license)
|
||||
|
||||
@ -39,9 +40,10 @@
|
||||
- re-fetches everything automatically every minute
|
||||
- balances are fetched via etherscan.io API
|
||||
- spot prices are fetched from coingecko.com API
|
||||
- detects system locale for number formatting
|
||||
- detects dark appearance setting and switches to dark theme automatically (macOS only)
|
||||
- detects system accent color and uses it as primary color (macOS & Windows only)
|
||||
- Touch Bar support (macOS only)
|
||||
- detects system locale for number formatting
|
||||
- currently highly optimized for macOS, your mileage on Windows or Linux may vary
|
||||
|
||||
## Download
|
||||
@ -57,6 +59,8 @@ Alternatively, you can [build the app on your system](#build-packages).
|
||||
|
||||
## Development
|
||||
|
||||
The main app is a React app in `src/renderer/` wrapped within an Electron app defined in `src/main/`.
|
||||
|
||||
Clone, and run:
|
||||
|
||||
```bash
|
||||
@ -70,6 +74,18 @@ npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The app has a settings screen where you can add your account addresses.
|
||||
|
||||
When building the app yourself, you can configure more in the `src/config.js` file:
|
||||
|
||||
| Key | Description |
|
||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `conversions` | Array defining the currencies the Ocean balance is converted to. Every currency listed here will appear in the ticker buttons. |
|
||||
| `refreshInterval` | Defines the interval prices and balances are refetched. |
|
||||
| `oceanTokenContract` | Contract address of the Ocean Token. You should not change this. |
|
||||
|
||||
## Build packages
|
||||
|
||||
```bash
|
||||
|
26
package.json
@ -3,7 +3,7 @@
|
||||
"productName": "Blowfish",
|
||||
"version": "1.0.2",
|
||||
"description": "🐡 Simple Electron-based desktop app to retrieve and display your total Ocean Token balances.",
|
||||
"main": "./src/main.js",
|
||||
"main": "./src/main/index.js",
|
||||
"scripts": {
|
||||
"test": "eslint ./src/**/*.{js,jsx} && stylelint ./src/**/*.css",
|
||||
"start": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js",
|
||||
@ -21,28 +21,23 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@coingecko/cryptoformat": "^0.3.1",
|
||||
"@reach/router": "^1.2.1",
|
||||
"ethereum-address": "0.0.4",
|
||||
"ms": "^2.1.1",
|
||||
"react": "^16.8.6",
|
||||
"react-blockies": "^1.4.1",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-pose": "^4.0.8",
|
||||
"react-touchbar-electron": "0.0.1"
|
||||
"ms": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.4",
|
||||
"@babel/core": "^7.4.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.4",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.4.4",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@babel/runtime": "^7.4.5",
|
||||
"@reach/router": "^1.2.1",
|
||||
"@svgr/webpack": "^4.2.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^8.0.6",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"css-loader": "^2.1.1",
|
||||
"electron": "^6.0.0-beta.3",
|
||||
"electron": "^5.0.2",
|
||||
"electron-builder": "^20.40.2",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-store": "^3.2.0",
|
||||
@ -53,10 +48,14 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"prettier": "^1.17.0",
|
||||
"prettier-stylelint": "^0.4.2",
|
||||
"react": "^16.8.6",
|
||||
"react-blockies": "^1.4.1",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-pose": "^4.0.8",
|
||||
"style-loader": "^0.23.1",
|
||||
"stylelint": "^10.0.1",
|
||||
"stylelint-config-standard": "^18.3.0",
|
||||
"webpack": "^4.31.0",
|
||||
"webpack": "^4.32.2",
|
||||
"webpack-cli": "^3.3.2",
|
||||
"webpack-dev-server": "^3.3.1"
|
||||
},
|
||||
@ -65,6 +64,7 @@
|
||||
"appId": "com.kremalicious.blowfish",
|
||||
"files": [
|
||||
"./build/**/*",
|
||||
"./src/main/**/*",
|
||||
"./src/*.js",
|
||||
"package.json"
|
||||
],
|
||||
|
@ -1,49 +0,0 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { TouchBar, Button } from 'react-touchbar-electron'
|
||||
import { cryptoFormatter } from '../../utils'
|
||||
import { AppContext } from '../store/createContext'
|
||||
|
||||
const TouchbarItems = ({ prices, currency, toggleCurrencies, accentColor }) => (
|
||||
<>
|
||||
<Button
|
||||
label={cryptoFormatter(1, 'ocean')}
|
||||
onClick={() => toggleCurrencies('ocean')}
|
||||
backgroundColor={currency === 'ocean' ? accentColor : '#141414'}
|
||||
/>
|
||||
{Object.keys(prices).map(key => (
|
||||
<Button
|
||||
key={key}
|
||||
label={cryptoFormatter(prices[key], key)}
|
||||
onClick={() => toggleCurrencies(key)}
|
||||
backgroundColor={
|
||||
currency !== 'ocean' && currency === key ? accentColor : '#141414'
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
|
||||
TouchbarItems.propTypes = {
|
||||
prices: PropTypes.object.isRequired,
|
||||
currency: PropTypes.string.isRequired,
|
||||
toggleCurrencies: PropTypes.func.isRequired,
|
||||
accentColor: PropTypes.string
|
||||
}
|
||||
|
||||
export default class Touchbar extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<TouchBar>
|
||||
<TouchbarItems
|
||||
prices={this.context.prices}
|
||||
currency={this.context.currency}
|
||||
toggleCurrencies={this.context.toggleCurrencies}
|
||||
accentColor={this.context.accentColor}
|
||||
/>
|
||||
</TouchBar>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Touchbar.contextType = AppContext
|
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
prices: ['eur', 'usd', 'btc', 'eth'],
|
||||
conversions: ['eur', 'usd', 'btc', 'eth'],
|
||||
refreshInterval: '1m',
|
||||
oceanTokenContract: '0x985dd3D42De1e256d09e1c10F112bCCB8015AD41'
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
const path = require('path')
|
||||
const { app, BrowserWindow, systemPreferences } = require('electron')
|
||||
const { touchBarWrapper } = require('react-touchbar-electron')
|
||||
const pkg = require('../package.json')
|
||||
const { app, BrowserWindow, systemPreferences, ipcMain } = require('electron')
|
||||
const pkg = require('../../package.json')
|
||||
const buildMenu = require('./menu')
|
||||
const { rgbaToHex } = require('./utils')
|
||||
const { buildTouchbar, updateTouchbar } = require('./touchbar')
|
||||
const { rgbaToHex } = require('../utils')
|
||||
|
||||
let mainWindow
|
||||
|
||||
@ -20,6 +20,84 @@ if (
|
||||
const width = 620
|
||||
const height = 440
|
||||
|
||||
const createWindow = async () => {
|
||||
const isDarkMode = systemPreferences.isDarkMode()
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width,
|
||||
height,
|
||||
minWidth: width,
|
||||
minHeight: height,
|
||||
acceptFirstMouse: true,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
fullscreenWindowTitle: true,
|
||||
backgroundColor: isDarkMode ? '#141414' : '#fff',
|
||||
frame: false,
|
||||
show: false,
|
||||
title: pkg.productName,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
scrollBounce: true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadURL(
|
||||
isDev
|
||||
? 'http://localhost:8080'
|
||||
: `file://${path.join(__dirname, '../../build/index.html')}`
|
||||
)
|
||||
|
||||
createWindowEvents(mainWindow)
|
||||
installDevTools(mainWindow)
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
})
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
|
||||
// Load menubar
|
||||
buildMenu(mainWindow)
|
||||
// Load touchbar
|
||||
if (process.platform === 'darwin') {
|
||||
const accentColor = getAccentColor()
|
||||
buildTouchbar(mainWindow, accentColor)
|
||||
|
||||
ipcMain.on('prices-updated', (event, pricesNew) => {
|
||||
updateTouchbar(pricesNew, mainWindow, accentColor)
|
||||
})
|
||||
|
||||
ipcMain.on('currency-updated', (event, pricesNew, currentCurrency) => {
|
||||
updateTouchbar(pricesNew, mainWindow, accentColor, currentCurrency)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
createWindow()
|
||||
|
||||
mainWindow.webContents.on('dom-ready', () => {
|
||||
switchTheme()
|
||||
switchAccentColor()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
const installDevTools = async mainWindow => {
|
||||
if (isDev) {
|
||||
const {
|
||||
@ -66,80 +144,17 @@ const createWindowEvents = mainWindow => {
|
||||
)
|
||||
}
|
||||
|
||||
const createWindow = async () => {
|
||||
const isDarkMode = systemPreferences.isDarkMode()
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
width,
|
||||
height,
|
||||
minWidth: width,
|
||||
minHeight: height,
|
||||
acceptFirstMouse: true,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
fullscreenWindowTitle: true,
|
||||
backgroundColor: isDarkMode ? '#141414' : '#fff',
|
||||
frame: false,
|
||||
show: false,
|
||||
title: pkg.productName,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
scrollBounce: true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadURL(
|
||||
isDev
|
||||
? 'http://localhost:8080'
|
||||
: `file://${path.join(__dirname, '../build/index.html')}`
|
||||
)
|
||||
|
||||
createWindowEvents(mainWindow)
|
||||
installDevTools(mainWindow)
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
mainWindow.focus()
|
||||
})
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
|
||||
// Load menubar
|
||||
buildMenu(mainWindow)
|
||||
// Load touchbar
|
||||
process.platform === 'darwin' && touchBarWrapper(mainWindow)
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
createWindow()
|
||||
|
||||
mainWindow.webContents.on('dom-ready', () => {
|
||||
switchTheme()
|
||||
switchAccentColor()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
//
|
||||
// Accent color setting
|
||||
// macOS & Windows
|
||||
//
|
||||
const switchAccentColor = () => {
|
||||
const getAccentColor = () => {
|
||||
const systemAccentColor = systemPreferences.getAccentColor()
|
||||
const accentColor = rgbaToHex(systemAccentColor)
|
||||
return rgbaToHex(systemAccentColor)
|
||||
}
|
||||
|
||||
const switchAccentColor = () => {
|
||||
const accentColor = getAccentColor()
|
||||
mainWindow.webContents.send('accent-color', accentColor)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
const { app, Menu } = require('electron')
|
||||
const { openUrl } = require('./utils')
|
||||
const { homepage } = require('../package.json')
|
||||
const { openUrl } = require('../utils')
|
||||
const { homepage } = require('../../package.json')
|
||||
|
||||
const buildMenu = mainWindow => {
|
||||
const template = [
|
54
src/main/touchbar.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { TouchBar } = require('electron')
|
||||
const { cryptoFormatter } = require('../utils')
|
||||
const { conversions } = require('../config')
|
||||
|
||||
const { TouchBarButton } = TouchBar
|
||||
|
||||
const createButton = (
|
||||
value,
|
||||
key,
|
||||
mainWindow,
|
||||
accentColor,
|
||||
currentCurrency = 'ocean'
|
||||
) =>
|
||||
new TouchBarButton({
|
||||
label: cryptoFormatter(value, key),
|
||||
click: () => mainWindow.webContents.send('setCurrency', key),
|
||||
backgroundColor: key === currentCurrency ? accentColor : '#141414'
|
||||
})
|
||||
|
||||
const buildTouchbar = (mainWindow, accentColor) => {
|
||||
const touchBar = new TouchBar({
|
||||
items: [
|
||||
createButton(1, 'ocean', mainWindow, accentColor),
|
||||
...conversions.map(key => createButton(0, key, mainWindow, accentColor))
|
||||
]
|
||||
})
|
||||
|
||||
mainWindow.setTouchBar(touchBar)
|
||||
}
|
||||
|
||||
const updateTouchbar = (
|
||||
pricesNew,
|
||||
mainWindow,
|
||||
accentColor,
|
||||
currentCurrency = 'ocean'
|
||||
) => {
|
||||
const items = pricesNew.map(item => {
|
||||
return createButton(
|
||||
item[1],
|
||||
item[0],
|
||||
mainWindow,
|
||||
accentColor,
|
||||
currentCurrency
|
||||
)
|
||||
})
|
||||
|
||||
const touchBar = new TouchBar({
|
||||
items: [...items]
|
||||
})
|
||||
|
||||
mainWindow.setTouchBar(touchBar)
|
||||
}
|
||||
|
||||
module.exports = { buildTouchbar, updateTouchbar }
|
@ -8,7 +8,6 @@ import Home from './screens/Home'
|
||||
import Preferences from './screens/Preferences'
|
||||
import './App.css'
|
||||
import { defaultAnimation } from './components/Animations'
|
||||
import Touchbar from './components/Touchbar'
|
||||
|
||||
//
|
||||
// Disable zooming
|
||||
@ -51,8 +50,6 @@ export default class App extends PureComponent {
|
||||
<Preferences path="/preferences" />
|
||||
</PosedRouter>
|
||||
</div>
|
||||
|
||||
<Touchbar />
|
||||
</>
|
||||
)
|
||||
}
|
@ -11,8 +11,10 @@ export default class Ticker extends PureComponent {
|
||||
static contextType = AppContext
|
||||
|
||||
items = activeStyle =>
|
||||
Object.keys(this.context.prices).map((key, i) => (
|
||||
<Item key={i} className="number-unit">
|
||||
// convert Map to array first, cause for...of or forEach returns undefined,
|
||||
// so it cannot be mapped to a collection of elements
|
||||
[...this.context.prices.entries()].map(([key, value]) => (
|
||||
<Item key={key} className="number-unit">
|
||||
<button
|
||||
className="label label--price"
|
||||
onClick={() => this.context.toggleCurrencies(key)}
|
||||
@ -23,7 +25,7 @@ export default class Ticker extends PureComponent {
|
||||
: {}
|
||||
}
|
||||
>
|
||||
{cryptoFormatter(this.context.prices[key], key)}
|
||||
{cryptoFormatter(value, key)}
|
||||
</button>
|
||||
</Item>
|
||||
))
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import { AppContext } from '../store/createContext'
|
||||
import Balance from './Balance'
|
||||
import { prices } from '../config'
|
||||
import { conversions } from '../../config'
|
||||
|
||||
const calculateTotalBalance = (accounts, currency) => {
|
||||
const balanceTotalArray = []
|
||||
@ -23,15 +23,15 @@ export default class Total extends PureComponent {
|
||||
static contextType = AppContext
|
||||
|
||||
render() {
|
||||
const conversions = Object.assign(
|
||||
...prices.map(key => ({
|
||||
const conversionsBalance = Object.assign(
|
||||
...conversions.map(key => ({
|
||||
[key]: calculateTotalBalance(this.context.accounts, key)
|
||||
}))
|
||||
)
|
||||
|
||||
const balanceNew = {
|
||||
ocean: calculateTotalBalance(this.context.accounts, 'ocean'),
|
||||
...conversions
|
||||
...conversionsBalance
|
||||
}
|
||||
|
||||
return (
|
Before Width: | Height: | Size: 871 B After Width: | Height: | Size: 871 B |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@ -1,6 +1,5 @@
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { TouchBarProvider } from 'react-touchbar-electron'
|
||||
import AppProvider from './store/AppProvider'
|
||||
import App from './App'
|
||||
|
||||
@ -13,9 +12,7 @@ document.body.appendChild(root)
|
||||
|
||||
render(
|
||||
<AppProvider>
|
||||
<TouchBarProvider>
|
||||
<App />
|
||||
</TouchBarProvider>
|
||||
<App />
|
||||
</AppProvider>,
|
||||
document.getElementById('root')
|
||||
)
|
@ -4,8 +4,14 @@ import ms from 'ms'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import Store from 'electron-store'
|
||||
import { AppContext } from './createContext'
|
||||
import fetchData from '../util/fetch'
|
||||
import { refreshInterval, prices, oceanTokenContract } from '../config'
|
||||
import fetchData from '../utils/fetch'
|
||||
import { refreshInterval, conversions, oceanTokenContract } from '../../config'
|
||||
|
||||
// construct initial prices Map to get consistent
|
||||
// order for Ticker and Touchbar
|
||||
let pricesMap = new Map()
|
||||
pricesMap.set('ocean', 1)
|
||||
conversions.map(key => pricesMap.set(key, 0))
|
||||
|
||||
export default class AppProvider extends PureComponent {
|
||||
static propTypes = {
|
||||
@ -19,18 +25,26 @@ export default class AppProvider extends PureComponent {
|
||||
accounts: [],
|
||||
currency: 'ocean',
|
||||
needsConfig: false,
|
||||
prices: Object.assign(...prices.map(key => ({ [key]: 0 }))),
|
||||
toggleCurrencies: currency => this.setState({ currency }),
|
||||
prices: pricesMap,
|
||||
toggleCurrencies: currency => this.toggleCurrencies(currency),
|
||||
setBalances: () => this.setBalances(),
|
||||
accentColor: ''
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// listener for accent color
|
||||
ipcRenderer.on('accent-color', (event, accentColor) => {
|
||||
this.setState({ accentColor })
|
||||
})
|
||||
|
||||
await this.fetchAndSetPrices()
|
||||
// listener for touchbar
|
||||
ipcRenderer.on('setCurrency', (evt, currency) =>
|
||||
this.state.toggleCurrencies(currency)
|
||||
)
|
||||
|
||||
const newPrizes = await this.fetchAndSetPrices()
|
||||
this.setState({ prices: newPrizes })
|
||||
|
||||
await this.setBalances()
|
||||
|
||||
setInterval(this.fetchAndSetPrices, ms(refreshInterval))
|
||||
@ -66,19 +80,17 @@ export default class AppProvider extends PureComponent {
|
||||
}
|
||||
|
||||
fetchAndSetPrices = async () => {
|
||||
const currencies = prices.join(',')
|
||||
const currencies = conversions.join(',')
|
||||
const json = await fetchData(
|
||||
`https://api.coingecko.com/api/v3/simple/price?ids=ocean-protocol&vs_currencies=${currencies}`
|
||||
)
|
||||
|
||||
const newPrizes = Object.assign(
|
||||
...prices.map(key => ({
|
||||
ocean: 1,
|
||||
[key]: json['ocean-protocol'][key]
|
||||
}))
|
||||
)
|
||||
let newPrices = new Map(this.state.prices) // make a shallow copy of the Map
|
||||
conversions.map(key => newPrices.set(key, json['ocean-protocol'][key])) // modify the copy
|
||||
|
||||
this.setState({ prices: newPrizes })
|
||||
ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
||||
this.setState({ prices: newPrices })
|
||||
return newPrices
|
||||
}
|
||||
|
||||
setBalances = async () => {
|
||||
@ -89,9 +101,9 @@ export default class AppProvider extends PureComponent {
|
||||
for (const account of accountsPref) {
|
||||
const oceanBalance = await this.getBalance(account)
|
||||
|
||||
const conversions = Object.assign(
|
||||
...prices.map(key => ({
|
||||
[key]: oceanBalance * this.state.prices[key] || 0
|
||||
const conversionsBalance = Object.assign(
|
||||
...conversions.map(key => ({
|
||||
[key]: oceanBalance * this.state.prices.get(key) || 0
|
||||
}))
|
||||
)
|
||||
|
||||
@ -99,7 +111,7 @@ export default class AppProvider extends PureComponent {
|
||||
address: account,
|
||||
balance: {
|
||||
ocean: oceanBalance,
|
||||
...conversions
|
||||
...conversionsBalance
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +123,12 @@ export default class AppProvider extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
toggleCurrencies(currency) {
|
||||
const pricesNew = Array.from(this.state.prices)
|
||||
ipcRenderer.send('currency-updated', pricesNew, currency)
|
||||
this.setState({ currency })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<AppContext.Provider value={this.state}>
|
@ -15,7 +15,7 @@ const rgbaToHex = color => {
|
||||
}
|
||||
|
||||
const locale =
|
||||
typeof navigator !== 'undefined' ? navigator.language : app.getLocale()
|
||||
typeof navigator !== 'undefined' ? navigator.language : () => app.getLocale()
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
|
||||
const numberFormatter = value =>
|
||||
@ -39,7 +39,7 @@ const cryptoFormatter = (value, currency) => {
|
||||
if (currency === 'ocean') {
|
||||
return formatOcean(value)
|
||||
} else {
|
||||
return formatCurrency(value, currency.toUpperCase(), locale.split('-')[0])
|
||||
return formatCurrency(value, currency.toUpperCase(), locale)
|
||||
.replace(/BTC/, 'Ƀ')
|
||||
.replace(/ETH/, 'Ξ')
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ const path = require('path')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const CopyPlugin = require('copy-webpack-plugin')
|
||||
|
||||
// Any directories you will be adding code/files into, need to be added to this array so webpack will pick them up
|
||||
const defaultInclude = [path.resolve(__dirname, 'src')]
|
||||
const defaultInclude = [path.resolve(__dirname, 'src', 'renderer')]
|
||||
|
||||
module.exports = {
|
||||
entry: path.resolve(__dirname, 'src') + '/app/index.js',
|
||||
entry: path.resolve(__dirname, 'src', 'renderer', 'index.js'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: 'bundle.js',
|
||||
@ -33,11 +32,6 @@ module.exports = {
|
||||
test: /\.svg$/,
|
||||
use: ['@svgr/webpack'],
|
||||
include: defaultInclude
|
||||
},
|
||||
{
|
||||
test: /\.(eot|ttf|woff|woff2)$/,
|
||||
use: ['file-loader?name=font/[name]__[hash:base64:5].[ext]'],
|
||||
include: defaultInclude
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -48,7 +42,7 @@ module.exports = {
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
new CopyPlugin([
|
||||
{ from: './src/app/images/icon.*', to: './', flatten: true }
|
||||
{ from: './src/renderer/images/icon.*', to: './', flatten: true }
|
||||
])
|
||||
]
|
||||
}
|
||||
|