Skip to content

Commit 443aa4b

Browse files
authored
feat: add in-app sponsorship prompts and reminders (#28)
* feat: add post-exit sponsorship message - Show sponsorship message when TUI exits normally - Display Buy Me a Coffee link - Add wiiiimm.codes site link - Invite users to leave feedback on GitHub - Only shows on normal exit, not for --help or --version * feat: add in-app sponsorship prompts and reminders - Add sponsor section to InfoModal (yellow border box) - Add sponsor line to help footer - Add periodic sponsor reminder after every 5 operations - Reminder auto-hides after 5 seconds - Shows buymeacoffee.com/wiiiimm link
1 parent b975e26 commit 443aa4b

3 files changed

Lines changed: 69 additions & 1 deletion

File tree

src/index.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,35 @@ const handleShutdown = (signal: string) => {
8282
process.exit(0);
8383
};
8484

85+
// Function to show sponsorship message
86+
const showSponsorshipMessage = () => {
87+
console.log('\n' + '─'.repeat(60));
88+
console.log('\n💚 Thank you for using gh-manager-cli!\n');
89+
console.log('If this app saved you time, please consider supporting');
90+
console.log('the development of more open-source projects like this:\n');
91+
console.log(' ☕ Buy Me a Coffee: https://buymeacoffee.com/wiiiimm');
92+
console.log(' 🚀 Visit my site: https://wiiiimm.codes');
93+
console.log(' 💬 Leave feedback: https://github.com/wiiiimm/gh-manager-cli');
94+
console.log('\nYour support and contributions make a difference! 🙏\n');
95+
console.log('─'.repeat(60) + '\n');
96+
};
97+
8598
// Register shutdown handlers
8699
process.on('SIGINT', () => handleShutdown('SIGINT')); // Ctrl+C
87100
process.on('SIGTERM', () => handleShutdown('SIGTERM')); // Kill signal
88101
process.on('exit', (code) => {
102+
// Only show sponsorship message on normal exit (code 0)
103+
// and not when there's an error or when using --version/--help
104+
const isNormalExit = code === 0;
105+
const isInteractiveSession = !argv.includes('--version') &&
106+
!argv.includes('-v') &&
107+
!argv.includes('--help') &&
108+
!argv.includes('-h');
109+
110+
if (isNormalExit && isInteractiveSession) {
111+
showSponsorshipMessage();
112+
}
113+
89114
logger.info('gh-manager-cli exited', {
90115
exitCode: code,
91116
uptime: process.uptime()

src/ui/components/modals/InfoModal.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export default function InfoModal({ repo, terminalWidth, onClose }: InfoModalPro
5151
<Text color="gray">Updated: {formatDate(repo.updatedAt)} • Pushed: {formatDate(repo.pushedAt)}</Text>
5252
<Text color="gray">Size: {repo.diskUsage} KB</Text>
5353
<Box height={1}><Text> </Text></Box>
54+
<Box flexDirection="column" borderStyle="single" borderColor="yellow" paddingX={1} marginY={1}>
55+
<Text color="yellow">💚 Enjoying gh-manager-cli?</Text>
56+
<Text color="gray">Support the project at:</Text>
57+
<Text color="cyan">buymeacoffee.com/wiiiimm</Text>
58+
</Box>
5459
<Text color="gray">Press Esc or I to close</Text>
5560
</Box>
5661
);

src/ui/views/RepoList.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
9393
const [ownerAffiliations, setOwnerAffiliations] = useState<OwnerAffiliation[]>(['OWNER']);
9494
const [orgSwitcherOpen, setOrgSwitcherOpen] = useState(false);
9595

96+
// Sponsor reminder state
97+
const [operationCount, setOperationCount] = useState(0);
98+
const [showSponsorReminder, setShowSponsorReminder] = useState(false);
99+
96100
// Search state (server-side)
97101
const [searchItems, setSearchItems] = useState<RepoNode[]>([]);
98102
const [searchEndCursor, setSearchEndCursor] = useState<string | null>(null);
@@ -189,6 +193,19 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
189193
})();
190194
}, [initialOrgSlug, token, prefsLoaded, client, addDebugMessage]);
191195

196+
// Helper to track successful operations and show sponsor reminder
197+
function trackSuccessfulOperation() {
198+
const newCount = operationCount + 1;
199+
setOperationCount(newCount);
200+
201+
// Show sponsor reminder every 5 operations
202+
if (newCount % 5 === 0) {
203+
setShowSponsorReminder(true);
204+
// Hide the reminder after 5 seconds
205+
setTimeout(() => setShowSponsorReminder(false), 5000);
206+
}
207+
}
208+
192209
function closeArchiveModal() {
193210
setArchiveMode(false);
194211
setArchiveTarget(null);
@@ -301,6 +318,7 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
301318
setItems(prev => prev.map(updateRepo));
302319
setSearchItems(prev => prev.map(updateRepo));
303320

321+
trackSuccessfulOperation(); // Track the successful operation
304322
closeArchiveModal();
305323
} catch (e) {
306324
setArchiving(false);
@@ -511,6 +529,7 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
511529
setSearchTotalCount((c) => Math.max(0, c - 1));
512530
}
513531

532+
trackSuccessfulOperation(); // Track the successful operation
514533
setDeleteMode(false);
515534
setDeleteTarget(null);
516535
setTypedCode('');
@@ -1621,6 +1640,19 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
16211640
{/* Header bar */}
16221641
{headerBar}
16231642

1643+
{/* Sponsor reminder notification */}
1644+
{showSponsorReminder && (
1645+
<Box marginX={1} marginBottom={1}>
1646+
<Box borderStyle="single" borderColor="yellow" paddingX={2} paddingY={1}>
1647+
<Box flexDirection="column" alignItems="center">
1648+
<Text color="yellow">💚 Thanks for using gh-manager-cli!</Text>
1649+
<Text color="gray">Your support helps craft more open-source tools</Text>
1650+
<Text color="cyan">☕ buymeacoffee.com/wiiiimm</Text>
1651+
</Box>
1652+
</Box>
1653+
</Box>
1654+
)}
1655+
16241656
{/* Main content container with border - fixed height */}
16251657
<Box borderStyle="single" borderColor={modalOpen ? 'gray' : 'yellow'} paddingX={1} paddingY={1} marginX={1} height={contentHeight + containerPadding + 2} flexDirection="column">
16261658
{deleteMode && deleteTarget ? (
@@ -2167,7 +2199,7 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
21672199
)}
21682200
</Box>
21692201

2170-
{/* Help footer - 4 lines */}
2202+
{/* Help footer - 5 lines */}
21712203
<Box marginTop={1} paddingX={1} flexDirection="column">
21722204
{/* Line 1: Basic navigation */}
21732205
<Box width={terminalWidth} justifyContent="center">
@@ -2193,6 +2225,12 @@ export default function RepoList({ token, maxVisibleRows, onLogout, viewerLogin,
21932225
K Cache Info • W Org Switch • Del/Backspace Delete • Ctrl+L Logout • Q Quit
21942226
</Text>
21952227
</Box>
2228+
{/* Line 5: Sponsorship */}
2229+
<Box width={terminalWidth} justifyContent="center" marginTop={1}>
2230+
<Text color="yellow" dimColor={modalOpen ? true : undefined}>
2231+
💚 Support the project: buymeacoffee.com/wiiiimm
2232+
</Text>
2233+
</Box>
21962234
</Box>
21972235

21982236
{/* Debug panel */}

0 commit comments

Comments
 (0)