|
| 1 | +<script setup lang="ts"> |
| 2 | +import { useApp, useTheme } from '@/composables' |
| 3 | +import { i18n, ipc } from '@/electron' |
| 4 | +import Typed from 'typed.js' |
| 5 | +
|
| 6 | +const { isSponsored } = useApp() |
| 7 | +const { isDark } = useTheme() |
| 8 | +
|
| 9 | +const labelRef = ref<HTMLElement | null>(null) |
| 10 | +let typed: Typed | null = null |
| 11 | +
|
| 12 | +const TYPING_DELAY = 1000 * 15 |
| 13 | +const FIRST_PROMPT = i18n.t('messages:special.unsponsored').toUpperCase() |
| 14 | +
|
| 15 | +const SINCE_YEAR = 2019 |
| 16 | +const NOW_YEAR = new Date().getFullYear() |
| 17 | +
|
| 18 | +const prompts = [ |
| 19 | + 'Zero sponsors. Infinite snippets', |
| 20 | + 'Free. Forever. Fueled by you', |
| 21 | + 'No sponsors. No regrets', |
| 22 | + 'Open source. Open wallet? 👀', |
| 23 | + `${NOW_YEAR - SINCE_YEAR} years solo. Still going`, |
| 24 | + 'Ad-free since 2019', |
| 25 | + '404: Sponsor Not Found', |
| 26 | + 'One dev. Thousands of users. Math? 🤔', |
| 27 | + 'Your snippets. My rent', |
| 28 | + 'Love it? Fuel it', |
| 29 | + 'You use it. You fund it?', |
| 30 | + 'A coffee keeps v6 coming', |
| 31 | + 'Stars are nice. Coffee is better', |
| 32 | + 'Built with love. Funded by you?', |
| 33 | + 'No tracking. No ads. No catch', |
| 34 | + 'Indie. Forever', |
| 35 | + 'Side project, full heart', |
| 36 | + 'Made by humans, for humans', |
| 37 | + 'Vibes-driven development', |
| 38 | + '100% indie. 0% bullshit', |
| 39 | + 'Snippets > Sponsors', |
| 40 | + // дев прикол |
| 41 | + '$ donate --please', |
| 42 | + 'throw new Error("No sponsors yet")', |
| 43 | + 'sudo support-massCode', |
| 44 | + 'npm install coffee', |
| 45 | + 'git blame → one guy', |
| 46 | + 'sponsors.length === 0', |
| 47 | + '// TODO: find sponsor', |
| 48 | + 'kill -9 ads', |
| 49 | + 'if (you.likeIt) donate()', |
| 50 | + 'await getSponsor() // pending...', |
| 51 | + 'try { ship() } catch { coffee() }', |
| 52 | + 'SELECT * FROM sponsors → 0 rows', |
| 53 | + 'console.log("send help")', |
| 54 | + 'npm install --save-life', |
| 55 | + 'git push --love origin main', |
| 56 | + 'chmod +x developer', |
| 57 | + 'function fund() { return ❤️ }', |
| 58 | + 'rm -rf ads/', |
| 59 | + 'process.exit(0) // jk, still here', |
| 60 | + 'import coffee from "you"', |
| 61 | + 'Error: SponsorsNotFoundException', |
| 62 | + 'cargo run --keep-alive', |
| 63 | + 'docker run --restart=donations', |
| 64 | + // самоирония |
| 65 | + 'Stars don\'t pay rent', |
| 66 | + 'GitHub stars: many. Sponsors: zero', |
| 67 | + 'One-man army. Tired army', |
| 68 | + 'Built different. Funded different?', |
| 69 | + 'Ship it. Eat ramen. Repeat', |
| 70 | + 'Free for you. Costly for me', |
| 71 | +] |
| 72 | +
|
| 73 | +function shufflePrompts(input: string[]) { |
| 74 | + const shuffled = [...input] |
| 75 | +
|
| 76 | + for (let i = shuffled.length - 1; i > 0; i -= 1) { |
| 77 | + const j = Math.floor(Math.random() * (i + 1)) |
| 78 | + const current = shuffled[i] |
| 79 | + shuffled[i] = shuffled[j] |
| 80 | + shuffled[j] = current |
| 81 | + } |
| 82 | +
|
| 83 | + return shuffled |
| 84 | +} |
| 85 | +
|
| 86 | +function getPromptSequence() { |
| 87 | + return [FIRST_PROMPT, ...shufflePrompts(prompts)] |
| 88 | +} |
| 89 | +
|
| 90 | +function openDonatePage() { |
| 91 | + void ipc.invoke( |
| 92 | + 'system:open-external', |
| 93 | + 'https://masscode.io/donate/?ref=unsponsored-label', |
| 94 | + ) |
| 95 | +} |
| 96 | +
|
| 97 | +onMounted(() => { |
| 98 | + if (isSponsored || !labelRef.value) { |
| 99 | + return |
| 100 | + } |
| 101 | +
|
| 102 | + typed = new Typed(labelRef.value, { |
| 103 | + strings: getPromptSequence(), |
| 104 | + typeSpeed: 60, |
| 105 | + backSpeed: 20, |
| 106 | + backDelay: TYPING_DELAY, |
| 107 | + startDelay: 700, |
| 108 | + loop: true, |
| 109 | + smartBackspace: true, |
| 110 | + showCursor: false, |
| 111 | + }) |
| 112 | +}) |
| 113 | +
|
| 114 | +onBeforeUnmount(() => { |
| 115 | + typed?.destroy() |
| 116 | + typed = null |
| 117 | +}) |
| 118 | +</script> |
| 119 | + |
| 120 | +<template> |
| 121 | + <button |
| 122 | + v-if="!isSponsored" |
| 123 | + type="button" |
| 124 | + class="relative h-32 w-3 cursor-pointer border-0 bg-transparent p-0 focus-visible:outline-none" |
| 125 | + :class="isDark ? 'text-amber-300/70' : 'text-violet-500/70'" |
| 126 | + @click="openDonatePage" |
| 127 | + > |
| 128 | + <div |
| 129 | + class="absolute top-0 left-0 flex h-3 w-32 origin-top-left translate-y-32 -rotate-90 items-center" |
| 130 | + > |
| 131 | + <span |
| 132 | + ref="labelRef" |
| 133 | + class="_uppercase font-mono text-[10px] leading-none font-semibold tracking-[0.14em] whitespace-nowrap select-none" |
| 134 | + /> |
| 135 | + </div> |
| 136 | + </button> |
| 137 | +</template> |
0 commit comments