import * as Clipboard from 'expo-clipboard';
import * as Haptics from 'expo-haptics';
import React, { useState } from 'react';
import {
Linking,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import { DONATE_COINS, DonateCoin, isPlaceholder, qrPayload } from '../lib/donate';
import { theme } from '../theme';
export function DonateScreen() {
return (
Support Goon
Goon is free, open-source, and ad-free. It stays that way only because
donations cover the server, the API keys, and the time. If the app
earned you a smile, throw a coin into the bucket.
{DONATE_COINS.map((coin) => (
))}
Why crypto?
Mainstream payment processors (Stripe, PayPal, Patreon) refuse adult
projects — even open-source tooling like this one. Crypto is the only
channel that does not require us to identify our donors and does not
let third parties freeze the project mid-month.
Monero is privacy-preserving by design — if you care about not being
linked to this app on-chain, send XMR. Bitcoin and USDT are public
ledgers; use a fresh wallet if anonymity matters to you.
Linking.openURL('https://www.getmonero.org/get-started/')}>
New to Monero? Learn how →
Linking.openURL('https://bitcoin.org/en/getting-started')}>
New to Bitcoin? Learn how →
);
}
function CoinCard({ coin }: { coin: DonateCoin }) {
const [copied, setCopied] = useState(false);
const placeholder = isPlaceholder(coin.address);
async function copy() {
if (placeholder) return;
await Clipboard.setStringAsync(coin.address);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {});
setCopied(true);
setTimeout(() => setCopied(false), 1800);
}
return (
{coin.ticker}
{coin.name}
{coin.blurb}
{placeholder ? (
Address not configured yet — see{' '}
mobile/src/lib/donate.ts
) : (
<>
{/* white background mandated for QR scanability across cameras */}
[styles.addressBox, pressed && styles.addressBoxPressed]}>
{coin.address}
{copied ? '✓ Copied' : 'Tap to copy'}
>
)}
);
}
const styles = StyleSheet.create({
root: { flex: 1, backgroundColor: theme.bg },
scroll: { padding: 16, paddingBottom: 40 },
hero: {
marginBottom: 18,
paddingHorizontal: 4,
},
heroTitle: {
color: theme.fg,
fontSize: 28,
fontWeight: '800',
letterSpacing: -0.5,
marginBottom: 8,
},
heroSubtitle: {
color: theme.muted,
fontSize: 14,
lineHeight: 20,
},
card: {
backgroundColor: theme.card,
borderWidth: 1.5,
borderRadius: 16,
padding: 16,
marginBottom: 14,
},
cardHeader: {
flexDirection: 'row',
alignItems: 'flex-start',
gap: 12,
marginBottom: 14,
},
ticker: {
width: 56,
height: 56,
borderRadius: 14,
alignItems: 'center',
justifyContent: 'center',
},
tickerText: {
color: '#fff',
fontWeight: '900',
fontSize: 14,
letterSpacing: 0.5,
},
coinName: {
color: theme.fg,
fontSize: 18,
fontWeight: '700',
marginBottom: 2,
},
coinBlurb: {
color: theme.muted,
fontSize: 12,
lineHeight: 16,
},
qrWrap: {
alignItems: 'center',
marginBottom: 14,
},
qrInner: {
padding: 10,
backgroundColor: '#fff',
borderRadius: 12,
},
addressBox: {
backgroundColor: theme.bgElevated,
borderWidth: 1,
borderColor: theme.border,
borderRadius: 10,
padding: 12,
},
addressBoxPressed: {
backgroundColor: theme.card,
borderColor: theme.borderFocus,
},
addressText: {
color: theme.fg,
fontFamily: 'monospace',
fontSize: 12,
lineHeight: 17,
},
copyHint: {
color: theme.mutedDim,
fontSize: 11,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 0.8,
marginTop: 8,
textAlign: 'right',
},
placeholderBox: {
backgroundColor: theme.bgElevated,
borderWidth: 1,
borderColor: theme.warn,
borderStyle: 'dashed',
borderRadius: 10,
padding: 14,
},
placeholderText: {
color: theme.warn,
fontSize: 12,
lineHeight: 17,
},
footnote: {
backgroundColor: theme.bgElevated,
borderWidth: 1,
borderColor: theme.border,
borderRadius: 14,
padding: 16,
marginTop: 6,
},
footnoteTitle: {
color: theme.fg,
fontSize: 13,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 0.5,
marginBottom: 8,
},
footnoteBody: {
color: theme.muted,
fontSize: 13,
lineHeight: 19,
},
footer: {
marginTop: 18,
alignItems: 'center',
gap: 10,
},
footerLink: {
color: theme.accent,
fontSize: 13,
fontWeight: '600',
},
});