This commit is contained in:
Matthias Kretschmann 2019-05-20 22:32:57 +02:00
parent 09f37af8d5
commit 8097306dce
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 238 additions and 204 deletions

View File

@ -10,14 +10,26 @@ const Item = posed.div(fadeIn)
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">
<button
className="label label--price"
onClick={() => this.context.toggleCurrencies(key)}
disabled={this.context.needsConfig}
style={
key === this.context.currency && !this.context.needsConfig
? activeStyle
: {}
}
>
{cryptoFormatter(this.context.prices[key], key)}
</button>
</Item>
))
render() {
const {
toggleCurrencies,
needsConfig,
currency,
prices,
accentColor
} = this.context
const { accentColor } = this.context
const activeStyle = {
backgroundColor: accentColor,
@ -27,20 +39,7 @@ export default class Ticker extends PureComponent {
return (
<footer className="number-unit-wrap ticker" {...this.props}>
<PoseGroup animateOnMount>
{Object.keys(prices).map((key, i) => (
<Item key={i} className="number-unit">
<button
className="label label--price"
onClick={() => toggleCurrencies(key)}
disabled={needsConfig}
style={key === currency && !needsConfig ? activeStyle : {}}
>
{cryptoFormatter(prices[key], key)}
</button>
</Item>
))}
</PoseGroup>
<PoseGroup animateOnMount>{this.items(activeStyle)}</PoseGroup>
</footer>
)
}

View File

@ -1,130 +0,0 @@
import React, { PureComponent } from 'react'
import { Link } from '@reach/router'
import Store from 'electron-store'
import Blockies from 'react-blockies'
import ethereum_address from 'ethereum-address'
import posed, { PoseGroup } from 'react-pose'
import { AppContext } from '../store/createContext'
import './Preferences.css'
import { fadeIn } from '../components/Animations'
const Item = posed.li(fadeIn)
export default class Preferences extends PureComponent {
static contextType = AppContext
store = new Store()
state = { accounts: [], input: '', error: '' }
componentDidMount() {
if (this.store.has('accounts')) {
this.setState({ accounts: this.store.get('accounts') })
}
}
handleInputChange = e => {
this.setState({ input: e.target.value })
}
handleSave = e => {
e.preventDefault()
const { accounts, input } = this.state
const isEmpty = input === ''
const isDuplicate = accounts.includes(input)
const isAddress = ethereum_address.isAddress(input)
if (isEmpty) {
this.setState({ error: 'Please enter an address.' })
return
} else if (isDuplicate) {
this.setState({ error: 'Address already added. Try another one.' })
return
} else if (!isAddress) {
this.setState({ error: 'Not an Ethereum address. Try another one.' })
return
} else {
const joined = [...accounts, input]
this.store.set('accounts', joined)
this.setState({ accounts: joined, input: '', error: '' })
this.context.setBalances()
}
}
handleDelete = (e, account) => {
e.preventDefault()
let array = this.state.accounts
array = array.filter(item => account !== item)
const index = array.indexOf(account)
if (index > -1) {
array.splice(index, 1)
}
this.store.set('accounts', array)
this.setState({ accounts: array })
this.context.setBalances()
}
render() {
const { accounts, input, error } = this.state
return (
<div className="preferences">
<h1 className="preferences__title">Preferences</h1>{' '}
<Link className="preferences__close" title="Close Preferences" to="/">
&times;
</Link>
<div className="preference box">
<h2 className="preference__title">Accounts</h2>
<p className="preference__help">
Add Ethereum account addresses holding Ocean Tokens.
</p>
<ul className="preference__list">
<PoseGroup>
{accounts &&
accounts.map(account => (
<Item key={account}>
<div>
<Blockies seed={account} size={10} scale={3} />
{account}
</div>
<button
className="delete"
onClick={e => this.handleDelete(e, account)}
title="Remove account"
>
&times;
</button>
</Item>
))}
</PoseGroup>
<li>
<input
type="text"
placeholder="0xxxxxxxx"
value={input}
onChange={this.handleInputChange}
className="preference__input"
/>
<button
className="preference__input__add"
onClick={e => this.handleSave(e)}
style={{ color: this.context.accentColor }}
>
Add
</button>
</li>
</ul>
{error !== '' && <div className="preference__error">{error}</div>}
</div>
</div>
)
}
}

View File

@ -0,0 +1,149 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Blockies from 'react-blockies'
import posed, { PoseGroup } from 'react-pose'
import Store from 'electron-store'
import ethereum_address from 'ethereum-address'
import { AppContext } from '../../store/createContext'
import { fadeIn } from '../../components/Animations'
const Item = posed.li(fadeIn)
const AccountsList = ({ accounts, handleDelete }) => (
<PoseGroup>
{accounts.map(account => (
<Item key={account}>
<div>
<Blockies seed={account} size={10} scale={3} />
{account}
</div>
<button
className="delete"
onClick={e => handleDelete(e, account)}
title="Remove account"
>
&times;
</button>
</Item>
))}
</PoseGroup>
)
AccountsList.propTypes = {
accounts: PropTypes.array.isRequired,
handleDelete: PropTypes.func.isRequired
}
const AccountNew = ({ input, handleInputChange, handleSave, accentColor }) => (
<li>
<input
type="text"
placeholder="0xxxxxxxx"
value={input}
onChange={e => handleInputChange(e)}
className="preference__input"
/>
<button
className="preference__input__add"
onClick={e => handleSave(e)}
style={{ color: accentColor }}
>
Add
</button>
</li>
)
AccountNew.propTypes = {
input: PropTypes.string.isRequired,
handleInputChange: PropTypes.func.isRequired,
handleSave: PropTypes.func.isRequired,
accentColor: PropTypes.string.isRequired
}
export default class Accounts extends PureComponent {
static contextType = AppContext
store = new Store()
state = { accounts: [], input: '', error: '' }
componentDidMount() {
if (this.store.has('accounts')) {
this.setState({ accounts: this.store.get('accounts') })
}
}
handleInputChange = e => {
this.setState({ input: e.target.value })
}
handleSave = e => {
e.preventDefault()
const { accounts, input } = this.state
const isEmpty = input === ''
const isDuplicate = accounts.includes(input)
const isAddress = ethereum_address.isAddress(input)
if (isEmpty) {
this.setState({ error: 'Please enter an address.' })
return
} else if (isDuplicate) {
this.setState({ error: 'Address already added. Try another one.' })
return
} else if (!isAddress) {
this.setState({ error: 'Not an Ethereum address. Try another one.' })
return
} else {
const joined = [...accounts, input]
this.store.set('accounts', joined)
this.setState({ accounts: joined, input: '', error: '' })
this.context.setBalances()
}
}
handleDelete = (e, account) => {
e.preventDefault()
let array = this.state.accounts
array = array.filter(item => account !== item)
const index = array.indexOf(account)
if (index > -1) {
array.splice(index, 1)
}
this.store.set('accounts', array)
this.setState({ accounts: array })
this.context.setBalances()
}
render() {
const { accentColor } = this.context
const { accounts, input, error } = this.state
return (
<div className="preference box">
<h2 className="preference__title">Accounts</h2>
<p className="preference__help">
Add Ethereum account addresses holding Ocean Tokens.
</p>
<ul className="preference__list">
<AccountsList accounts={accounts} handleDelete={this.handleDelete} />
<AccountNew
input={input}
handleInputChange={this.handleInputChange}
accentColor={accentColor}
handleSave={this.handleSave}
/>
</ul>
{error !== '' && <div className="preference__error">{error}</div>}
</div>
)
}
}

View File

@ -0,0 +1,20 @@
import React, { PureComponent } from 'react'
import { Link } from '@reach/router'
import './index.css'
import Accounts from './Accounts'
export default class Preferences extends PureComponent {
render() {
return (
<div className="preferences">
<h1 className="preferences__title">Preferences</h1>{' '}
<Link className="preferences__close" title="Close Preferences" to="/">
&times;
</Link>
<Accounts />
</div>
)
}
}

View File

@ -20,6 +20,52 @@ if (
const width = 620
const height = 440
const installDevTools = async mainWindow => {
if (isDev) {
const {
default: installExtension,
REACT_DEVELOPER_TOOLS
} = require('electron-devtools-installer')
try {
const name = await installExtension(REACT_DEVELOPER_TOOLS)
console.log(`Added Extension: ${name}`) // eslint-disable-line no-console
mainWindow.webContents.on('devtools-opened', () =>
mainWindow.setSize(1024, 420, true)
)
mainWindow.webContents.on('devtools-closed', () =>
mainWindow.setSize(width, height, true)
)
} catch (error) {
console.log('An error occurred: ', error) // eslint-disable-line no-console
}
}
}
const createWindowEvents = mainWindow => {
mainWindow.on('enter-full-screen', () =>
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.add(\'fullscreen\')'
)
)
mainWindow.on('leave-full-screen', () =>
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.remove(\'fullscreen\')'
)
)
mainWindow.on('blur', () =>
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.add(\'blur\')'
)
)
mainWindow.on('focus', () =>
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.remove(\'blur\')'
)
)
}
const createWindow = async () => {
const isDarkMode = systemPreferences.isDarkMode()
@ -47,19 +93,8 @@ const createWindow = async () => {
: `file://${path.join(__dirname, '../build/index.html')}`
)
if (isDev) {
const {
default: installExtension,
REACT_DEVELOPER_TOOLS
} = require('electron-devtools-installer')
try {
const name = await installExtension(REACT_DEVELOPER_TOOLS)
console.log(`Added Extension: ${name}`) // eslint-disable-line no-console
} catch (error) {
console.log('An error occurred: ', error) // eslint-disable-line no-console
}
}
createWindowEvents(mainWindow)
installDevTools(mainWindow)
mainWindow.once('ready-to-show', () => {
mainWindow.show()
@ -70,49 +105,10 @@ const createWindow = async () => {
mainWindow = null
})
//
// Events
//
mainWindow.on('enter-full-screen', () => {
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.add(\'fullscreen\')'
)
})
mainWindow.on('leave-full-screen', () => {
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.remove(\'fullscreen\')'
)
})
mainWindow.on('blur', () => {
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.add(\'blur\')'
)
})
mainWindow.on('focus', () => {
mainWindow.webContents.executeJavaScript(
'document.getElementsByTagName(\'html\')[0].classList.remove(\'blur\')'
)
})
// Make window bigger automatically when devtools are opened
mainWindow.webContents.on('devtools-opened', () => {
mainWindow.setSize(1024, 420, true)
})
mainWindow.webContents.on('devtools-closed', () => {
mainWindow.setSize(width, height, true)
})
// Load menubar
buildMenu(mainWindow)
// Load touchbar
if (process.platform === 'darwin') {
touchBarWrapper(mainWindow)
}
process.platform === 'darwin' && touchBarWrapper(mainWindow)
}
app.on('ready', () => {