Skip to content

Commit

Permalink
feat: aligned copy around earnings, even simpler collect modal
Browse files Browse the repository at this point in the history
  • Loading branch information
efstajas committed Oct 2, 2023
1 parent 2a8a2f5 commit caf893d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 85 deletions.
115 changes: 43 additions & 72 deletions src/lib/flows/collect-flow/collect-amounts.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@
import expect from '$lib/utils/expect';
import transact, { makeTransactPayload } from '$lib/components/stepper/utils/transact';
import type { StepComponentEvents } from '$lib/components/stepper/types';
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, onMount } from 'svelte';
import SafeAppDisclaimer from '$lib/components/safe-app-disclaimer/safe-app-disclaimer.svelte';
import type { AddressDriverAccount } from '$lib/stores/streams/types';
export let context: Writable<CollectFlowState>;
const restorer = $context.restorer;
$: cycle = $context.currentDripsCycle ?? unreachable();
$: currentCycleEnd = new Date(cycle.start.getTime() + cycle.durationMillis);
Expand Down Expand Up @@ -86,6 +84,15 @@
return acc;
}, []);
// Initially select all incoming squeeze senders by default, unless there's prior state.
onMount(() => {
if ($context.selectedSqueezeSenderItems?.length === 0 && !$context.squeezeEnabled) {
$context.selectedSqueezeSenderItems = incomingEstimatesBySender.map(
(e) => e.sender.accountId,
);
}
});
let currentCycleSenders: Items;
$: currentCycleSenders = Object.fromEntries(
mapFilterUndefined(incomingEstimatesBySender, (estimate) => {
Expand All @@ -110,11 +117,8 @@
}),
);
let squeezeEnabled = restorer.restore('squeezeEnabled');
let selectedSqueezeSenderItems: string[] = restorer.restore('selectedSqueezeSenderItems');
$: totalSelectedSqueezeAmount = squeezeEnabled
? selectedSqueezeSenderItems.reduce<bigint>(
$: totalSelectedSqueezeAmount = $context.squeezeEnabled
? $context.selectedSqueezeSenderItems.reduce<bigint>(
(acc, sender) =>
acc +
(incomingEstimatesBySender.find((e) => e.sender.accountId === sender)?.amount ??
Expand Down Expand Up @@ -145,8 +149,8 @@
const { DRIPS, ADDRESS_DRIVER } = getNetworkConfig();
let squeezeArgs: Awaited<ReturnType<typeof getSqueezeArgs>> | undefined;
if (squeezeEnabled && selectedSqueezeSenderItems.length > 0) {
squeezeArgs = await getSqueezeArgs(selectedSqueezeSenderItems, tokenAddress);
if ($context.squeezeEnabled && $context.selectedSqueezeSenderItems.length > 0) {
squeezeArgs = await getSqueezeArgs($context.selectedSqueezeSenderItems, tokenAddress);
}
const collectFlow = await AddressDriverPresets.Presets.createCollectFlow({
Expand Down Expand Up @@ -201,58 +205,44 @@
context.update((c) => ({
...c,
amountCollected,
squeezeEnabled,
receipt,
}));
// The squeeze event should be indexed by now, so this should cause the dashboard to update
// in the background to reflect the newly reduced incoming balance.
if (squeezeEnabled) await balancesStore.updateSqueezeHistory(transactContext.accountId);
if ($context.squeezeEnabled) {
await balancesStore.updateSqueezeHistory(transactContext.accountId);
}
},
}),
);
}
$: restorer.saveAll({
squeezeEnabled,
selectedSqueezeSenderItems,
});
</script>

<StepLayout>
<EmojiAndToken emoji="👛" {tokenAddress} animateTokenOnMount={splittableAfterReceive !== 0n} />
<StepHeader headline={`Collect ${selectedToken.symbol}`} />
<div>
<p>
Income from Drip Lists, projects, and streams settles once per week. Your collectable balance
updates next on <span class="typo-text-bold">{formatDate(currentCycleEnd, 'onlyDay')}</span>.
Earnings settle once per week. The next settlement date is <span class="typo-text-bold"
>{formatDate(currentCycleEnd, 'onlyDay')}</span
>.
</p>
<a
class="typo-text-small"
target="_blank"
rel="noreferrer"
href="https://docs.drips.network/docs/streaming-and-splitting/manage-funds/collect-earnings"
>Learn more</a
>
</div>
{#if incomingEstimatesBySender.length > 0}
<div class="squeeze-section">
<Toggleable label="Include unsettled stream income" bind:toggled={squeezeEnabled}>
<p>
You may collect stream income from specific senders already before it settles, but the
network fee for collecting increases with each selected sender.
</p>
<Toggleable label="Include unsettled stream earnings" bind:toggled={$context.squeezeEnabled}>
<AnnotationBox type="warning">
The amounts shown below are estimated based on your system time so the value you collect
may slightly differ.
The network fee for collecting increases with each selected sender. Unsettled earnings are
estimates, so you may collect less than expected.
</AnnotationBox>
<div class="list-wrapper">
<ListSelect
items={currentCycleSenders}
multiselect
bind:selected={selectedSqueezeSenderItems}
bind:selected={$context.selectedSqueezeSenderItems}
searchable={false}
emptyStateText="You don't have any unsettled income from streams."
emptyStateText="You don't have any unsettled earnings from streams."
/>
</div>
</Toggleable>
Expand All @@ -262,36 +252,29 @@
<LineItems
lineItems={mapFilterUndefined(
[
squeezeEnabled
? {
title: `Unsettled ${selectedToken.symbol}`,
subtitle: 'From incoming streams',
value:
'' +
formatTokenAmount(
makeAmount(totalSelectedSqueezeAmount ?? 0n),
selectedToken.decimals,
1n,
),
symbol: selectedToken.symbol,
}
: undefined,
balances.receivable > 0n
? {
title: `Settled ${selectedToken.symbol}`,
subtitle: 'From incoming streams',
value: formatTokenAmount(
makeAmount(balances.receivable),
selectedToken.decimals,
1n,
),
title: `Streams`,
subtitle: $context.squeezeEnabled ? 'Including unsettled earnings' : undefined,
value:
$context.squeezeEnabled && totalSelectedSqueezeAmount > 0n
? '' +
formatTokenAmount(
makeAmount(balances.receivable + (totalSelectedSqueezeAmount ?? 0n)),
selectedToken.decimals,
1n,
)
: formatTokenAmount(
makeAmount(balances.receivable),
selectedToken.decimals,
1n,
),
symbol: selectedToken.symbol,
}
: undefined,
balances.splittable > 0n
? {
title: `Settled ${selectedToken.symbol}`,
subtitle: 'From Drip Lists and projects',
title: 'Drip Lists and projects',
value: formatTokenAmount(
makeAmount(balances.splittable),
selectedToken.decimals,
Expand All @@ -311,7 +294,7 @@
? {
title: `Splitting ${getSplitPercent(1000000n - ownSplitsWeight, 'pretty')}`,
value:
(squeezeEnabled ? '' : '') +
($context.squeezeEnabled ? '' : '') +
formatTokenAmount(
makeAmount(collectableAfterSplit - splittableAfterReceive),
selectedToken.decimals,
Expand All @@ -338,7 +321,7 @@
title: 'You collect',
subtitle: 'These funds will be sent to your wallet.',
value:
(squeezeEnabled ? '' : '') +
($context.squeezeEnabled && totalSelectedSqueezeAmount > 0n ? '' : '') +
formatTokenAmount(makeAmount(collectableAfterSplit), selectedToken.decimals, 1n),
symbol: selectedToken.symbol,
disabled: collectableAfterSplit === 0n,
Expand All @@ -365,18 +348,6 @@
text-align: left;
}
.squeeze-section p {
margin-bottom: 1rem;
}
a {
color: var(--color-foreground-level-6);
text-decoration: underline;
display: block;
margin-top: 0.5rem;
text-align: left;
}
.list-wrapper {
margin-top: 1rem;
border: 1px solid var(--color-foreground);
Expand Down
13 changes: 4 additions & 9 deletions src/lib/flows/collect-flow/collect-flow-state.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { newRestorer, type Restorer } from '$lib/utils/restorer';
import type { ContractReceipt } from 'ethers';
import type { SplitsEntry } from 'radicle-drips';
import { writable } from 'svelte/store';

type Restorable = {
squeezeEnabled: boolean;
selectedSqueezeSenderItems: string[];
};

export interface CollectFlowState {
tokenAddress?: string;
balances?: {
Expand All @@ -23,13 +17,14 @@ export interface CollectFlowState {
durationMillis: number;
};
amountCollected?: bigint;
squeezeEnabled?: boolean;
squeezeEnabled: boolean;
selectedSqueezeSenderItems: string[];
receipt?: ContractReceipt;
restorer: Restorer<Restorable>;
}

export default (tokenAddress?: string) =>
writable<CollectFlowState>({
tokenAddress,
restorer: newRestorer<Restorable>({ squeezeEnabled: false, selectedSqueezeSenderItems: [] }),
squeezeEnabled: false,
selectedSqueezeSenderItems: [],
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
onMount(() =>
dispatch('await', {
promise,
message: 'Fetching collectable amounts',
message: 'Getting ready',
}),
);
</script>
19 changes: 18 additions & 1 deletion src/lib/utils/format-date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ const DATE_FORMAT_CONVENTIONS = {
},
} as const;

function suffixNumber(n: number) {
if (n > 3 && n < 21) return 'th';
switch (n % 10) {
case 1:
return 'st';
case 2:
return 'nd';
case 3:
return 'rd';
default:
return 'th';
}
}

/**
* Format a date with a reusable, pre-configured date format convention.
* @param date The date to format.
Expand All @@ -33,5 +47,8 @@ export default function (
date: Date,
convention: keyof typeof DATE_FORMAT_CONVENTIONS = 'standard',
): string {
return Intl.DateTimeFormat('en-US', DATE_FORMAT_CONVENTIONS[convention]).format(date);
return (
Intl.DateTimeFormat('en-US', DATE_FORMAT_CONVENTIONS[convention]).format(date) +
(convention === 'onlyDay' ? suffixNumber(date.getDate()) : '')
);
}
4 changes: 2 additions & 2 deletions src/routes/app/(app)/projects/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@
<div class="earnings card">
<div class="content">
<div class="values">
<KeyValuePair key="Collectable now" highlight>
<KeyValuePair key="Settled earnings" highlight>
<AggregateFiatEstimate amounts={$splittableStore} />
</KeyValuePair>
<KeyValuePair key="Next payout">{formatDate(cycle.end, 'onlyDay')}</KeyValuePair>
<KeyValuePair key="Next settlement">{formatDate(cycle.end, 'onlyDay')}</KeyValuePair>
</div>
<div />
</div>
Expand Down

0 comments on commit caf893d

Please sign in to comment.