Files
mutiny-web/src/components/BalanceBox.tsx
Paul Miller e01b8465d5 web worker
check if already initialized

more progress, zap feed not loading?

request send receive

fix setup

profile editing and show zaps

wallet connections

kitchen sink

mutiny plus and misc

get rid of swap

backup / restore, nostr stuff

get rid of gifts

channels stuff

manage federations and profile fixes

cleanup

fix build

fix chrome android

update to cap 6

bump to actual 6.0.0

update xcode version

fix interpolation again (regression)

move all static methods to the worker

add doc strings

get rid of window.nostr, make parse params async

fight load flicker

use a "-test" bundle for debug builds so they don't clobber

add back swaps and do some cleanup

fix activity flicker
2024-05-06 21:00:59 +01:00

212 lines
8.9 KiB
TypeScript

import { A, useNavigate } from "@solidjs/router";
import { Shuffle, Users } from "lucide-solid";
import { createMemo, Match, Show, Suspense, Switch } from "solid-js";
import {
AmountFiat,
AmountSats,
ButtonCard,
FancyCard,
Indicator,
InfoBox,
MediumHeader,
NiceP,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
export function LoadingShimmer(props: { center?: boolean; small?: boolean }) {
return (
<div class="flex animate-pulse flex-col gap-2">
<h1
class="text-4xl font-light"
classList={{ "flex justify-center": props.center }}
>
<div
class="rounded bg-neutral-700"
classList={{
"h-[2.5rem] w-[12rem]": !props.small,
"h-[1rem] w-[8rem]": props.small
}}
/>
</h1>
<Show when={!props.small}>
<h2
class="text-xl font-light text-white/70"
classList={{ "flex justify-center": props.center }}
>
<div class="h-[1.75rem] w-[8rem] rounded bg-neutral-700" />
</h2>
</Show>
</div>
);
}
const STYLE =
"px-2 py-1 rounded-xl text-sm flex gap-2 items-center font-semibold";
export function BalanceBox(props: { loading?: boolean; small?: boolean }) {
const [state, _actions] = useMegaStore();
const navigate = useNavigate();
const i18n = useI18n();
const totalOnchain = createMemo(
() =>
(state.balance?.confirmed || 0n) +
(state.balance?.unconfirmed || 0n) +
(state.balance?.force_close || 0n)
);
const usableOnchain = createMemo(
() =>
(state.balance?.confirmed || 0n) +
(state.balance?.unconfirmed || 0n)
);
return (
<VStack>
<Switch>
<Match when={state.federations && state.federations.length}>
<MediumHeader>Fedimint</MediumHeader>
<FancyCard>
<Show
when={!props.loading}
fallback={<LoadingShimmer />}
>
<div class="flex justify-between">
<div class="flex flex-col gap-1">
<div class="text-2xl">
<AmountSats
amountSats={
state.balance?.federation || 0n
}
icon="community"
denominationSize="lg"
isFederation
/>
</div>
<div class="text-lg text-white/70">
<Suspense>
<AmountFiat
amountSats={
state.balance?.federation ||
0n
}
denominationSize="sm"
/>
</Suspense>
</div>
</div>
<Show
when={state.balance?.federation || 0n > 0n}
>
<div class="self-end justify-self-end">
<A href="/swaplightning" class={STYLE}>
<Shuffle class="h-6 w-6" />
</A>
</div>
</Show>
</div>
</Show>
</FancyCard>
<ButtonCard
onClick={() => navigate("/settings/federations")}
>
<div class="flex items-center gap-2">
<Users class="inline-block text-m-red" />
<NiceP>{i18n.t("profile.manage_federation")}</NiceP>
</div>
</ButtonCard>
</Match>
<Match when={true}>
<ButtonCard
onClick={() => navigate("/settings/federations")}
>
<div class="flex items-center gap-2">
<Users class="inline-block text-m-red" />
<NiceP>{i18n.t("profile.join_federation")}</NiceP>
</div>
</ButtonCard>
</Match>
</Switch>
<MediumHeader>{i18n.t("profile.self_custody")}</MediumHeader>
<FancyCard>
<Show when={!props.loading} fallback={<LoadingShimmer />}>
<Switch>
<Match when={state.safe_mode}>
<div class="flex flex-col gap-1">
<InfoBox accent="red">
{i18n.t("common.error_safe_mode")}
</InfoBox>
</div>
</Match>
<Match when={true}>
<div class="flex flex-col gap-1">
<div class="text-2xl">
<AmountSats
amountSats={
state.balance?.lightning || 0
}
icon="lightning"
denominationSize="lg"
/>
</div>
<div class="text-lg text-white/70">
<Suspense>
<AmountFiat
amountSats={
state.balance?.lightning || 0
}
denominationSize="sm"
/>
</Suspense>
</div>
</div>
</Match>
</Switch>
</Show>
<hr class="my-2 border-m-grey-750" />
<Show when={!props.loading} fallback={<LoadingShimmer />}>
<div class="flex justify-between">
<div class="flex flex-col gap-1">
<div class="text-2xl">
<AmountSats
amountSats={totalOnchain()}
icon="chain"
denominationSize="lg"
/>
</div>
<div class="text-lg text-white/70">
<Suspense>
<AmountFiat
amountSats={totalOnchain()}
denominationSize="sm"
/>
</Suspense>
</div>
</div>
<div class="flex flex-col items-end justify-between gap-1">
<Show when={state.balance?.unconfirmed != 0n}>
<Indicator>
{i18n.t("common.pending")}
</Indicator>
</Show>
<Show when={state.balance?.unconfirmed === 0n}>
<div />
</Show>
<Show when={usableOnchain() > 0n}>
<div class="self-end justify-self-end">
<A href="/swap" class={STYLE}>
<Shuffle class="h-6 w-6" />
</A>
</div>
</Show>
</div>
</div>
</Show>
</FancyCard>
</VStack>
);
}