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

feat: drip list support button #705

Merged
merged 3 commits into from
Oct 4, 2023
Merged
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
4 changes: 2 additions & 2 deletions src/lib/components/drip-list-editor/drip-list-editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
description: undefined,
};
export let showListFirst = false;
export let projectUrlToAdd: string | undefined = undefined;
export let urlToAdd: string | undefined = undefined;

// validation
let listValid = false;
Expand Down Expand Up @@ -65,7 +65,7 @@
bind:percentages={dripList.percentages}
bind:items={dripList.items}
bind:valid={listValid}
addOnMount={projectUrlToAdd}
addOnMount={urlToAdd}
/>
</FormField>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
DripList,
RepoDriverSplitReceiver,
} from '$lib/utils/metadata/types';
import { onMount } from 'svelte';
import DripListService from '$lib/utils/driplist/DripListService';
import walletStore from '$lib/stores/wallet/wallet.store';
import Spinner from '$lib/components/spinner/spinner.svelte';
Expand All @@ -20,15 +19,59 @@
import Stepper from '$lib/components/stepper/stepper.svelte';
import editDripListSteps from '$lib/flows/edit-drip-list/edit-drip-list-steps';
import buildUrl from '$lib/utils/build-url';
import type { SplitsEntry } from 'radicle-drips';

export let project: ClaimedGitProject | undefined = undefined;
export let dripList: DripList | undefined = undefined;

let ownDripList: DripList | null | undefined = undefined;
let ownDripListSplits: SplitsEntry[] | undefined = undefined;

let isSupporting: boolean | undefined;
$: isSupporting = ownDripListSplits?.some(
(s) =>
s.accountId === project?.repoDriverAccount.accountId ||
s.accountId === dripList?.account.accountId,
);

$: isOwner =
$walletStore.connected &&
($walletStore.dripsAccountId === project?.owner.accountId ||
$walletStore.dripsAccountId === dripList?.account.owner.accountId);

let supportUrl: string;
$: {
if (project) {
supportUrl = project.source.url;
} else if (dripList) {
supportUrl = `https://drips.network/app/drip-lists/${dripList.account.accountId}`;
} else {
throw new Error('You must populate either the `project` or `dripList` prop.');
}
}

export let project: ClaimedGitProject;
const { initialized } = walletStore;

let updating = true;
async function updateState() {
updating = true;

if (!$initialized) {
// Wait for wallet to be initialized before proceeding
await new Promise<void>((resolve) => {
const unsubscribe = initialized.subscribe((v) => {
if (v) {
unsubscribe();
resolve();
}
});
});
}

let dripList: DripList | null | undefined = undefined;
let isSupportingProject: boolean | undefined = undefined;
onMount(async () => {
const { address } = $walletStore;
if (!address) {
dripList = null;
ownDripList = null;
updating = false;
return;
}

Expand All @@ -37,47 +80,50 @@

if (result[0]) {
const subgraph = getSubgraphClient();
const dripListSplits = await subgraph.getSplitsConfigByAccountId(result[0].account.accountId);

isSupportingProject = Boolean(
dripListSplits.find((s) => s.accountId === project.repoDriverAccount.accountId),
);
dripList = result[0];
ownDripListSplits = await subgraph.getSplitsConfigByAccountId(result[0].account.accountId);
ownDripList = result[0];
} else {
dripList = null;
ownDripList = null;
}
});

updating = false;
}
$: {
$walletStore.connected;
updateState();
}

