Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1057 embedable support button: "backend" resources #1308

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
693 changes: 655 additions & 38 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"isomorphic-fetch": "^3.0.0",
"jimp": "^0.22.12",
"lodash": "^4.17.21",
"puppeteer": "^23.6.0",
"redis": "^4.6.14",
"sanitize-html": "^2.13.0",
"satori": "^0.10.13",
Expand Down
8 changes: 7 additions & 1 deletion src/lib/components/illustrations/drip.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<script lang="ts">
export let height = '38px';
export let fill = 'var(--color-primary)';
export let stroke: string | undefined = undefined;
export let strokeWidth: string | undefined = undefined;
</script>

<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 25 38" {height}
>{@html `
<path fill=${fill} d="M.531 25.456c0-2.569 1.146-5.624 3.244-9.67 1.405-2.71 3.211-5.818 5.338-9.478.915-1.576 1.89-3.254 2.918-5.046 1.028 1.792 2.003 3.47 2.918 5.046 2.127 3.66 3.934 6.769 5.338 9.478 2.098 4.046 3.244 7.101 3.244 9.67 0 5.74-5.192 11.5-11.5 11.5s-11.5-5.76-11.5-11.5Z"/>
<path
${stroke ? `stroke="${stroke}" ` : ''}
${strokeWidth ? `stroke-width="${strokeWidth}" ` : ''}
fill=${fill}
d="M.531 25.456c0-2.569 1.146-5.624 3.244-9.67 1.405-2.71 3.211-5.818 5.338-9.478.915-1.576 1.89-3.254 2.918-5.046 1.028 1.792 2.003 3.47 2.918 5.046 2.127 3.66 3.934 6.769 5.338 9.478 2.098 4.046 3.244 7.101 3.244 9.67 0 5.74-5.192 11.5-11.5 11.5s-11.5-5.76-11.5-11.5Z"/>
`}</svg
>
3 changes: 2 additions & 1 deletion src/lib/components/project-avatar/project-avatar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@

export let pendingAvatar = false;

type Size = 'tiny' | 'small' | 'medium' | 'large' | 'huge';
type Size = 'micro' | 'tiny' | 'small' | 'medium' | 'large' | 'huge';
export let size: Size = 'small';
export let outline = project.__typename === 'ClaimedProjectData';

