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 {
+
+
+
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}
+
+
+ {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;
+}