diff --git a/app/soapbox/features/crypto_donate/components/crypto_address.js b/app/soapbox/features/crypto_donate/components/crypto_address.js new file mode 100644 index 000000000..512ba686c --- /dev/null +++ b/app/soapbox/features/crypto_donate/components/crypto_address.js @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import QRCode from 'qrcode.react'; +import CoinDB from '../utils/coin_db'; +import { getCoinIcon } from '../utils/coin_icons'; + +export default class CryptoAddress extends ImmutablePureComponent { + + static propTypes = { + address: PropTypes.string.isRequired, + ticker: PropTypes.string.isRequired, + note: PropTypes.string, + } + + render() { + const { address, ticker, note } = this.props; + const title = CoinDB.getIn([ticker, 'name']); + + return ( +
+
+ {title} +
+
+ +
+
{title}
+
{address}
+ {note &&
{note}
} +
+ ); + } + +} diff --git a/app/soapbox/features/crypto_donate/components/site_wallet.js b/app/soapbox/features/crypto_donate/components/site_wallet.js new file mode 100644 index 000000000..3e5d30bc5 --- /dev/null +++ b/app/soapbox/features/crypto_donate/components/site_wallet.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import CryptoAddress from './crypto_address'; + +const mapStateToProps = state => { + // Address example: + // {"ticker": "btc", "address": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n", "note": "This is our main address"} + return { + coinList: state.getIn(['soapbox', 'crypto_addresses']), + }; +}; + +export default @connect(mapStateToProps) +class CoinList extends ImmutablePureComponent { + + static propTypes = { + coinList: ImmutablePropTypes.list, + } + + render() { + const { coinList } = this.props; + if (!coinList) return null; + + return ( +
+ {coinList.map(coin => ( + + ))} +
+ ); + } + +} diff --git a/app/soapbox/features/cryptocoin/index.js b/app/soapbox/features/crypto_donate/index.js similarity index 69% rename from app/soapbox/features/cryptocoin/index.js rename to app/soapbox/features/crypto_donate/index.js index b509bbb2c..a06652ffe 100644 --- a/app/soapbox/features/cryptocoin/index.js +++ b/app/soapbox/features/crypto_donate/index.js @@ -3,15 +3,15 @@ import { defineMessages, injectIntl } from 'react-intl'; import PropTypes from 'prop-types'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Column from '../ui/components/column'; -import CoinList from './coin_list'; +import SiteWallet from './components/site_wallet'; const messages = defineMessages({ - heading: { id: 'column.cryptocoin', defaultMessage: 'Donate Cryptocurrency' }, + heading: { id: 'column.crypto_donate', defaultMessage: 'Donate Cryptocurrency' }, }); export default @injectIntl -class Cryptocoin extends ImmutablePureComponent { +class CryptoDonate extends ImmutablePureComponent { static propTypes = { intl: PropTypes.object.isRequired, @@ -22,8 +22,8 @@ class Cryptocoin extends ImmutablePureComponent { return ( -
- +
+
); diff --git a/app/soapbox/features/crypto_donate/utils/coin_db.js b/app/soapbox/features/crypto_donate/utils/coin_db.js new file mode 100644 index 000000000..33c566cdb --- /dev/null +++ b/app/soapbox/features/crypto_donate/utils/coin_db.js @@ -0,0 +1,6 @@ +import { fromJS } from 'immutable'; +import manifestMap from './manifest_map'; + +// All this does is converts the result from manifest_map.js into an ImmutableMap +const coinDB = fromJS(manifestMap); +export default coinDB; diff --git a/app/soapbox/features/crypto_donate/utils/coin_icons.js b/app/soapbox/features/crypto_donate/utils/coin_icons.js new file mode 100644 index 000000000..2c0376bfa --- /dev/null +++ b/app/soapbox/features/crypto_donate/utils/coin_icons.js @@ -0,0 +1,20 @@ +// Does some trickery to import all the icons into the project +// See: https://stackoverflow.com/questions/42118296/dynamically-import-images-from-a-directory-using-webpack + +const icons = {}; + +function importAll(r) { + const pathRegex = /\.\/(.*)\.svg/i; + + r.keys().forEach((key) => { + const ticker = pathRegex.exec(key)[1]; + return icons[ticker] = r(key).default; + }); +} + +importAll(require.context('cryptocurrency-icons/svg/color/', true, /\.svg$/)); + +export default icons; + +// For getting the icon +export const getCoinIcon = ticker => icons[ticker] || icons.generic || null; diff --git a/app/soapbox/features/crypto_donate/utils/manifest_map.js b/app/soapbox/features/crypto_donate/utils/manifest_map.js new file mode 100644 index 000000000..bab27695f --- /dev/null +++ b/app/soapbox/features/crypto_donate/utils/manifest_map.js @@ -0,0 +1,12 @@ +// @preval +// Converts cryptocurrency-icon's manifest file from a list to a map. +// See: https://github.com/spothq/cryptocurrency-icons/blob/master/manifest.json + +const manifest = require('cryptocurrency-icons/manifest.json'); +const { Map: ImmutableMap, fromJS } = require('immutable'); + +const manifestMap = fromJS(manifest).reduce((acc, entry) => { + return acc.set(entry.get('symbol').toLowerCase(), entry); +}, ImmutableMap()); + +module.exports = manifestMap.toJS(); diff --git a/app/soapbox/features/cryptocoin/coin.js b/app/soapbox/features/cryptocoin/coin.js deleted file mode 100644 index 2474aaebf..000000000 --- a/app/soapbox/features/cryptocoin/coin.js +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import QRCode from 'qrcode.react'; -import { getCoinIcon } from './icons'; - -export default class Coin extends ImmutablePureComponent { - - static propTypes = { - coin: ImmutablePropTypes.map.isRequired, - } - - render() { - const { coin } = this.props; - - return ( -
-
- {coin.get('title')} -
-
- -
-
{coin.get('title')}
-
{coin.get('address')}
-
- ); - } - -} diff --git a/app/soapbox/features/cryptocoin/coin_db.json b/app/soapbox/features/cryptocoin/coin_db.json deleted file mode 100644 index 4b2889ce4..000000000 --- a/app/soapbox/features/cryptocoin/coin_db.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "supportedCoins": [ - "btc", - "eth", - "ltc", - "doge", - "ubq", - "xmr" - ], - "coinData": { - "btc": { "title": "Bitcoin" }, - "eth": { "title": "Ethereum" }, - "ltc": { "title": "Litecoin" }, - "doge": { "title": "Dogecoin" }, - "xmr": { "title": "Monero" } - } -} diff --git a/app/soapbox/features/cryptocoin/coin_list.js b/app/soapbox/features/cryptocoin/coin_list.js deleted file mode 100644 index f7912b183..000000000 --- a/app/soapbox/features/cryptocoin/coin_list.js +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { List as ImmutableList, fromJS } from 'immutable'; -import coinDB from './coin_db.json'; -import Coin from './coin'; - -const supportedCoins = ImmutableList(coinDB.supportedCoins); -const coinData = fromJS(coinDB.coinData); - -const makeCoinList = crypto => { - return supportedCoins.reduce((acc, ticker) => { - const address = crypto.get(ticker); - const data = coinData.get(ticker); - if (!address || !data) return acc; - - const coin = data.merge({ ticker, address }); - - return acc.push(coin); - }, ImmutableList()); -}; - -const mapStateToProps = state => { - const crypto = state.getIn(['soapbox', 'cryptocoin']); - - return { - coinList: makeCoinList(crypto), - }; -}; - -export default @connect(mapStateToProps) -class CoinList extends ImmutablePureComponent { - - static propTypes = { - coinList: ImmutablePropTypes.list, - } - - render() { - const { coinList } = this.props; - if (!coinList) return null; - - return ( -
- {coinList.map(coin => ( - - ))} -
- ); - } - -} diff --git a/app/soapbox/features/cryptocoin/icons.js b/app/soapbox/features/cryptocoin/icons.js deleted file mode 100644 index f3b6b878c..000000000 --- a/app/soapbox/features/cryptocoin/icons.js +++ /dev/null @@ -1,19 +0,0 @@ -const icons = {}; - -function importAll(r) { - const pathRegex = /\.\/(.*)\.svg/i; - - r.keys().forEach((key) => { - const ticker = pathRegex.exec(key)[1]; - return icons[ticker] = r(key).default; - }); -} - -importAll(require.context('cryptocurrency-icons/svg/color/', true, /\.svg$/)); - -const getCoinIcon = ticker => icons[ticker] || icons.generic || null; - -module.exports = { - default: icons, - getCoinIcon, -}; diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index d193ae606..9595bf2a5 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -92,7 +92,7 @@ import { AwaitingApproval, Reports, ModerationLog, - Cryptocoin, + CryptoDonate, } from './util/async-components'; // Dummy import, to make sure that ends up in the application bundle. @@ -290,7 +290,7 @@ class SwitchingColumnsArea extends React.PureComponent { - + diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 9e94c3e85..dc06d1677 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -230,6 +230,6 @@ export function ModerationLog() { return import(/* webpackChunkName: "features/admin/moderation_log" */'../../admin/moderation_log'); } -export function Cryptocoin() { - return import(/* webpackChunkName: "features/cryptocoin" */'../../cryptocoin'); +export function CryptoDonate() { + return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } diff --git a/app/styles/application.scss b/app/styles/application.scss index 068c6a528..457a4faf4 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -81,7 +81,7 @@ @import 'components/server-info'; @import 'components/admin'; @import 'components/backups'; -@import 'components/cryptocoin'; +@import 'components/crypto-donate'; // Holiday @import 'holiday/halloween'; diff --git a/app/styles/components/cryptocoin.scss b/app/styles/components/crypto-donate.scss similarity index 51% rename from app/styles/components/cryptocoin.scss rename to app/styles/components/crypto-donate.scss index 4deaf3341..255acfeaa 100644 --- a/app/styles/components/cryptocoin.scss +++ b/app/styles/components/crypto-donate.scss @@ -1,3 +1,3 @@ -.coin { +.crypto-address { padding: 20px; }