Skip to content

Commit d5d86b2

Browse files
committed
Display the latest "Buy Me A Coffee" donation within the intro view
1 parent d30e4c2 commit d5d86b2

6 files changed

Lines changed: 141 additions & 14 deletions

File tree

packages/ui/src/components/editor/BuyMeACoffee/BuyMeACoffee.module.scss

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
.donations {
2+
display: flex;
3+
flex-direction: column;
4+
gap: var(--padding-8px);
5+
6+
&__donation {
7+
display: flex;
8+
flex-direction: column;
9+
gap: var(--padding-4px);
10+
user-select: text;
11+
position: relative;
12+
13+
&::before {
14+
content: '';
15+
position: absolute;
16+
width: 2px;
17+
height: 100%;
18+
background-color: #ffdd00;
19+
left: 0;
20+
transform: translateX(-12px);
21+
border-top-right-radius: 1px;
22+
border-bottom-right-radius: 1px;
23+
}
24+
25+
&__header {
26+
font-size: var(--font-size-12px);
27+
overflow: hidden;
28+
text-overflow: ellipsis;
29+
white-space: nowrap;
30+
}
31+
32+
&__note {
33+
background-color: var(--vscode-list-hoverBackground);
34+
padding: var(--padding-8px);
35+
border-radius: var(--border-radius-8px);
36+
}
37+
}
38+
}
39+
140
.button {
241
display: flex;
342
align-items: center;
@@ -11,7 +50,6 @@
1150

1251
&:hover {
1352
color: black;
14-
background-color: #ffe331;
1553
}
1654

1755
> svg {

packages/ui/src/components/editor/BuyMeACoffee/BuyMeACoffee.stories.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/ui/src/components/editor/BuyMeACoffee/BuyMeACoffee.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,54 @@ import React from 'react'
22
import styles from './BuyMeACoffee.module.scss'
33
import { Icon } from '../Icon'
44

5-
type Props = {
5+
export type BuyMeACoffeeProps = {
66
username: string
7+
supporter_name?: string
8+
support_coffees?: number
9+
support_note?: string
710
}
811

9-
export const BuyMeACoffee: React.FC<Props> = (props) => {
12+
export const BuyMeACoffee: React.FC<BuyMeACoffeeProps> = (props) => {
13+
if (props.supporter_name && props.support_coffees) {
14+
return (
15+
<div className={styles.donations}>
16+
<a
17+
href={`https://buymeacoffee.com/${props.username}`}
18+
className={styles.button}
19+
title="Buy me a coffee"
20+
>
21+
<Icon variant="BUY_ME_A_COFFEE_WITH_TEXT" />
22+
<span className="codicon codicon-link-external" />
23+
</a>
24+
<div className={styles.donations__donation}>
25+
<div
26+
className={styles.donations__donation__header}
27+
title={`${props.supporter_name} bought ${
28+
props.support_coffees
29+
} coffee${props.support_coffees > 1 ? 's' : ''}`}
30+
>
31+
<strong>{props.supporter_name}</strong> bought{' '}
32+
{props.support_coffees} coffee
33+
{props.support_coffees > 1 && 's'}
34+
</div>
35+
{props.support_note && (
36+
<div className={styles.donations__donation__note}>
37+
"{props.support_note}"
38+
</div>
39+
)}
40+
</div>
41+
</div>
42+
)
43+
}
44+
1045
return (
1146
<a
1247
href={`https://buymeacoffee.com/${props.username}`}
1348
className={styles.button}
1449
title="Buy me a coffee"
1550
>
1651
<Icon variant="BUY_ME_A_COFFEE_WITH_TEXT" />
17-
<span className="codicon codicon-link-external"/>
52+
<span className="codicon codicon-link-external" />
1853
</a>
1954
)
2055
}

packages/vscode/src/view/frontend/View.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { ApiMode, WebMode } from '@shared/types/modes'
1313
import { post_message } from './utils/post_message'
1414
import { FileInReview } from '@shared/types/file-in-review'
1515
import { CodeReview as UiCodeReview } from '@ui/components/editor/CodeReview'
16+
import { use_latest_donation } from './hooks/lastest-donation-hook'
1617

1718
const vscode = acquireVsCodeApi()
1819

@@ -48,6 +49,8 @@ export const View = () => {
4849
const [chat_input_focus_and_select_key, set_chat_input_focus_and_select_key] =
4950
useState(0)
5051

52+
const latest_donation = use_latest_donation(active_view == 'intro')
53+
5154
const handle_mouse_enter = () => {
5255
post_message(vscode, {
5356
command: 'CHECK_CLIPBOARD_FOR_APPLY'
@@ -368,6 +371,7 @@ export const View = () => {
368371
set_chat_input_focus_and_select_key((k) => k + 1)
369372
}}
370373
version={version}
374+
latest_donation={latest_donation}
371375
/>
372376
</div>
373377
</div>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useEffect, useRef, useState } from 'react'
2+
import axios from 'axios'
3+
4+
type Donation = {
5+
supporter_name: string
6+
support_coffees: number
7+
support_note: string
8+
}
9+
10+
export const use_latest_donation = (is_active: boolean) => {
11+
const [donation, set_donation] = useState<Donation | null>(null)
12+
const last_fetched_at = useRef<number | null>(null)
13+
14+
useEffect(() => {
15+
if (!is_active) {
16+
return
17+
}
18+
19+
const fetch_donation = async () => {
20+
if (
21+
last_fetched_at.current &&
22+
Date.now() - last_fetched_at.current < 5000
23+
) {
24+
return
25+
}
26+
try {
27+
const response = await axios.get(
28+
'https://app.buymeacoffee.com/api/creators/slug/robertpiosik/coffees?web=1&page=1&per_page=10'
29+
)
30+
last_fetched_at.current = Date.now()
31+
if (response.data?.data && response.data.data.length > 0) {
32+
const raw = response.data.data[0]
33+
set_donation({
34+
supporter_name: raw.supporter_name,
35+
support_coffees: raw.support_coffees,
36+
support_note: raw.support_note ?? ''
37+
})
38+
}
39+
} catch (error) {
40+
console.error('Failed to fetch latest donation', error)
41+
}
42+
}
43+
fetch_donation()
44+
}, [is_active])
45+
46+
return donation
47+
}

packages/vscode/src/view/frontend/intro/Intro/Intro.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@ import { BuyMeACoffee } from '@ui/components/editor/BuyMeACoffee'
55
import { Icon } from '@ui/components/editor/Icon'
66
import cn from 'classnames'
77

8+
type Donation = {
9+
supporter_name: string
10+
support_coffees: number
11+
support_note: string
12+
}
13+
814
type Props = {
915
on_new_chat: () => void
1016
on_api_call: () => void
1117
version: string
18+
latest_donation: Donation | null
1219
}
1320

1421
export const Intro: React.FC<Props> = (props) => {
@@ -28,7 +35,12 @@ export const Intro: React.FC<Props> = (props) => {
2835
description="Send prompt with an API provider"
2936
on_click={props.on_api_call}
3037
/>
31-
<BuyMeACoffee username="robertpiosik" />
38+
<BuyMeACoffee
39+
username="robertpiosik"
40+
supporter_name={props.latest_donation?.supporter_name}
41+
support_coffees={props.latest_donation?.support_coffees}
42+
support_note={props.latest_donation?.support_note}
43+
/>
3244
</div>
3345
</div>
3446
<div className={styles.bottom}>

0 commit comments

Comments
 (0)