From 11ecea22d422138b8346dccded7dcdd70191fae4 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 10 Sep 2024 18:45:08 -0500 Subject: Add badges, clean up spacing --- src/components/dialogs/nudges/TenMillion/index.tsx | 509 +++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 src/components/dialogs/nudges/TenMillion/index.tsx (limited to 'src/components/dialogs/nudges/TenMillion/index.tsx') diff --git a/src/components/dialogs/nudges/TenMillion/index.tsx b/src/components/dialogs/nudges/TenMillion/index.tsx new file mode 100644 index 000000000..fdac91f4f --- /dev/null +++ b/src/components/dialogs/nudges/TenMillion/index.tsx @@ -0,0 +1,509 @@ +import React from 'react' +import {View} from 'react-native' +import ViewShot from 'react-native-view-shot' +import {Image} from 'expo-image' +import {moderateProfile} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {getCanvas} from '#/lib/canvas' +import {shareUrl} from '#/lib/sharing' +import {sanitizeDisplayName} from '#/lib/strings/display-names' +import {sanitizeHandle} from '#/lib/strings/handles' +import {isNative} from '#/platform/detection' +import {useModerationOpts} from '#/state/preferences/moderation-opts' +import {useProfileQuery} from '#/state/queries/profile' +import {useSession} from '#/state/session' +import {useComposerControls} from 'state/shell' +import {formatCount} from '#/view/com/util/numeric/format' +// import {UserAvatar} from '#/view/com/util/UserAvatar' +import {Logomark} from '#/view/icons/Logomark' +import { + atoms as a, + ThemeProvider, + tokens, + useBreakpoints, + useTheme, +} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {useContext} from '#/components/dialogs/nudges' +import {OnePercent} from '#/components/dialogs/nudges/TenMillion/icons/OnePercent' +import {PointOnePercent} from '#/components/dialogs/nudges/TenMillion/icons/PointOnePercent' +import {TenPercent} from '#/components/dialogs/nudges/TenMillion/icons/TenPercent' +import {Divider} from '#/components/Divider' +import {GradientFill} from '#/components/GradientFill' +import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox' +import {Download_Stroke2_Corner0_Rounded as Download} from '#/components/icons/Download' +import {Image_Stroke2_Corner0_Rounded as ImageIcon} from '#/components/icons/Image' +import {Loader} from '#/components/Loader' +import {Text} from '#/components/Typography' +// import {TwentyFivePercent} from '#/components/dialogs/nudges/TenMillion/icons/TwentyFivePercent' + +const DEBUG = false +const RATIO = 8 / 10 +const WIDTH = 2000 +const HEIGHT = WIDTH * RATIO + +function getFontSize(count: number) { + const length = count.toString().length + if (length < 7) { + return 80 + } else if (length < 5) { + return 100 + } else { + return 70 + } +} + +function getPercentBadge(percent: number) { + if (percent <= 0.001) { + return PointOnePercent + } else if (percent <= 0.01) { + return OnePercent + } else if (percent <= 0.1) { + return TenPercent + } + // else if (percent <= 0.25) { + // return TwentyFivePercent + // } + return null +} + +function Frame({children}: {children: React.ReactNode}) { + return ( + + {children} + + ) +} + +export function TenMillion() { + const t = useTheme() + const lightTheme = useTheme('light') + const {_, i18n} = useLingui() + const {controls} = useContext() + const {gtMobile} = useBreakpoints() + const {openComposer} = useComposerControls() + const {currentAccount} = useSession() + const {isLoading: isProfileLoading, data: profile} = useProfileQuery({ + did: currentAccount!.did, + }) // TODO PWI + const moderationOpts = useModerationOpts() + const moderation = React.useMemo(() => { + return profile && moderationOpts + ? moderateProfile(profile, moderationOpts) + : undefined + }, [profile, moderationOpts]) + const [uri, setUri] = React.useState(null) + + const isLoadingData = isProfileLoading || !moderation || !profile + const isLoadingImage = !uri + + const userNumber = 56_738 // TODO + const percent = userNumber / 10_000_000 + const Badge = getPercentBadge(percent) + + const sharePost = () => { + if (uri) { + controls.tenMillion.close(() => { + setTimeout(() => { + openComposer({ + text: '10 milly, babyyy', + imageUris: [ + { + uri, + width: WIDTH, + height: HEIGHT, + }, + ], + }) + }, 1e3) + }) + } + } + + const onNativeShare = () => { + if (uri) { + controls.tenMillion.close(() => { + shareUrl(uri) + }) + } + } + + const download = async () => { + if (uri) { + const canvas = await getCanvas(uri) + const imgHref = canvas + .toDataURL('image/png') + .replace('image/png', 'image/octet-stream') + const link = document.createElement('a') + link.setAttribute('download', `Bluesky 10M Users.png`) + link.setAttribute('href', imgHref) + link.click() + } + } + + const imageRef = React.useRef(null) + // const captureInProgress = React.useRef(false) + // const [cavasRelayout, setCanvasRelayout] = React.useState('key') + // const onCanvasReady = async () => { + // if ( + // imageRef.current && + // imageRef.current.capture && + // !captureInProgress.current + // ) { + // captureInProgress.current = true + // setCanvasRelayout('updated') + // } + // } + const onCanvasLayout = async () => { + if ( + imageRef.current && + imageRef.current.capture // && + // cavasRelayout === 'updated' + ) { + const uri = await imageRef.current.capture() + setUri(uri) + } + } + + const canvas = isLoadingData ? null : ( + + + + + + + + + + + + + + {/* Centered content */} + + + + Celebrating {formatCount(i18n, 10000000)} users + {' '} + 🎉 + + + + # + + + {i18n.number(userNumber)} + + + + {Badge && ( + + + + )} + + {/* End centered content */} + + + + {/* + + */} + + + {sanitizeDisplayName( + profile.displayName || + sanitizeHandle(profile.handle), + moderation.ui('displayName'), + )} + + + + {sanitizeHandle(profile.handle, '@')} + + + {profile.createdAt && ( + + + Joined{' '} + {i18n.date(profile.createdAt, { + dateStyle: 'long', + })} + + + )} + + + + + + + + + + + + ) + + return ( + + + + + + + {isLoadingData || isLoadingImage ? ( + + ) : ( + + )} + + + + {canvas} + + + + You're part of the next wave of the internet. + + + + + Online culture is too important to be controlled by a few + corporations. + {' '} + + + We’re dedicated to building an open foundation for the social + internet so that we can all shape its future. + + + + + + Congratulations. We're glad you're here. + + + + + + + Brag a little ;) + + + + + + + + + + + + ) +} -- cgit 1.4.1