From 39ee6505d8b332eb9537507942c3f3ab223de018 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 9 Jun 2021 19:28:16 -0500 Subject: [PATCH] CryptoDonate: add CryptoDonateModal --- .../components/crypto_address.js | 13 +++- .../components/detailed_crypto_address.js | 72 +++++++++++++++++++ .../ui/components/crypto_donate_modal.js | 21 ++++++ .../features/ui/components/modal_root.js | 2 + app/styles/components/crypto-donate.scss | 16 ++++- 5 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 app/soapbox/features/crypto_donate/components/detailed_crypto_address.js create mode 100644 app/soapbox/features/ui/components/crypto_donate_modal.js diff --git a/app/soapbox/features/crypto_donate/components/crypto_address.js b/app/soapbox/features/crypto_donate/components/crypto_address.js index d3f6c3301..3d6966af8 100644 --- a/app/soapbox/features/crypto_donate/components/crypto_address.js +++ b/app/soapbox/features/crypto_donate/components/crypto_address.js @@ -1,4 +1,5 @@ import React from 'react'; +import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; @@ -6,6 +7,7 @@ import Icon from 'soapbox/components/icon'; import blockExplorers from '../utils/block_explorers.json'; import CoinDB from '../utils/coin_db'; import { getCoinIcon } from '../utils/coin_icons'; +import { openModal } from 'soapbox/actions/modal'; const getExplorerUrl = (ticker, address) => { const template = blockExplorers[ticker]; @@ -13,7 +15,8 @@ const getExplorerUrl = (ticker, address) => { return template.replace('{address}', address); }; -export default class CryptoAddress extends ImmutablePureComponent { +export default @connect() +class CryptoAddress extends ImmutablePureComponent { static propTypes = { address: PropTypes.string.isRequired, @@ -34,6 +37,11 @@ export default class CryptoAddress extends ImmutablePureComponent { document.execCommand('copy'); } + handleModalClick = e => { + this.props.dispatch(openModal('CRYPTO_DONATE', this.props)); + e.preventDefault(); + } + render() { const { address, ticker, note } = this.props; const title = CoinDB.getIn([ticker, 'name']); @@ -47,6 +55,9 @@ export default class CryptoAddress extends ImmutablePureComponent {
{title}
+ + + diff --git a/app/soapbox/features/crypto_donate/components/detailed_crypto_address.js b/app/soapbox/features/crypto_donate/components/detailed_crypto_address.js new file mode 100644 index 000000000..70a588890 --- /dev/null +++ b/app/soapbox/features/crypto_donate/components/detailed_crypto_address.js @@ -0,0 +1,72 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import Icon from 'soapbox/components/icon'; +import QRCode from 'qrcode.react'; +import blockExplorers from '../utils/block_explorers.json'; +import CoinDB from '../utils/coin_db'; +import { getCoinIcon } from '../utils/coin_icons'; + +const getExplorerUrl = (ticker, address) => { + const template = blockExplorers[ticker]; + if (!template) return false; + return template.replace('{address}', address); +}; + +export default @connect() +class DetailedCryptoAddress extends ImmutablePureComponent { + + static propTypes = { + address: PropTypes.string.isRequired, + ticker: PropTypes.string.isRequired, + note: PropTypes.string, + } + + setInputRef = c => { + this.input = c; + } + + handleCopyClick = e => { + if (!this.input) return; + + this.input.select(); + this.input.setSelectionRange(0, 99999); + + document.execCommand('copy'); + } + + render() { + const { address, ticker, note } = this.props; + const title = CoinDB.getIn([ticker, 'name']); + const explorerUrl = getExplorerUrl(ticker, address); + + return ( +
+
+
+ {title} +
+
{title}
+
+ + + +
+
+ {note &&
{note}
} +
+ +
+
+ + +
+
+ ); + } + +} diff --git a/app/soapbox/features/ui/components/crypto_donate_modal.js b/app/soapbox/features/ui/components/crypto_donate_modal.js new file mode 100644 index 000000000..90ae87842 --- /dev/null +++ b/app/soapbox/features/ui/components/crypto_donate_modal.js @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import DetailedCryptoAddress from 'soapbox/features/crypto_donate/components/detailed_crypto_address'; + +export default class CryptoDonateModal extends React.PureComponent { + + static propTypes = { + address: PropTypes.string.isRequired, + ticker: PropTypes.string.isRequired, + note: PropTypes.string, + }; + + render() { + return ( +
+ +
+ ); + } + +} diff --git a/app/soapbox/features/ui/components/modal_root.js b/app/soapbox/features/ui/components/modal_root.js index b6cfa5737..b3f7f8681 100644 --- a/app/soapbox/features/ui/components/modal_root.js +++ b/app/soapbox/features/ui/components/modal_root.js @@ -13,6 +13,7 @@ import FocalPointModal from './focal_point_modal'; import HotkeysModal from './hotkeys_modal'; import ComposeModal from './compose_modal'; import UnauthorizedModal from './unauthorized_modal'; +import CryptoDonateModal from './crypto_donate_modal'; import { MuteModal, @@ -37,6 +38,7 @@ const MODAL_COMPONENTS = { 'HOTKEYS': () => Promise.resolve({ default: HotkeysModal }), 'COMPOSE': () => Promise.resolve({ default: ComposeModal }), 'UNAUTHORIZED': () => Promise.resolve({ default: UnauthorizedModal }), + 'CRYPTO_DONATE': () => Promise.resolve({ default: CryptoDonateModal }), }; export default class ModalRoot extends React.PureComponent { diff --git a/app/styles/components/crypto-donate.scss b/app/styles/components/crypto-donate.scss index 95857df69..2c2d1f819 100644 --- a/app/styles/components/crypto-donate.scss +++ b/app/styles/components/crypto-donate.scss @@ -27,10 +27,10 @@ &__actions { margin-left: auto; - padding-left: 10px; a { color: var(--primary-text-color--faint); + margin-left: 10px; } } @@ -38,6 +38,14 @@ margin-bottom: 10px; } + &__qrcode { + margin-bottom: 12px; + padding: 10px; + display: flex; + align-items: center; + justify-content: center; + } + &__address { margin-top: auto; display: flex; @@ -64,3 +72,9 @@ display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); } + +.crypto-donate-modal { + background: var(--foreground-color); + border-radius: 8px; + padding-bottom: 13px; +}