mirror of
https://github.com/kremalicious/blowfish.git
synced 2024-12-26 14:47:53 +01:00
refactor, add global error state
This commit is contained in:
parent
2efee0ec73
commit
33532c33d3
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
ETHERSCAN_API_KEY=
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,4 +5,5 @@ build
|
||||
dist
|
||||
coverage
|
||||
.next
|
||||
out
|
||||
out
|
||||
.env
|
@ -53,6 +53,7 @@
|
||||
"babel-jest": "^25.1.0",
|
||||
"copy": "^0.3.2",
|
||||
"cross-env": "^7.0.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"electron": "^8.0.1",
|
||||
"electron-builder": "^22.3.2",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
|
@ -2,8 +2,6 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import posed, { PoseGroup } from 'react-pose'
|
||||
import shortid from 'shortid'
|
||||
import AppProvider from './store/AppProvider'
|
||||
import PriceProvider from './store/PriceProvider'
|
||||
import { defaultAnimation } from './components/Animations'
|
||||
import Titlebar from './components/Titlebar'
|
||||
import styles from './Layout.module.css'
|
||||
@ -12,16 +10,14 @@ const Animation = posed.div(defaultAnimation)
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<PriceProvider>
|
||||
<AppProvider>
|
||||
{process.platform === 'darwin' && <Titlebar />}
|
||||
<div className={styles.app}>
|
||||
<PoseGroup animateOnMount>
|
||||
<Animation key={shortid.generate()}>{children}</Animation>
|
||||
</PoseGroup>
|
||||
</div>
|
||||
</AppProvider>
|
||||
</PriceProvider>
|
||||
<>
|
||||
{process.platform === 'darwin' && <Titlebar />}
|
||||
<div className={styles.app}>
|
||||
<PoseGroup animateOnMount>
|
||||
<Animation key={shortid.generate()}>{children}</Animation>
|
||||
</PoseGroup>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => {
|
||||
require('dotenv').config()
|
||||
|
||||
const withSvgr = (nextConfig = {}) => {
|
||||
return Object.assign({}, nextConfig, {
|
||||
webpack(config, options) {
|
||||
config.module.rules.push({
|
||||
@ -23,15 +24,25 @@ const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = withSvgr({
|
||||
webpack: config => {
|
||||
config.target = 'electron-renderer'
|
||||
return config
|
||||
},
|
||||
exportPathMap() {
|
||||
return {
|
||||
'/': { page: '/' },
|
||||
'/preferences': { page: '/preferences' }
|
||||
const withElectron = (nextConfig = {}) => {
|
||||
return Object.assign({}, nextConfig, {
|
||||
webpack: config => {
|
||||
config.target = 'electron-renderer'
|
||||
return config
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = withSvgr(
|
||||
withElectron({
|
||||
env: {
|
||||
ETHERSCAN_API_KEY: process.env.ETHERSCAN_API_KEY
|
||||
},
|
||||
exportPathMap() {
|
||||
return {
|
||||
'/': { page: '/' },
|
||||
'/preferences': { page: '/preferences' }
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
@ -2,6 +2,8 @@ import React, { useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Router from 'next/router'
|
||||
// import { ipcRenderer } from 'electron'
|
||||
import AppProvider from '../store/AppProvider'
|
||||
import PriceProvider from '../store/PriceProvider'
|
||||
import Layout from '../Layout'
|
||||
|
||||
import '../global.css'
|
||||
@ -14,9 +16,13 @@ export default function App({ Component, pageProps }) {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
<PriceProvider>
|
||||
<AppProvider>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</AppProvider>
|
||||
</PriceProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import IconCog from '../images/cog.svg'
|
||||
import styles from './index.module.css'
|
||||
|
||||
export default function Home() {
|
||||
const { isLoading, needsConfig } = useContext(AppContext)
|
||||
const { isLoading, error, needsConfig } = useContext(AppContext)
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -24,6 +24,8 @@ export default function Home() {
|
||||
|
||||
{needsConfig ? (
|
||||
<Welcome />
|
||||
) : error ? (
|
||||
<div className={styles.error}>{error}</div>
|
||||
) : isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
|
@ -32,3 +32,8 @@
|
||||
justify-items: start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 0.9rem;
|
||||
color: lightcoral;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { refreshInterval, conversions, oceanTokenContract } from '../../config'
|
||||
|
||||
async function getBalance(account) {
|
||||
const json = await fetchData(
|
||||
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest`
|
||||
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${oceanTokenContract}&address=${account}&tag=latest&apikey=${process.env.ETHERSCAN_API_KEY}`
|
||||
)
|
||||
|
||||
const balance = unit.fromWei(`${json.result}`, 'ether')
|
||||
@ -24,18 +24,26 @@ export default function AppProvider({ children }) {
|
||||
const [needsConfig, setNeedsConfig] = useState(false)
|
||||
const [currency, setCurrency] = useState('ocean')
|
||||
const [accentColor, setAccentColor] = useState('#f6388a')
|
||||
const [error, setError] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
// listener for accent color
|
||||
global.ipcRenderer.on('accent-color', (evt, accentColor) => {
|
||||
setAccentColor(accentColor)
|
||||
})
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
global.ipcRenderer.on('accent-color', (evt, accentColor) => {
|
||||
setAccentColor(accentColor)
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
await setBalances()
|
||||
setIsLoading(false)
|
||||
try {
|
||||
await setBalances()
|
||||
setIsLoading(false)
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
setError(error.message)
|
||||
}
|
||||
|
||||
// listener for touchbar
|
||||
global.ipcRenderer.on('setCurrency', (evt, currency) =>
|
||||
@ -96,9 +104,9 @@ export default function AppProvider({ children }) {
|
||||
}
|
||||
|
||||
function toggleCurrencies(currency) {
|
||||
setCurrency(currency)
|
||||
const pricesNew = Array.from(prices)
|
||||
global.ipcRenderer.send('currency-updated', pricesNew, currency)
|
||||
setCurrency(currency)
|
||||
}
|
||||
|
||||
const context = {
|
||||
@ -107,8 +115,9 @@ export default function AppProvider({ children }) {
|
||||
currency,
|
||||
needsConfig,
|
||||
accentColor,
|
||||
toggleCurrencies: currency => toggleCurrencies(currency),
|
||||
setBalances: () => setBalances()
|
||||
error,
|
||||
toggleCurrencies,
|
||||
setBalances
|
||||
}
|
||||
|
||||
return <AppContext.Provider value={context}>{children}</AppContext.Provider>
|
||||
|
@ -41,10 +41,14 @@ export default function PriceProvider({ children }) {
|
||||
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
const { newPrices, newPriceChanges } = await fetchAndSetPrices()
|
||||
setPrices(newPrices)
|
||||
setPriceChanges(newPriceChanges)
|
||||
global.ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
||||
try {
|
||||
const { newPrices, newPriceChanges } = await fetchAndSetPrices()
|
||||
setPrices(newPrices)
|
||||
setPriceChanges(newPriceChanges)
|
||||
global.ipcRenderer.send('prices-updated', Array.from(newPrices)) // convert Map to array, ipc messages seem to kill it
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
22
tests/Providers.test.jsx
Normal file
22
tests/Providers.test.jsx
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
import { render, waitForElement } from '@testing-library/react'
|
||||
import AppProvider from '../src/renderer/store/AppProvider'
|
||||
import PriceProvider from '../src/renderer/store/PriceProvider'
|
||||
import { PriceContext } from '../src/renderer/store/createContext'
|
||||
import { priceContext } from './__fixtures__/context'
|
||||
|
||||
describe('Providers', () => {
|
||||
it('PriceProvider', async () => {
|
||||
const { getByText } = render(<PriceProvider>Hello</PriceProvider>)
|
||||
await waitForElement(() => getByText('Hello'))
|
||||
})
|
||||
|
||||
it('AppProvider', async () => {
|
||||
const { getByText } = render(
|
||||
<PriceContext.Provider value={priceContext}>
|
||||
<AppProvider>Hello</AppProvider>
|
||||
</PriceContext.Provider>
|
||||
)
|
||||
await waitForElement(() => getByText('Hello'))
|
||||
})
|
||||
})
|
@ -1,10 +0,0 @@
|
||||
const global = {
|
||||
ipcRenderer: {
|
||||
on: () => jest.fn()
|
||||
},
|
||||
store: {
|
||||
has: () => jest.fn()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = global
|
Loading…
Reference in New Issue
Block a user