const CONTAINER_SIZES: Record<Size, string> = {
micro: '0.8rem',
tiny: '1.5rem',
small: '2rem',
medium: '3rem',
Expand Down
107 changes: 107 additions & 0 deletions src/lib/components/project-support-button/drips-style-button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<script lang="ts">
import Drip from '$lib/components/illustrations/drip.svelte';
import ProjectAvatar from '$lib/components/project-avatar/project-avatar.svelte';
import {
SupportButtonStat,
SupportButtonText,
type SupportButtonData,
type SupportButtonOptions,
} from './project-support-button';
import AggregateFiatEstimate from '$lib/components/aggregate-fiat-estimate/aggregate-fiat-estimate.svelte';

export let options: SupportButtonOptions;
export let data: SupportButtonData;

$: dripFill = options.background === 'blue' ? 'var(--color-background)' : 'var(--color-primary)';
$: dependencies = data?.dependencies || 0;
$: dependenciesString =
dependencies && dependencies === 1
? `Splitting to ${dependencies} Dependency`
: `Splitting to ${dependencies} Dependencies`;
</script>

<a
href={data.projectUrl}
class={`support-button support-button--drips support-button--${options.background} support-button--${options.text} support-button--${options.stat}`}
>
<span class="support-button__icon">
<Drip fill={dripFill} />
</span>

<span class="support-button__text">
{#if options.text === SupportButtonText.me}
Drip to me
{:else if options.text === SupportButtonText.us}
Support us on Drips
{:else if options.text === SupportButtonText.project}
Support <ProjectAvatar project={data.projectAvatar} size="tiny" /><strong
>{data.projectName}</strong
> on Drips
{/if}
</span>

{#if options.stat === SupportButtonStat.support}
<span class="support-button__support"
><AggregateFiatEstimate amounts={data.projectAvatar.totalEarned} /></span
>
{:else if options.stat === SupportButtonStat.dependencies}
<span class="support-button__dependencies">{dependenciesString}</span>
{/if}
</a>

<style>
.support-button--drips {
border: 1px solid #28333d;
padding: 0 10px;
border-radius: 1rem 0 1rem 1rem;
display: inline-flex;
gap: 7px;
align-items: center;
height: 32px;
background-color: #ffffff;
color: #28333d;
}

.support-button--drips.support-button--dark {
background-color: #28333d;
color: #ffffff;
}

.support-button--drips.support-button--blue {
background-color: #5555ff;
color: #ffffff;
}

.support-button__icon {
width: 12px;
display: flex;
align-items: center;
}

.support-button__text {
display: flex;
gap: 7px;
align-items: center;
}

.support-button__avatar {
width: 24px;
height: 24px;
border-radius: 100%;
}

.support-button__dependencies,
.support-button__support {
color: #ffffff;
font-weight: 600;
}

.support-button--drips.support-button--light .support-button__dependencies,
.support-button--drips.support-button--light .support-button__support {
color: #5555ff;
}

.support-button strong {
font-weight: 600;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script lang="ts">
import Drip from '$lib/components/illustrations/drip.svelte';
import {
SupportButtonStat,
SupportButtonText,
type SupportButtonData,
type SupportButtonOptions,
} from './project-support-button';
import ProjectAvatar from '$lib/components/project-avatar/project-avatar.svelte';
import AggregateFiatEstimate from '$lib/components/aggregate-fiat-estimate/aggregate-fiat-estimate.svelte';

export let options: SupportButtonOptions;
export let data: SupportButtonData;

$: dripFill = options.background === 'blue' ? 'var(--color-background)' : 'var(--color-primary)';
$: dripStroke = options.background === 'blue' ? 'var(--color-primary)' : 'white';
$: dependencies = data?.dependencies || 0;
$: dependenciesString =
dependencies && dependencies === 1
? `Splitting to ${dependencies} Dependency`
: `Splitting to ${dependencies} Dependencies`;
</script>

<a
href={data.projectUrl}
class={`support-button support-button--github support-button--${options.background} support-button--${options.text} support-button--${options.stat}`}
>
<span class="support-button__icon">
<Drip fill={dripFill} stroke={dripStroke} strokeWidth="4px" />
</span>

<span class="support-button__text">
{#if options.text === SupportButtonText.me}
Drip to me
{:else if options.text === SupportButtonText.us}
Support us on Drips
{:else if options.text === SupportButtonText.project}
Support <ProjectAvatar project={data.projectAvatar} size="micro" /><strong
>{data.projectName}</strong
> on Drips
{/if}
</span>

{#if options.stat === SupportButtonStat.support}
<span class="support-button__support"
><AggregateFiatEstimate amounts={data.projectAvatar.totalEarned} /></span
>
{:else if options.stat === SupportButtonStat.dependencies}
<span class="support-button__dependencies">{dependenciesString}</span>
{/if}
</a>

<style>
.support-button strong {
font-weight: 600;
}

.support-button--github {
display: inline-flex;
align-items: center;
font-size: 11px;
font-family: Verdana, sans-serif;
gap: 3px;
background: linear-gradient(0deg, #425160 0%, #5a6b7c 100%);
height: 20px;
padding: 0 4px;
color: white;
border-radius: 4px;
overflow: hidden;
}

.support-button__icon {
width: 6px;
display: flex;
align-items: center;
}

.support-button__text {
display: flex;
gap: 3px;
align-items: center;
}

.support-button--github.support-button--dependencies,
.support-button--github.support-button--support {
padding-right: 0;
}

.support-button__support,
.support-button__dependencies {
background: #5555ff;
height: 20px;
padding: 0 4px;
display: flex;
align-items: center;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import {
SupportButtonStyle,
type SupportButtonData,
type SupportButtonOptions,
} from './project-support-button';
import DripsSupportButton from './drips-style-button.svelte';
import GithubSupportButton from './github-style-button.svelte';
import fiatEstimates from '$lib/utils/fiat-estimates/fiat-estimates';
import { onMount } from 'svelte';

export let data: SupportButtonData;
export let options: SupportButtonOptions;

onMount(() => {
fiatEstimates.start();
});
</script>

<div>
{#if options.style === SupportButtonStyle.github}
<GithubSupportButton {data} {options} />
{:else}
<DripsSupportButton {data} {options} />
{/if}
</div>

<style>
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { ProjectAvatarFragment } from '$lib/components/project-avatar/__generated__/gql.generated';
import type { Amount } from '../aggregate-fiat-estimate/aggregate-fiat-estimate';

export enum SupportButtonStyle {
github = 'github',
drips = 'drips',
default = drips,
}

export enum SupportButtonText {
project = 'project',
me = 'me',
us = 'us',
default = me,
}

export enum SupportButtonBackground {
dark = 'dark',
light = 'light',
blue = 'blue',
default = light,
}

export enum SupportButtonStat {
support = 'support',
dependencies = 'dependencies',
none = 'none',
default = none,
}

export type SupportButtonOptions = {
style: SupportButtonStyle;
text: SupportButtonText;
background: SupportButtonBackground;
stat: SupportButtonStat;
};

export type SupportButtonData = {
support?: number;
dependencies?: string;
projectName?: string;
projectUrl?: string;
// TODO: a more appropriate type
projectAvatar: ProjectAvatarFragment & { totalEarned?: Amount[] };
};
3 changes: 1 addition & 2 deletions src/lib/components/stepper/__test__/stepper.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import OnlyText from './test-steps/only-text.svelte';
import userEvent from '@testing-library/user-event';
import { tick } from 'svelte';
import TriggerAwaitEvent from './test-steps/trigger-await-event.svelte';
import wait from '$lib/utils/wait';

vi.mock('$app/environment', () => ({
browser: true,
}));

const wait = (millis: number) => new Promise((resolve) => setTimeout(resolve, millis));

class ResizeObserver {
observe() {
return undefined;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/utils/wait.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function wait(millis: number) {
return new Promise((resolve) => setTimeout(resolve, millis));
}
31 changes: 31 additions & 0 deletions src/routes/embed/project/[projectUrl]/support.png/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { RequestHandler } from './$types';
import { error } from '@sveltejs/kit';
import puppeteer from 'puppeteer';

const REPLACE_PNG_REGEX = /(\.png\/?)(\?.*|$)/;

export const GET: RequestHandler = async ({ url }) => {
// drips.network/embed/project.png/support.png/?background=dark
// ==> drips.network/embed/project.png/support?background=dark
const imageUrl = url.href.replace(REPLACE_PNG_REGEX, '$2');
// TODO: handle invalid href

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();

await page.goto(imageUrl);
const selector = '.embed-badge';
await page.waitForSelector(selector);
const element = await page.$(selector);
// if there's no element for any reason, that's
// very unexpected and we're toast
if (!element) {
return error(500);
}
const imageBuffer = await element.screenshot({ omitBackground: true });

return new Response(imageBuffer, {
status: 200,
headers: new Headers({ 'Content-Type': 'image/png' }),
});
};
Loading
Loading