diff --git a/components/donation-nag-modal.tsx b/components/donation-nag-modal.tsx index a804f8df..f1036dd5 100644 --- a/components/donation-nag-modal.tsx +++ b/components/donation-nag-modal.tsx @@ -1,17 +1,95 @@ import { + Animated, Linking, Modal, Platform, View, } from 'react-native'; import { - useState, useEffect, + useRef, + useState, } from 'react'; import { DefaultText } from './default-text'; import { ButtonWithCenteredText } from './button/centered-text'; import { signedInUser } from '../App'; import { api } from '../api/api'; +import { getRandomElement } from '../util/util'; + +const gagLocations = [ + '/a/', + '/adv/', + '/r9k/', + '/v/', + '@tinder on Twitter', + 'Bronies Anonymous', + 'Pornhub gooners', + 'Quora', + 'Re**it', + 'a 3-viewer Twitch chat', + 'a mongolian basket weaving forum', + 'a telemarketer', + 'a televangelist hotline', + 'annual cheese rolling event-goers', + 'boomers on Facebook', + 'cabal of BPD-having besties 😊', + 'chat', + 'goth girls at the local cemetery', + 'jehovah’s witnesses', + 'my Ao3 readers', + 'my Discord server', + 'my Fortnite squad', + 'my Hinge matches', + 'my Letterboxd review readers', + 'my LinkedIn connections', + 'my Rabbi', + 'my TikTok followers', + 'my Tinder date', + 'my Twitch followers', + 'my Twitter oomfies', + 'my YouTube subscribers', + 'my autism support group', + 'my body pillow', + 'my church', + 'my colleagues', + 'my cosplay convention', + 'my doctor', + 'my drunk uncle at Thanksgiving', + 'my femboy oomfies', + 'my flat earth society gathering', + 'my furry convention', + 'my grandmother’s ghost', + 'my imaginary friend', + 'my local renaissance faire', + 'my mom', + 'my parole officer', + 'my priest', + 'my silent meditation retreat', + 'my sleep paralysis demon', + 'my tax agent', + 'my therapist', + 'my weeb friends', + 'my wife’s boyfriend', + 'r/TwoXChromosomes', + 'r/UnexpectedJoJo', + 'r/bumble', + 'r/greentext', + 'r/wallstreetbets', + 'some gooners', + 'the NSA agent monitoring me', + 'the Neopets Revival Discord', + 'the Wendy’s drive-thru', + 'the antique typewriter convention', + 'the comic-con', + 'the fediverse', + 'the guy using the urinal next to mine', + 'the guy who hands out samples at Costco', + 'the guy who sells me vape juice', + 'the hand cuz the face ain’t listening', + 'the homeless gentleman outside my apartment', + 'the voices in my head', + 'you want I want, what I really really want', +]; const DonationNagModal = () => { const name = signedInUser?.name; @@ -31,7 +109,18 @@ const DonationNagModal = () => { } }; -const DonationNagModalWeb = ({ +const DonationNagModalWeb = (props: { + name: string + estimatedEndDate: Date +}) => { + if (Math.random() > 0.5) { + return + } else { + return + } +}; + +const MonetaryDonationNagModalWeb = ({ name, estimatedEndDate, }: { @@ -160,6 +249,184 @@ const DonationNagModalWeb = ({ ); }; +const MarketingDonationNagModalWeb = ({ + name, + estimatedEndDate, +}: { + name: string + estimatedEndDate: Date +}) => { + const [gagLocation, setGagLocation] = useState(getRandomElement(gagLocations)); + const [isVisible, setIsVisible] = useState(true); + const opacity = useRef(new Animated.Value(1)).current; + + useEffect(() => { + // Function to pick a random location with cross-fade animation + const pickRandomLocation = () => { + // Fade out the current text + Animated.timing(opacity, { + toValue: 0, + duration: 300, // Duration of fade-out + useNativeDriver: true, + }).start(() => { + // After fade-out completes, update the location + const randomIndex = Math.floor(Math.random() * gagLocations.length); + setGagLocation(gagLocations[randomIndex]); + + // Fade in the new text + Animated.timing(opacity, { + toValue: 1, + duration: 300, // Duration of fade-in + useNativeDriver: true, + }).start(); + }); + }; + + const intervalId = setInterval(pickRandomLocation, 3000); + + // Cleanup interval on component unmount + return () => clearInterval(intervalId); + }, [opacity]); + + const onPressButton = () => { + setIsVisible(false); + api('post', '/dismiss-donation'); + }; + + return ( + + + + + + Attention all terminally online degenerates! + + + + + Want Duolicious to stay free? You’re gonna need to do some shilling... + + + + + + + Shilling is what brought us all here. But Duolicious’ choice to + be 100% free and volunteer-run means we can’t afford paid shills + like big apps can. That means {} + + edgy shitposters like you + + {} need to shill Duolicious to keep the new members coming. {} + + Please mention us wherever you lurk. + + + + + + + + Ok, I’ll tell {gagLocation} + + + } + /> + + + Just plaster this shithole with ads already + + + + + + ); +}; + const DonationNagModalMobile = ({ name, estimatedEndDate, diff --git a/util/util.tsx b/util/util.tsx index 38cbd04f..c96134a8 100644 --- a/util/util.tsx +++ b/util/util.tsx @@ -127,6 +127,11 @@ const secToMinSec = (sec: number): [string, string] => { return [minutes, seconds]; }; +const getRandomElement = (list: T[]): T | undefined => + list.length === 0 ? + undefined : + list[Math.floor(Math.random() * list.length)]; + export { compareArrays, delay, @@ -139,4 +144,5 @@ export { possessive, secToMinSec, withTimeout, + getRandomElement, };