let loadingModal = false;
async function handleSupportButton() {
if (!dripList) {
goto(buildUrl('/app/funder-onboarding', { projectToAdd: project.source.url }));
if (!ownDripList) {
goto(buildUrl('/app/funder-onboarding', { urlToAdd: supportUrl }));
} else {
// TODO: Refresh profile state after becoming a supporter
loadingModal = true;
const representationalSplits = await getRepresentationalSplitsForAccount(
dripList.account.accountId,
dripList.projects.filter((s): s is RepoDriverSplitReceiver => 'source' in s),
ownDripList.account.accountId,
ownDripList.projects.filter((s): s is RepoDriverSplitReceiver => 'source' in s),
);

modal.show(
Stepper,
undefined,
editDripListSteps(
dripList.account.accountId,
dripList.name,
dripList.description,
ownDripList.account.accountId,
ownDripList.name,
ownDripList.description,
representationalSplits,
project,
dripList,
),
);
loadingModal = false;
}
}
</script>

<div class="become-supporter-card">
{#if dripList === undefined || loadingModal}
<div class="become-supporter-card" class:is-owner={isOwner}>
{#if ownDripList === undefined || loadingModal || updating}
<div transition:fade|local={{ duration: 300 }} class="loading-overlay">
<Spinner />
</div>
Expand All @@ -88,35 +134,28 @@
<div class="circle">
<Heart style="height: 3rem; width: 3rem; fill: var(--color-primary)" />
</div>
<div>
<ProjectAvatar {project} size="large" outline />
</div>
{#if project}
<div>
<ProjectAvatar {project} size="large" outline />
</div>
{/if}
</div>
</div>
<h2 class="pixelated">Become a supporter</h2>
<p>
{#if isSupportingProject}
You're already supporting <span class="typo-text-bold">{project.source.repoName}</span> with your
Drip List.
{#if isSupporting}
You're already supporting this with your Drip List.
{:else}
Add <span class="typo-text-bold">{project.source.repoName}</span> to your Drip List to support
this project.
Add this {project ? 'project' : ''} to your Drip List to flexibly support it with an ongoing contribution.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Add this {project ? 'project' : ''} to your Drip List to flexibly support it with an ongoing contribution.
Add this {project ? 'project' : ''} to {ownDripList === null ? 'a' : 'your'} Drip List where they will receive a portion of any funds streamed to your list.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it sounds weird to use "where" here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"and they will.."
would also do

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's better. But maybe "and it will" since it's referring to the list.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's referring to the project though (which receives a portion of what goes to the list). 'Become a supporter of the project by adding it to a Drip List'

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right this is used on project and drip list pages* So ya maybe a conditional for they/it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works for project and list. Just because it's a project doesn't mean it's multiple people.

{/if}
</p>
<Button
on:click={handleSupportButton}
disabled={isSupportingProject}
disabled={isSupporting || isOwner}
size="large"
icon={Plus}
variant="primary">{dripList === null ? 'Create your Drip List' : 'Add to Drip List'}</Button
variant="primary">{ownDripList === null ? 'Create your Drip List' : 'Add to Drip List'}</Button
>
<div class="benefits typo-text-small">
{#if isSupportingProject}You're getting…{:else}Youʼll get…{/if}
<div class="benefit">
<Heart />
<span>…to feel good about yourself, because you're supporting open-source software.</span>
</div>
</div>
</div>

<style>
Expand Down Expand Up @@ -177,16 +216,9 @@
box-shadow: var(--elevation-low);
}

.benefits {
color: var(--color-foreground-level-5);
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.benefits > .benefit {
display: flex;
gap: 0.5rem;
.is-owner {
opacity: 0.75;
pointer-events: none;
}

p {
Expand Down
4 changes: 3 additions & 1 deletion src/lib/flows/edit-drip-list/edit-drip-list-steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ import SuccessStep from '$lib/components/success-step/success-step.svelte';
import { get } from 'svelte/store';
import EditDripListStep from './steps/edit-drip-list.svelte';
import walletStore from '$lib/stores/wallet/wallet.store';
import type { GitProject } from '$lib/utils/metadata/types';
import type { DripList, GitProject } from '$lib/utils/metadata/types';

export default (
dripListId: string,
listName: string,
listDescription: string | undefined,
representationalSplits: Splits,
projectToAdd?: GitProject,
dripListToAdd?: DripList,
) => ({
context: undefined,
steps: [
makeStep({
component: EditDripListStep,
props: {
projectToAdd,
dripListToAdd,
dripListId,
representationalSplits,
listName,
Expand Down
13 changes: 10 additions & 3 deletions src/lib/flows/edit-drip-list/steps/edit-drip-list.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
getNFTDriverClient,
getNFTDriverTxFactory,
} from '$lib/utils/get-drips-clients';
import type { GitProject } from '$lib/utils/metadata/types';
import type { DripList, GitProject } from '$lib/utils/metadata/types';
import modal from '$lib/stores/modal';
import NftDriverMetadataManager from '$lib/utils/metadata/NftDriverMetadataManager';
import DripListService from '$lib/utils/driplist/DripListService';
Expand All @@ -33,11 +33,10 @@
export let dripListId: string;
export let representationalSplits: Splits;
export let projectToAdd: GitProject | undefined = undefined;
export let dripListToAdd: DripList | undefined = undefined;
export let listName: string;
export let listDescription: string | undefined;

// TODO: Ensure these values are saved in case there's some TX error.

function flattenRepresentationalSplits(list: Splits): Split[] {
return list.reduce<Split[]>((acc, i) => {
if (i.type === 'split-group') {
Expand Down Expand Up @@ -85,6 +84,14 @@
items[projectToAdd.source.url] = projectItem(projectToAdd);
}

if (dripListToAdd) {
items[dripListToAdd.account.accountId] = dripListItem(
dripListToAdd.name,
dripListToAdd.account.accountId,
dripListToAdd.account.owner.accountId,
);
}

let dripList: DripListConfig = {
items,
percentages,
Expand Down
5 changes: 4 additions & 1 deletion src/lib/stores/wallet/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ function isSupportedChainId(chainId: number): chainId is ChainId {
}

const configuredChainId = Number(PUBLIC_NETWORK);
assert(isSupportedChainId(configuredChainId));
assert(
isSupportedChainId(configuredChainId),
'Missing or invalid PUBLIC_NETWORK env variable. See DEVELOPMENT.md for more information.',
);

export function isConfiguredChainId(chainId: number): boolean {
return chainId === configuredChainId;
Expand Down
43 changes: 37 additions & 6 deletions src/routes/app/(app)/drip-lists/[listId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import HeadMeta from '$lib/components/head-meta/head-meta.svelte';
import IdentityBadge from '$lib/components/identity-badge/identity-badge.svelte';
import SectionSkeleton from '$lib/components/section-skeleton/section-skeleton.svelte';
import SupportCard from '$lib/components/support-card/support-card.svelte';
import Supporters from '$lib/components/supporters-section/supporters.section.svelte';
import streamsStore from '$lib/stores/streams/streams.store';
import type { PageData } from './$types';
Expand Down Expand Up @@ -33,12 +34,19 @@
</div>

<SectionSkeleton loaded={Boolean(data.dripList)}>
<DripListCard
{supportStreams}
incomingSplits={data.incomingSplits}
dripList={data.dripList}
representationalSplits={data.representationalSplits}
/>
<div class="list-and-support">
<div class="list">
<DripListCard
{supportStreams}
incomingSplits={data.incomingSplits}
dripList={data.dripList}
representationalSplits={data.representationalSplits}
/>
</div>
<div class="support">
<SupportCard {dripList} />
</div>
</div>
</SectionSkeleton>
</section>

Expand All @@ -61,6 +69,23 @@
gap: 3rem;
}

.list-and-support {
padding: 2px 0 8px 0;
display: flex;
gap: 1rem;
}

.list-and-support .list {
flex-grow: 1;
width: 100%;
}

.list-and-support .support {
flex-grow: 0;
max-width: 18rem;
align-self: top;
}

.owner {
display: flex;
gap: 0.25rem;
Expand All @@ -69,4 +94,10 @@
.owner span {
color: var(--color-foreground-level-6);
}

@media (max-width: 1252px) {
.list-and-support {
flex-direction: column;
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import PrimaryColorThemer from '$lib/components/primary-color-themer/primary-color-themer.svelte';
import SectionHeader from '$lib/components/section-header/section-header.svelte';
import SplitsIcon from 'radicle-design-system/icons/Splits.svelte';
import BecomeSupporterCard from '../become-supporter-card/become-supporter-card.svelte';
import SupportCard from '$lib/components/support-card/support-card.svelte';
import ProjectProfileHeader from '$lib/components/project-profile-header/project-profile-header.svelte';
import type { GitProject } from '$lib/utils/metadata/types';
import UnclaimedProjectCard from '$lib/components/unclaimed-project-card/unclaimed-project-card.svelte';
Expand Down Expand Up @@ -294,7 +294,7 @@
{#if project.owner}
<aside>
<div class="become-supporter-card">
<BecomeSupporterCard {project} />
<SupportCard {project} />
</div>
</aside>
{/if}
Expand Down
Loading