diff --git a/.editorconfig b/.editorconfig
index 013c8c5..37fee84 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,6 +8,3 @@ end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
-
-[*.css,*.scss]
-indent_size = 4
diff --git a/.stylelintrc b/.stylelintrc
index 38d2566..7f7097c 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -3,10 +3,5 @@
"stylelint-config-standard",
"stylelint-config-css-modules",
"./node_modules/prettier-stylelint/config.js"
- ],
- "rules": {
- "indentation": 4,
- "declaration-empty-line-before": null,
- "number-leading-zero": "never"
- }
+ ]
}
diff --git a/package.json b/package.json
index 1d145c5..0ab3db0 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,9 @@
"package": "electron-builder build -mwl -p never && open ./dist",
"dist": "rm -rf {dist,build}/ && npm run build && npm run package",
"release": "release-it --non-interactive",
- "changelog": "auto-changelog -p"
+ "changelog": "auto-changelog -p",
+ "format": "prettier --write 'src/**/*.{js,jsx}' && npm run format:css",
+ "format:css": "prettier-stylelint --write --quiet 'src/**/*.{css,scss}'"
},
"repository": "https://github.com/kremalicious/blowfish.git",
"homepage": "https://github.com/kremalicious/blowfish",
@@ -32,7 +34,6 @@
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
- "@babel/runtime": "^7.6.0",
"@reach/router": "^1.2.1",
"@svgr/webpack": "^4.3.2",
"auto-changelog": "^1.16.1",
@@ -51,14 +52,12 @@
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
- "node-sass": "^4.12.0",
"prettier": "^1.18.2",
"prettier-stylelint": "^0.4.2",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-pose": "^4.0.8",
"release-it": "^12.3.6",
- "sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"stylelint": "^10.1.0",
"stylelint-config-css-modules": "^1.4.0",
@@ -67,7 +66,7 @@
"webpack-cli": "^3.3.8",
"webpack-dev-server": "^3.8.0"
},
- "browserslist": "electron >= 5.0",
+ "browserslist": "electron >= 6.0",
"build": {
"appId": "com.kremalicious.blowfish",
"files": [
diff --git a/src/renderer/App.css b/src/renderer/App.css
deleted file mode 100644
index ea9ad65..0000000
--- a/src/renderer/App.css
+++ /dev/null
@@ -1,96 +0,0 @@
-*,
-*::before,
-*::after {
- box-sizing: border-box;
-}
-
-html,
-body {
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
- background: #fcfcfc !important;
- overflow: hidden;
-}
-
-html.dark,
-.dark body {
- background: #141414 !important;
-}
-
-html {
- font-size: 13px;
-}
-
-html.fullscreen {
- font-size: 24px;
-}
-
-#root {
- height: 100%;
- position: relative;
- font-size: 1rem;
- line-height: 1.3;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu,
- Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
- 'Segoe UI Symbol';
- font-feature-settings: 'kern' 1, 'liga' 1, 'calt' 1, 'pnum' 1, 'tnum' 0,
- 'onum' 0, 'lnum' 0, 'dlig' 1;
- color: #303030;
- transform: translate3d(0, 0, 0);
- -webkit-app-region: drag;
- -webkit-user-select: none;
-}
-
-.dark #root {
- color: #e2e2e2;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5 {
- font-weight: 700;
-}
-
-a,
-button {
- text-decoration: none;
- cursor: default;
-}
-
-a h1 {
- color: unset;
-}
-
-.app {
- padding: 10% 7% 5% 7%;
- cursor: default;
- transition: .15s ease-out;
- width: 100%;
- height: 100%;
- overflow-y: auto;
-}
-
-.darwin .app {
- padding-top: calc(35px + 10%);
-}
-
-.fullscreen.darwin .app {
- transform: translate3d(0, -36px, 0);
-}
-
-.box {
- width: 100%;
- padding: 5%;
- background: #fff;
- border-radius: 5px;
- border: .1rem solid #e2e2e2;
-}
-
-.dark .box {
- background: #222;
- border-color: #303030;
-}
diff --git a/src/renderer/App.jsx b/src/renderer/App.jsx
index b04c4e6..6454683 100644
--- a/src/renderer/App.jsx
+++ b/src/renderer/App.jsx
@@ -10,10 +10,10 @@ import {
import { webFrame, ipcRenderer } from 'electron'
import posed, { PoseGroup } from 'react-pose'
import Titlebar from './components/Titlebar'
+import { defaultAnimation } from './components/Animations'
import Home from './screens/Home'
import Preferences from './screens/Preferences'
-import './App.css'
-import { defaultAnimation } from './components/Animations'
+import styles from './App.module.css'
//
// Disable zooming
@@ -55,7 +55,7 @@ export default class App extends PureComponent {
return (
<>
{process.platform === 'darwin' && }
-
+
diff --git a/src/renderer/App.module.css b/src/renderer/App.module.css
new file mode 100644
index 0000000..fee0a99
--- /dev/null
+++ b/src/renderer/App.module.css
@@ -0,0 +1,16 @@
+.app {
+ padding: 10% 7% 5% 7%;
+ cursor: default;
+ transition: 0.15s ease-out;
+ width: 100%;
+ height: 100%;
+ overflow-y: auto;
+}
+
+:global(.darwin) .app {
+ padding-top: calc(35px + 10%);
+}
+
+:global(.fullscreen.darwin) .app {
+ transform: translate3d(0, -36px, 0);
+}
diff --git a/src/renderer/components/Account.jsx b/src/renderer/components/Account.jsx
deleted file mode 100644
index b4751b4..0000000
--- a/src/renderer/components/Account.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import { openUrl } from '../../utils'
-import Balance from './Balance'
-
-export default class Account extends PureComponent {
- static propTypes = {
- account: PropTypes.shape({
- address: PropTypes.string.isRequired,
- balance: PropTypes.object.isRequired
- })
- }
-
- render() {
- const { account } = this.props
- const { balance, address } = account
-
- return (
-
- )
- }
-}
diff --git a/src/renderer/components/Balance.jsx b/src/renderer/components/Balance.jsx
index ee0feac..0335a40 100644
--- a/src/renderer/components/Balance.jsx
+++ b/src/renderer/components/Balance.jsx
@@ -1,30 +1,37 @@
-import React, { PureComponent } from 'react'
+import React, { useContext } from 'react'
import PropTypes from 'prop-types'
import posed, { PoseGroup } from 'react-pose'
import { AppContext } from '../store/createContext'
import { cryptoFormatter } from '../../utils'
-import styles from './Balance.module.scss'
import { fadeIn } from './Animations'
+import Label from './Label'
+import styles from './Balance.module.css'
const Animation = posed.h1(fadeIn)
-export default class Balance extends PureComponent {
- static contextType = AppContext
+const Balance = ({ balance, label, labelOnClick, large }) => {
+ const { currency } = useContext(AppContext)
- static propTypes = {
- balance: PropTypes.object.isRequired
- }
-
- render() {
- const { currency } = this.context
- const { balance } = this.props
-
- return (
+ return (
+
-
+
{cryptoFormatter(balance[currency], currency)}
- )
- }
+ {label &&
}
+
+ )
}
+
+Balance.propTypes = {
+ balance: PropTypes.object.isRequired,
+ label: PropTypes.string,
+ labelOnClick: PropTypes.func,
+ large: PropTypes.bool
+}
+
+export default Balance
diff --git a/src/renderer/components/Balance.module.css b/src/renderer/components/Balance.module.css
new file mode 100644
index 0000000..5099139
--- /dev/null
+++ b/src/renderer/components/Balance.module.css
@@ -0,0 +1,33 @@
+.balance {
+ text-align: center;
+ width: 100%;
+}
+
+.number {
+ margin: 0;
+ -webkit-app-region: no-drag;
+ -webkit-user-select: text;
+ font-size: 1rem;
+ display: inline-block;
+ padding: 0 0.3rem;
+ border-radius: 4px;
+}
+
+.numberLarge {
+ composes: number;
+ font-size: 2.5rem;
+}
+
+.updated {
+ animation: updated 0.5s ease-out;
+}
+
+@keyframes updated {
+ 0% {
+ background: rgba(255, 255, 255, 0.2);
+ }
+
+ 100% {
+ background: rgba(255, 255, 255, 0);
+ }
+}
diff --git a/src/renderer/components/Balance.module.scss b/src/renderer/components/Balance.module.scss
deleted file mode 100644
index 02fcd70..0000000
--- a/src/renderer/components/Balance.module.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.number {
- margin: 0;
- -webkit-app-region: no-drag;
- -webkit-user-select: text;
- font-size: 1rem;
- display: inline-block;
- padding: 0 .3rem;
- border-radius: 4px;
-
- :global(.number-unit--main) & {
- font-size: 2.5rem;
- }
-}
-
-.updated {
- animation: updated .5s ease-out;
-}
-
-@keyframes updated {
- 0% {
- background: rgba(255, 255, 255, .2);
- }
-
- 100% {
- background: rgba(255, 255, 255, 0);
- }
-}
diff --git a/src/renderer/components/Box.module.css b/src/renderer/components/Box.module.css
new file mode 100644
index 0000000..b436e46
--- /dev/null
+++ b/src/renderer/components/Box.module.css
@@ -0,0 +1,12 @@
+.box {
+ width: 100%;
+ padding: 5%;
+ background: #fff;
+ border-radius: 5px;
+ border: 0.1rem solid #e2e2e2;
+}
+
+:global(.dark) .box {
+ background: #222;
+ border-color: #303030;
+}
diff --git a/src/renderer/components/Divider.jsx b/src/renderer/components/Divider.jsx
new file mode 100644
index 0000000..a9c1e8c
--- /dev/null
+++ b/src/renderer/components/Divider.jsx
@@ -0,0 +1,6 @@
+import React from 'react'
+import styles from './Divider.module.css'
+
+const Divider = () =>
+
+export default Divider
diff --git a/src/renderer/components/Divider.module.css b/src/renderer/components/Divider.module.css
new file mode 100644
index 0000000..213d994
--- /dev/null
+++ b/src/renderer/components/Divider.module.css
@@ -0,0 +1,11 @@
+.divider {
+ width: 100%;
+ height: 1px;
+ background: #e2e2e2;
+ margin-top: 5%;
+ border: 0;
+}
+
+:global(.dark) .divider {
+ background: #303030;
+}
diff --git a/src/renderer/components/Label.jsx b/src/renderer/components/Label.jsx
new file mode 100644
index 0000000..dc68f70
--- /dev/null
+++ b/src/renderer/components/Label.jsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './Label.module.css'
+
+const Label = ({ children, labelOnClick, ...props }) => (
+
+ {children}
+
+)
+
+Label.propTypes = {
+ labelOnClick: PropTypes.func,
+ children: PropTypes.any.isRequired
+}
+
+export default Label
diff --git a/src/renderer/components/Label.module.css b/src/renderer/components/Label.module.css
new file mode 100644
index 0000000..ab262ca
--- /dev/null
+++ b/src/renderer/components/Label.module.css
@@ -0,0 +1,7 @@
+.label {
+ color: #8b98a9;
+ font-size: 0.85rem;
+ display: block;
+ white-space: nowrap;
+ margin-top: 0.5rem;
+}
diff --git a/src/renderer/components/Spinner.jsx b/src/renderer/components/Spinner.jsx
index 14e53de..5e8310a 100644
--- a/src/renderer/components/Spinner.jsx
+++ b/src/renderer/components/Spinner.jsx
@@ -1,5 +1,5 @@
import React from 'react'
-import styles from './Spinner.module.scss'
+import styles from './Spinner.module.css'
const Spinner = () =>
diff --git a/src/renderer/components/Spinner.module.css b/src/renderer/components/Spinner.module.css
new file mode 100644
index 0000000..ed36c44
--- /dev/null
+++ b/src/renderer/components/Spinner.module.css
@@ -0,0 +1,28 @@
+.spinner {
+ position: relative;
+ text-align: center;
+ margin: auto;
+ width: 100%;
+}
+
+.spinner::before {
+ content: '';
+ box-sizing: border-box;
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 20px;
+ height: 20px;
+ margin-top: -20px;
+ margin-left: -10px;
+ border-radius: 50%;
+ border: 2px solid #7b1173;
+ border-top-color: #e000cf;
+ animation: spinner 0.6s linear infinite;
+}
+
+@keyframes spinner {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/renderer/components/Spinner.module.scss b/src/renderer/components/Spinner.module.scss
deleted file mode 100644
index b01c1a0..0000000
--- a/src/renderer/components/Spinner.module.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-.spinner {
- position: relative;
- text-align: center;
- margin: auto;
- width: 100%;
-
- &::before {
- content: '';
- box-sizing: border-box;
- position: absolute;
- top: 0;
- left: 50%;
- width: 20px;
- height: 20px;
- margin-top: -20px;
- margin-left: -10px;
- border-radius: 50%;
- border: 2px solid #7b1173;
- border-top-color: #e000cf;
- animation: spinner .6s linear infinite;
- }
-}
-
-@keyframes spinner {
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/renderer/components/Ticker.css b/src/renderer/components/Ticker.css
deleted file mode 100644
index 67b2bc3..0000000
--- a/src/renderer/components/Ticker.css
+++ /dev/null
@@ -1,56 +0,0 @@
-.ticker {
- margin-top: 3rem;
- width: 100%;
-}
-
-.ticker .number-unit {
- margin-top: 0;
-}
-
-.ticker button {
- background: none;
- border: 1px solid #e2e2e2;
- box-shadow: none;
- margin: 0 auto;
- outline: 0;
- font-size: .75rem;
- border-radius: .3rem;
- padding: .3rem .4rem;
- display: block;
- width: 100%;
- max-width: 12rem;
- transition: border .2s ease-out;
- color: #41474e;
-}
-
-.ticker button:disabled {
- pointer-events: none;
-}
-
-.dark .ticker button {
- border-color: #303030;
- color: #8b98a9;
-}
-
-.label--price {
- font-size: .95rem;
-}
-
-.change {
- font-size: .65rem;
- display: inline-block;
- margin-left: .25rem;
-}
-
-.change--positive {
- color: forestgreen;
-}
-
-.change--negative {
- color: crimson;
-}
-
-.active .change--positive,
-.active .change--negative {
- color: #fff !important;
-}
diff --git a/src/renderer/components/Ticker.jsx b/src/renderer/components/Ticker.jsx
deleted file mode 100644
index 8183b29..0000000
--- a/src/renderer/components/Ticker.jsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import posed, { PoseGroup } from 'react-pose'
-import { AppContext } from '../store/createContext'
-import { cryptoFormatter } from '../../utils'
-import './Ticker.css'
-import { fadeIn } from './Animations'
-
-const Item = posed.div(fadeIn)
-
-const Change = ({ currency }) => (
-
- {({ priceChanges }) => {
- const isNegative = JSON.stringify(priceChanges[currency]).startsWith('-')
- let classes = isNegative ? 'change--negative' : 'change--positive'
-
- return (
-
- {!isNegative && '+'}
- {Number(priceChanges[currency]).toFixed(1)}%
-
- )
- }}
-
-)
-
-Change.propTypes = {
- currency: PropTypes.string.isRequired
-}
-
-export default class Ticker extends PureComponent {
- static contextType = AppContext
-
- items = () => {
- const {
- prices,
- needsConfig,
- currency,
- toggleCurrencies,
- accentColor
- } = this.context
-
- const activeStyle = {
- backgroundColor: accentColor,
- color: '#fff',
- borderColor: accentColor
- }
-
- // convert Map to array first, cause for...of or forEach returns
- // undefined, so it cannot be mapped to a collection of elements
- return [...prices.entries()].map(([key, value]) => (
- -
-
-
- ))
- }
-
- render() {
- return (
-
- )
- }
-}
diff --git a/src/renderer/components/Titlebar.jsx b/src/renderer/components/Titlebar.jsx
index fc1daa0..d0d1acf 100644
--- a/src/renderer/components/Titlebar.jsx
+++ b/src/renderer/components/Titlebar.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import pkg from '../../../package.json'
-import styles from './Titlebar.module.scss'
+import styles from './Titlebar.module.css'
const Titlebar = () => (
diff --git a/src/renderer/components/Titlebar.module.css b/src/renderer/components/Titlebar.module.css
new file mode 100644
index 0000000..e20ecb9
--- /dev/null
+++ b/src/renderer/components/Titlebar.module.css
@@ -0,0 +1,48 @@
+.titlebar {
+ position: fixed;
+ width: 100%;
+ height: 35px;
+ line-height: 35px;
+ text-align: center;
+ user-select: none;
+ background: linear-gradient(to top, #ccc 0%, #d6d6d6 1px, #ebebeb 100%);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
+ transition: opacity 0.15s ease-out;
+}
+
+:global(.dark) .titlebar {
+ background: linear-gradient(to top, #141416 0%, #38383c 1px, #3f3f44 100%);
+ box-shadow: none;
+}
+
+:global(.fullscreen) .titlebar {
+ opacity: 0;
+}
+
+:global(.blur) .titlebar {
+ background: #f6f6f6;
+}
+
+:global(.blur.dark) .titlebar {
+ background: linear-gradient(to top, #141416 0%, #2d2a32 1px, #2d2a32 100%);
+}
+
+.titlebarTitle {
+ line-height: 35px;
+ height: 35px;
+ font-weight: 400;
+ font-size: 13px;
+ color: #555;
+}
+
+:global(.dark) .titlebarTitle {
+ color: #b6b3ba;
+}
+
+:global(.blur) .titlebarTitle {
+ color: #b6b6b6;
+}
+
+:global(.blur.dark) .titlebarTitle {
+ color: #67666e;
+}
diff --git a/src/renderer/components/Titlebar.module.scss b/src/renderer/components/Titlebar.module.scss
deleted file mode 100644
index d55a871..0000000
--- a/src/renderer/components/Titlebar.module.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-.titlebar {
- position: fixed;
- width: 100%;
- height: 35px;
- line-height: 35px;
- text-align: center;
- user-select: none;
- background: linear-gradient(to top, #ccc 0%, #d6d6d6 1px, #ebebeb 100%);
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
- transition: opacity .15s ease-out;
-
- :global(.dark) & {
- background: linear-gradient(
- to top,
- #141416 0%,
- #38383c 1px,
- #3f3f44 100%
- );
- box-shadow: none;
- }
-
- :global(.fullscreen) & {
- opacity: 0;
- }
-
- :global(.blur) & {
- background: #f6f6f6;
- }
-
- :global(.blur.dark) & {
- background: linear-gradient(
- to top,
- #141416 0%,
- #2d2a32 1px,
- #2d2a32 100%
- );
- }
-}
-
-.titlebarTitle {
- line-height: 35px;
- height: 35px;
- font-weight: 400;
- font-size: 13px;
- color: #555;
-
- :global(.dark) & {
- color: #b6b3ba;
- }
-
- :global(.blur) & {
- color: #b6b6b6;
- }
-
- :global(.blur.dark) & {
- color: #67666e;
- }
-}
diff --git a/src/renderer/components/Total.jsx b/src/renderer/components/Total.jsx
deleted file mode 100644
index 4812f28..0000000
--- a/src/renderer/components/Total.jsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React, { PureComponent } from 'react'
-import { AppContext } from '../store/createContext'
-import Balance from './Balance'
-import { conversions } from '../../config'
-
-const calculateTotalBalance = (accounts, currency) => {
- const balanceTotalArray = []
-
- for (const account of accounts) {
- balanceTotalArray.push(account.balance[currency])
- }
-
- // Convert array to numbers and add numbers together
- const balanceTotal = balanceTotalArray.reduce(
- (a, b) => Number(a) + Number(b),
- 0
- )
-
- return balanceTotal
-}
-
-export default class Total extends PureComponent {
- static contextType = AppContext
-
- render() {
- const conversionsBalance = Object.assign(
- ...conversions.map(key => ({
- [key]: calculateTotalBalance(this.context.accounts, key)
- }))
- )
-
- const balanceNew = {
- ocean: calculateTotalBalance(this.context.accounts, 'ocean'),
- ...conversionsBalance
- }
-
- return (
-
-
- Total Balance
-
- )
- }
-}
diff --git a/src/renderer/components/Welcome.jsx b/src/renderer/components/Welcome.jsx
index 0f8e937..648b3c1 100644
--- a/src/renderer/components/Welcome.jsx
+++ b/src/renderer/components/Welcome.jsx
@@ -1,20 +1,20 @@
-import React from 'react'
+import React, { useContext } from 'react'
import { Link } from '@reach/router'
-import IconRocket from '../images/rocket.svg'
-import styles from './Welcome.module.scss'
import { AppContext } from '../store/createContext'
+import IconRocket from '../images/rocket.svg'
+import styles from './Welcome.module.css'
-const Welcome = () => (
-
-
-
- {context => (
-
- Add your first address to get started.
-
- )}
-
-
-)
+const Welcome = () => {
+ const { accentColor } = useContext(AppContext)
+
+ return (
+
+
+
+ Add your first address to get started.
+
+
+ )
+}
export default Welcome
diff --git a/src/renderer/components/Welcome.module.css b/src/renderer/components/Welcome.module.css
new file mode 100644
index 0000000..1ccf81e
--- /dev/null
+++ b/src/renderer/components/Welcome.module.css
@@ -0,0 +1,18 @@
+.welcome {
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ margin-top: 2rem;
+}
+
+.welcome svg {
+ display: block;
+ width: 5rem;
+ height: 5rem;
+ margin: 0 auto 2rem auto;
+ fill: #e2e2e2;
+}
+
+:global(.dark) .welcome svg {
+ fill: #41474e;
+}
diff --git a/src/renderer/components/Welcome.module.scss b/src/renderer/components/Welcome.module.scss
deleted file mode 100644
index c389e27..0000000
--- a/src/renderer/components/Welcome.module.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-.welcome {
- width: 100%;
- height: 100%;
- text-align: center;
- margin-top: 2rem;
-
- svg {
- display: block;
- width: 5rem;
- height: 5rem;
- margin: 0 auto 2rem auto;
- fill: #e2e2e2;
- }
-
- :global(.dark) & svg {
- fill: #41474e;
- }
-}
diff --git a/src/renderer/index.css b/src/renderer/index.css
new file mode 100644
index 0000000..ac4fad4
--- /dev/null
+++ b/src/renderer/index.css
@@ -0,0 +1,66 @@
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ background: #fcfcfc !important;
+ overflow: hidden;
+}
+
+html.dark,
+.dark body {
+ background: #141414 !important;
+}
+
+html {
+ font-size: 13px;
+}
+
+html.fullscreen {
+ font-size: 24px;
+}
+
+#root {
+ height: 100%;
+ position: relative;
+ font-size: 1rem;
+ line-height: 1.3;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu,
+ Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
+ 'Segoe UI Symbol';
+ font-feature-settings: 'kern' 1, 'liga' 1, 'calt' 1, 'pnum' 1, 'tnum' 0,
+ 'onum' 0, 'lnum' 0, 'dlig' 1;
+ color: #303030;
+ transform: translate3d(0, 0, 0);
+ -webkit-app-region: drag;
+ -webkit-user-select: none;
+}
+
+.dark #root {
+ color: #e2e2e2;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5 {
+ font-weight: 700;
+}
+
+a,
+button {
+ text-decoration: none;
+ cursor: default;
+}
+
+a h1 {
+ color: unset;
+}
diff --git a/src/renderer/index.js b/src/renderer/index.js
index 631d13d..e606b4d 100644
--- a/src/renderer/index.js
+++ b/src/renderer/index.js
@@ -3,6 +3,7 @@ import { render } from 'react-dom'
import AppProvider from './store/AppProvider'
import App from './App'
import pkg from '../../package.json'
+import './index.css'
document.body.style.backgroundColor = '#141414'
diff --git a/src/renderer/screens/Home.css b/src/renderer/screens/Home.css
deleted file mode 100644
index d603c96..0000000
--- a/src/renderer/screens/Home.css
+++ /dev/null
@@ -1,60 +0,0 @@
-.main {
- min-height: 222px;
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- position: relative;
-}
-
-.preferences-link {
- position: absolute;
- right: 5%;
- top: 1.5rem;
-}
-
-.preferences-link svg {
- fill: #8b98a9;
- transition: .2s ease-out;
- width: 1.25rem;
- height: 1.25rem;
-}
-
-.dark .preferences-link svg {
- fill: #8b98a9;
- opacity: .5;
-}
-
-.number-unit-wrap {
- display: grid;
- grid-gap: .5rem;
- grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
- justify-items: start;
- width: 100%;
-}
-
-.number-unit {
- text-align: center;
- width: 100%;
-}
-
-.label {
- color: #8b98a9;
- font-size: .85rem;
- display: block;
- white-space: nowrap;
- margin-top: .5rem;
-}
-
-.number-unit-wrap--accounts {
- min-height: 55px;
- padding-top: 2rem;
-}
-
-.number-unit--main {
- padding-bottom: 5%;
- border-bottom: 1px solid #e2e2e2;
-}
-
-.dark .number-unit--main {
- border-bottom-color: #303030;
-}
diff --git a/src/renderer/screens/Home.jsx b/src/renderer/screens/Home.jsx
deleted file mode 100644
index 5627ba9..0000000
--- a/src/renderer/screens/Home.jsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import React, { PureComponent } from 'react'
-import { Link } from '@reach/router'
-import { AppContext } from '../store/createContext'
-import Welcome from '../components/Welcome'
-import Total from '../components/Total'
-import Account from '../components/Account'
-import Ticker from '../components/Ticker'
-import Spinner from '../components/Spinner'
-import IconCog from '../images/cog.svg'
-import './Home.css'
-
-export default class Home extends PureComponent {
- static contextType = AppContext
-
- render() {
- const { isLoading, accounts, needsConfig } = this.context
-
- return (
- <>
-
-
-
-
-
- {needsConfig ? (
-
- ) : isLoading ? (
-
- ) : (
- <>
-
-
-
- {accounts.map((account, i) => (
-
- ))}
-
- >
- )}
-
-
-
- >
- )
- }
-}
diff --git a/src/renderer/screens/Home/Accounts.jsx b/src/renderer/screens/Home/Accounts.jsx
new file mode 100644
index 0000000..d0ebc14
--- /dev/null
+++ b/src/renderer/screens/Home/Accounts.jsx
@@ -0,0 +1,26 @@
+import React, { useContext } from 'react'
+import { openUrl } from '../../../utils'
+import Balance from '../../components/Balance'
+import { AppContext } from '../../store/createContext'
+import styles from './Accounts.module.css'
+
+const Accounts = () => {
+ const { accounts } = useContext(AppContext)
+
+ return (
+
+ {accounts.map((account, i) => (
+
+ openUrl(`https://etherscan.io/address/${account.address}#tokentxns`)
+ }
+ />
+ ))}
+
+ )
+}
+
+export default Accounts
diff --git a/src/renderer/screens/Home/Accounts.module.css b/src/renderer/screens/Home/Accounts.module.css
new file mode 100644
index 0000000..295138a
--- /dev/null
+++ b/src/renderer/screens/Home/Accounts.module.css
@@ -0,0 +1,5 @@
+.accounts {
+ composes: balanceWrap from './index.module.css';
+ min-height: 55px;
+ padding-top: 2rem;
+}
diff --git a/src/renderer/screens/Home/Ticker.jsx b/src/renderer/screens/Home/Ticker.jsx
new file mode 100644
index 0000000..1e69168
--- /dev/null
+++ b/src/renderer/screens/Home/Ticker.jsx
@@ -0,0 +1,71 @@
+import React, { useContext } from 'react'
+import PropTypes from 'prop-types'
+import posed, { PoseGroup } from 'react-pose'
+import { AppContext } from '../../store/createContext'
+import { cryptoFormatter } from '../../../utils'
+import stylesIndex from './index.module.css'
+import styles from './Ticker.module.css'
+import { fadeIn } from '../../components/Animations'
+
+const Item = posed.div(fadeIn)
+
+const Change = ({ currency }) => {
+ const { priceChanges } = useContext(AppContext)
+ const isNegative = JSON.stringify(priceChanges[currency]).startsWith('-')
+ let classes = isNegative ? styles.negative : styles.positive
+
+ return (
+
+ {!isNegative && '+'}
+ {Number(priceChanges[currency]).toFixed(1)}%
+
+ )
+}
+
+Change.propTypes = {
+ currency: PropTypes.string.isRequired
+}
+
+const Items = () => {
+ const {
+ prices,
+ needsConfig,
+ currency,
+ toggleCurrencies,
+ accentColor
+ } = useContext(AppContext)
+
+ const activeStyle = {
+ backgroundColor: accentColor,
+ color: '#fff',
+ borderColor: accentColor
+ }
+
+ // convert Map to array first, cause for...of or forEach returns
+ // undefined, so it cannot be mapped to a collection of elements
+ return [...prices.entries()].map(([key, value]) => (
+ -
+
+
+ ))
+}
+
+const Ticker = props => (
+
+)
+
+export default Ticker
diff --git a/src/renderer/screens/Home/Ticker.module.css b/src/renderer/screens/Home/Ticker.module.css
new file mode 100644
index 0000000..3772080
--- /dev/null
+++ b/src/renderer/screens/Home/Ticker.module.css
@@ -0,0 +1,76 @@
+.ticker {
+ margin-top: 3rem;
+ width: 100%;
+}
+
+.ticker button {
+ background: none;
+ border: 1px solid #e2e2e2;
+ box-shadow: none;
+ margin: 0 auto;
+ outline: 0;
+ font-size: 0.75rem;
+ border-radius: 0.3rem;
+ padding: 0.3rem 0.4rem;
+ display: block;
+ width: 100%;
+ max-width: 12rem;
+ transition: border 0.2s ease-out;
+ color: #41474e;
+}
+
+.ticker button:disabled {
+ pointer-events: none;
+}
+
+:global(.dark) .ticker button {
+ border-color: #303030;
+ color: #8b98a9;
+}
+
+.label--price {
+ font-size: 0.95rem;
+}
+
+.change {
+ font-size: 0.65rem;
+ display: inline-block;
+ margin-left: 0.25rem;
+}
+
+.positive {
+ composes: change;
+ color: forestgreen;
+}
+
+.negative {
+ composes: change;
+ color: crimson;
+}
+
+:global(.active) .positive,
+:global(.active) .negative {
+ color: #fff !important;
+}
+
+.number {
+ text-align: center;
+ width: 100%;
+}
+
+.label {
+ color: #8b98a9;
+ font-size: 0.85rem;
+ display: block;
+ white-space: nowrap;
+ margin-top: 0.5rem;
+}
+
+.labelActive {
+ composes: label;
+}
+
+.labelActive .positive,
+.labelActive .negative {
+ color: #fff !important;
+}
diff --git a/src/renderer/screens/Home/Total.jsx b/src/renderer/screens/Home/Total.jsx
new file mode 100644
index 0000000..85b24e1
--- /dev/null
+++ b/src/renderer/screens/Home/Total.jsx
@@ -0,0 +1,39 @@
+import React, { useContext } from 'react'
+import { AppContext } from '../../store/createContext'
+import Balance from '../../components/Balance'
+import { conversions } from '../../../config'
+
+const calculateTotalBalance = (accounts, currency) => {
+ const balanceTotalArray = []
+
+ for (const account of accounts) {
+ balanceTotalArray.push(account.balance[currency])
+ }
+
+ // Convert array to numbers and add numbers together
+ const balanceTotal = balanceTotalArray.reduce(
+ (a, b) => Number(a) + Number(b),
+ 0
+ )
+
+ return balanceTotal
+}
+
+const Total = () => {
+ const { accounts } = useContext(AppContext)
+
+ const conversionsBalance = Object.assign(
+ ...conversions.map(key => ({
+ [key]: calculateTotalBalance(accounts, key)
+ }))
+ )
+
+ const balanceNew = {
+ ocean: calculateTotalBalance(accounts, 'ocean'),
+ ...conversionsBalance
+ }
+
+ return
+}
+
+export default Total
diff --git a/src/renderer/screens/Home/index.jsx b/src/renderer/screens/Home/index.jsx
new file mode 100644
index 0000000..5bd4259
--- /dev/null
+++ b/src/renderer/screens/Home/index.jsx
@@ -0,0 +1,41 @@
+import React, { useContext } from 'react'
+import { Link } from '@reach/router'
+import { AppContext } from '../../store/createContext'
+import Welcome from '../../components/Welcome'
+import Spinner from '../../components/Spinner'
+import Divider from '../../components/Divider'
+import Total from './Total'
+import Ticker from './Ticker'
+import Accounts from './Accounts'
+import IconCog from '../../images/cog.svg'
+import styles from './index.module.css'
+
+const Home = () => {
+ const { isLoading, needsConfig } = useContext(AppContext)
+
+ return (
+ <>
+
+
+
+
+
+ {needsConfig ? (
+
+ ) : isLoading ? (
+
+ ) : (
+ <>
+
+
+
+ >
+ )}
+
+
+
+ >
+ )
+}
+
+export default Home
diff --git a/src/renderer/screens/Home/index.module.css b/src/renderer/screens/Home/index.module.css
new file mode 100644
index 0000000..1c6a3ee
--- /dev/null
+++ b/src/renderer/screens/Home/index.module.css
@@ -0,0 +1,34 @@
+.main {
+ composes: box from '../../components/Box.module.css';
+ min-height: 222px;
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ position: relative;
+}
+
+.preferences {
+ position: absolute;
+ right: 5%;
+ top: 1.5rem;
+}
+
+.preferences svg {
+ fill: #8b98a9;
+ transition: 0.2s ease-out;
+ width: 1.25rem;
+ height: 1.25rem;
+}
+
+:global(.dark) .preferences svg {
+ fill: #8b98a9;
+ opacity: 0.5;
+}
+
+.balanceWrap {
+ display: grid;
+ grid-gap: 0.5rem;
+ grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
+ justify-items: start;
+ width: 100%;
+}
diff --git a/src/renderer/screens/Preferences/Accounts/New.jsx b/src/renderer/screens/Preferences/Accounts/New.jsx
new file mode 100644
index 0000000..c72a0a8
--- /dev/null
+++ b/src/renderer/screens/Preferences/Accounts/New.jsx
@@ -0,0 +1,32 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './New.module.css'
+
+const New = ({ input, handleInputChange, handleSave, accentColor }) => (
+
+ handleInputChange(e)}
+ className={styles.input}
+ />
+
+
+
+)
+
+New.propTypes = {
+ input: PropTypes.string.isRequired,
+ handleInputChange: PropTypes.func.isRequired,
+ handleSave: PropTypes.func.isRequired,
+ accentColor: PropTypes.string.isRequired
+}
+
+export default New
diff --git a/src/renderer/screens/Preferences/Accounts/New.module.css b/src/renderer/screens/Preferences/Accounts/New.module.css
new file mode 100644
index 0000000..b91589a
--- /dev/null
+++ b/src/renderer/screens/Preferences/Accounts/New.module.css
@@ -0,0 +1,18 @@
+.input {
+ font-size: 1rem;
+ outline: 0;
+ background: none;
+ border: 0;
+ width: 80%;
+ color: #303030;
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+:global(.dark) .input {
+ color: #fff;
+}
+
+.button {
+ composes: button from './index.module.css';
+}
diff --git a/src/renderer/screens/Preferences/Accounts/Saved.jsx b/src/renderer/screens/Preferences/Accounts/Saved.jsx
new file mode 100644
index 0000000..774e949
--- /dev/null
+++ b/src/renderer/screens/Preferences/Accounts/Saved.jsx
@@ -0,0 +1,40 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { toDataUrl } from 'ethereum-blockies'
+import posed, { PoseGroup } from 'react-pose'
+import { fadeIn } from '../../../components/Animations'
+import styles from './Saved.module.css'
+
+const Item = posed.li(fadeIn)
+
+const Saved = ({ accounts, handleDelete }) => (
+
+ {accounts.map(account => {
+ const identicon = account && toDataUrl(account)
+
+ return (
+ -
+
+
+ {account}
+
+
+
+
+ )
+ })}
+
+)
+
+Saved.propTypes = {
+ accounts: PropTypes.array.isRequired,
+ handleDelete: PropTypes.func.isRequired
+}
+
+export default Saved
diff --git a/src/renderer/screens/Preferences/Accounts/Saved.module.css b/src/renderer/screens/Preferences/Accounts/Saved.module.css
new file mode 100644
index 0000000..234853f
--- /dev/null
+++ b/src/renderer/screens/Preferences/Accounts/Saved.module.css
@@ -0,0 +1,15 @@
+.identicon {
+ width: 1.5rem !important;
+ height: 1.5rem !important;
+ border-radius: 50%;
+ margin-right: 0.75rem;
+}
+
+.delete {
+ composes: button from './index.module.css';
+ position: relative;
+ font-size: 2rem;
+ top: -0.2rem;
+ color: #41474e;
+ transition: color 0.5s ease-out;
+}
diff --git a/src/renderer/screens/Preferences/Accounts.jsx b/src/renderer/screens/Preferences/Accounts/index.jsx
similarity index 50%
rename from src/renderer/screens/Preferences/Accounts.jsx
rename to src/renderer/screens/Preferences/Accounts/index.jsx
index 15eb4de..de556ec 100644
--- a/src/renderer/screens/Preferences/Accounts.jsx
+++ b/src/renderer/screens/Preferences/Accounts/index.jsx
@@ -1,70 +1,10 @@
import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import { toDataUrl } from 'ethereum-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 }) => (
-
- {accounts.map(account => {
- const identicon = account && toDataUrl(account)
-
- return (
- -
-
-
- {account}
-
-
-
-
- )
- })}
-
-)
-
-AccountsList.propTypes = {
- accounts: PropTypes.array.isRequired,
- handleDelete: PropTypes.func.isRequired
-}
-
-const AccountNew = ({ input, handleInputChange, handleSave, accentColor }) => (
-
- handleInputChange(e)}
- className="preference__input"
- />
-
-
-
-)
-
-AccountNew.propTypes = {
- input: PropTypes.string.isRequired,
- handleInputChange: PropTypes.func.isRequired,
- handleSave: PropTypes.func.isRequired,
- accentColor: PropTypes.string.isRequired
-}
+import { AppContext } from '../../../store/createContext'
+import Saved from './Saved'
+import New from './New'
+import styles from './index.module.css'
export default class Accounts extends PureComponent {
static contextType = AppContext
@@ -99,7 +39,9 @@ export default class Accounts extends PureComponent {
this.setState({ error: 'Address already added. Try another one.' })
return
} else if (!isAddress) {
- this.setState({ error: 'Not an Ethereum address. Try another one.' })
+ this.setState({
+ error: 'Not an Ethereum address. Try another one.'
+ })
return
} else {
const joined = [...accounts, input]
@@ -131,22 +73,22 @@ export default class Accounts extends PureComponent {
const { accounts, input, error } = this.state
return (
-
-
Accounts
-
+
+
Accounts
+
Add Ethereum account addresses holding Ocean Tokens.
-
-
+
- {error !== '' && {error}
}
+ {error !== '' && {error}
}
)
}
diff --git a/src/renderer/screens/Preferences/Accounts/index.module.css b/src/renderer/screens/Preferences/Accounts/index.module.css
new file mode 100644
index 0000000..eb1403e
--- /dev/null
+++ b/src/renderer/screens/Preferences/Accounts/index.module.css
@@ -0,0 +1,62 @@
+.preference {
+ composes: box from '../../../components/Box.module.css';
+ -webkit-app-region: none;
+ -webkit-user-select: text;
+}
+
+.title,
+.help {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+}
+
+.title {
+ font-size: 1.2rem;
+}
+
+.help {
+ color: #8b98a9;
+ margin-left: 0.5rem;
+}
+
+.error {
+ font-size: 0.9rem;
+}
+
+.list {
+ padding: 0;
+ border-top: 1px solid #e2e2e2;
+}
+
+:global(.dark) .list {
+ border-top-color: #303030;
+}
+
+.list li,
+.list li > div {
+ display: flex;
+ align-items: center;
+}
+
+.list li {
+ list-style: none;
+ justify-content: space-between;
+ border-bottom: 1px solid #e2e2e2;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+}
+
+:global(.dark) .list li {
+ border-bottom-color: #303030;
+}
+
+.button {
+ background: none;
+ border: 0;
+ box-shadow: none;
+ margin: 0;
+ padding: 0;
+ outline: 0;
+ font-size: 1rem;
+}
diff --git a/src/renderer/screens/Preferences/index.css b/src/renderer/screens/Preferences/index.css
deleted file mode 100644
index 2eade08..0000000
--- a/src/renderer/screens/Preferences/index.css
+++ /dev/null
@@ -1,114 +0,0 @@
-.preferences {
- text-align: left;
- width: 100%;
- position: relative;
- padding-bottom: 4rem;
-}
-
-.preferences__title {
- width: 100%;
- font-size: 2.2rem;
- margin-top: -1rem;
- margin-bottom: 2rem;
-}
-
-.preferences__close {
- text-decoration: none;
- font-size: 2rem;
- position: absolute;
- top: 0;
- right: 0;
- color: #8b98a9;
-}
-
-.preference__list {
- padding: 0;
- border-top: 1px solid #e2e2e2;
-}
-
-.dark .preference__list {
- border-top-color: #303030;
-}
-
-.preference__list li,
-.preference__list li > div {
- display: flex;
- align-items: center;
-}
-
-.preference__list li {
- list-style: none;
- justify-content: space-between;
- border-bottom: 1px solid #e2e2e2;
- padding-top: .25rem;
- padding-bottom: .25rem;
-}
-
-.dark .preference__list li {
- border-bottom-color: #303030;
-}
-
-.preferences button {
- background: none;
- border: 0;
- box-shadow: none;
- margin: 0;
- padding: 0;
- outline: 0;
- font-size: 1rem;
-}
-
-button.delete {
- position: relative;
- font-size: 2rem;
- top: -.2rem;
- color: #41474e;
- transition: color .5s ease-out;
-}
-
-.preference {
- -webkit-app-region: none;
- -webkit-user-select: text;
-}
-
-.preference__title,
-.preference__help {
- display: inline-block;
- margin-top: 0;
- margin-bottom: .5rem;
-}
-
-.preference__title {
- font-size: 1.2rem;
-}
-
-.preference__help {
- color: #8b98a9;
- margin-left: .5rem;
-}
-
-.preference .identicon {
- width: 1.5rem !important;
- height: 1.5rem !important;
- border-radius: 50%;
- margin-right: .75rem;
-}
-
-.preference__input {
- font-size: 1rem;
- outline: 0;
- background: none;
- border: 0;
- width: 80%;
- color: #303030;
- margin-top: .75rem;
- margin-bottom: .75rem;
-}
-
-.dark .preference__input {
- color: #fff;
-}
-
-.preference__error {
- font-size: .9rem;
-}
diff --git a/src/renderer/screens/Preferences/index.jsx b/src/renderer/screens/Preferences/index.jsx
index 14da3c6..86a389c 100644
--- a/src/renderer/screens/Preferences/index.jsx
+++ b/src/renderer/screens/Preferences/index.jsx
@@ -1,20 +1,16 @@
-import React, { PureComponent } from 'react'
+import React from 'react'
import { Link } from '@reach/router'
-
-import './index.css'
-
import Accounts from './Accounts'
+import styles from './index.module.css'
-export default class Preferences extends PureComponent {
- render() {
- return (
-
-
Preferences
{' '}
-
- ×
-
-
-
- )
- }
-}
+const Preferences = () => (
+
+
Preferences
{' '}
+
+ ×
+
+
+
+)
+
+export default Preferences
diff --git a/src/renderer/screens/Preferences/index.module.css b/src/renderer/screens/Preferences/index.module.css
new file mode 100644
index 0000000..c2aa751
--- /dev/null
+++ b/src/renderer/screens/Preferences/index.module.css
@@ -0,0 +1,21 @@
+.preferences {
+ text-align: left;
+ width: 100%;
+ position: relative;
+}
+
+.title {
+ width: 100%;
+ font-size: 2.2rem;
+ margin-top: -1rem;
+ margin-bottom: 2rem;
+}
+
+.close {
+ text-decoration: none;
+ font-size: 2rem;
+ position: absolute;
+ top: 0;
+ right: 0;
+ color: #8b98a9;
+}
diff --git a/webpack.common.config.js b/webpack.common.config.js
index 2137cb2..69bc6cc 100644
--- a/webpack.common.config.js
+++ b/webpack.common.config.js
@@ -24,11 +24,12 @@ module.exports = {
},
{
test: /\.css$/,
+ exclude: /\.module\.css$/,
use: ['style-loader', 'css-loader'],
include: defaultInclude
},
{
- test: /\.module\.(scss|sass)$/,
+ test: /\.module\.css$/,
include: defaultInclude,
loader: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
@@ -41,26 +42,6 @@ module.exports = {
localsConvention: 'camelCase',
sourceMap: isDevelopment
}
- },
- {
- loader: 'sass-loader',
- options: {
- sourceMap: isDevelopment
- }
- }
- ]
- },
- {
- test: /\.(scss|sass)$/,
- exclude: /\.module.(scss|sass)$/,
- loader: [
- isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
- 'css-loader',
- {
- loader: 'sass-loader',
- options: {
- sourceMap: isDevelopment
- }
}
]
},
@@ -77,7 +58,7 @@ module.exports = {
]
},
resolve: {
- extensions: ['*', '.js', '.jsx', '.scss']
+ extensions: ['*', '.js', '.jsx', '.css']
},
target: 'electron-renderer',
plugins: [