From f27e87178aa55ce858bcbfd4facdfa3ec99caa37 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 8 May 2024 16:48:23 -0500 Subject: [PATCH] show federation popups --- public/i18n/en.json | 3 +- src/components/Activity.tsx | 40 ++------------ src/components/AmountEditable.tsx | 14 ++--- src/components/FederationPopup.tsx | 45 ++++++++++++++++ src/components/index.ts | 1 + src/routes/Send.tsx | 7 +-- src/routes/Swap.tsx | 2 +- src/routes/Transfer.tsx | 20 ++++--- src/routes/settings/ManageFederations.tsx | 49 +++++++++++------ src/state/megaStore.tsx | 66 +++++++++-------------- src/workers/walletWorker.ts | 2 +- 11 files changed, 131 insertions(+), 118 deletions(-) create mode 100644 src/components/FederationPopup.tsx diff --git a/public/i18n/en.json b/public/i18n/en.json index 7158cfd..bea6ef3 100644 --- a/public/i18n/en.json +++ b/public/i18n/en.json @@ -568,7 +568,8 @@ "join_me": "Join me", "recommend": "Recommend federation", "recommended_by_you": "Recommended by you", - "transfer_funds": "Transfer funds" + "transfer_funds": "Transfer funds", + "transfer_funds_message": "Add a second federation to enable transfers." }, "gift": { "give_sats_link": "Give sats as a gift", diff --git a/src/components/Activity.tsx b/src/components/Activity.tsx index 592b851..a86d7cf 100644 --- a/src/components/Activity.tsx +++ b/src/components/Activity.tsx @@ -8,7 +8,6 @@ import { createSignal, For, Match, - onMount, Show, Suspense, Switch @@ -19,6 +18,7 @@ import { Button, ButtonCard, ContactButton, + FederationPopup, LoadingShimmer, NiceP, SimpleDialog @@ -365,7 +365,7 @@ function NewContactModal(props: { profile: PseudoContact; close: () => void }) { } export function CombinedActivity() { - const [state, actions, sw] = useMegaStore(); + const [state, _actions, sw] = useMegaStore(); const i18n = useI18n(); const [detailsOpen, setDetailsOpen] = createSignal(false); @@ -408,17 +408,6 @@ export function CombinedActivity() { const [newContact, setNewContact] = createSignal(); - const [ - showFederationExpirationWarning, - setShowFederationExpirationWarning - ] = createSignal(false); - - onMount(() => { - if (state.expiration_warning) { - setShowFederationExpirationWarning(true); - } - }); - return ( <> @@ -437,30 +426,7 @@ export function CombinedActivity() { }> - { - if (!open) { - setShowFederationExpirationWarning(false); - actions.clearExpirationWarning(); - } - }} - > - - {state.expiration_warning?.expiresMessage} - - navigate("/settings/federations")} - > -
- - - {i18n.t("profile.manage_federation")} - -
-
-
+
{ + if (!open) { + setShowFederationExpirationWarning(false); + actions.clearExpirationWarning(); + } + }} + > + {state.expiration_warning?.expiresMessage} + { + actions.clearExpirationWarning(); + setShowFederationExpirationWarning(false); + navigate("/settings/federations"); + }} + > +
+ + {i18n.t("profile.manage_federation")} +
+
+ + ); +} diff --git a/src/components/index.ts b/src/components/index.ts index d3b2160..5706dba 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -56,3 +56,4 @@ export * from "./EditProfileForm"; export * from "./ImportNsecForm"; export * from "./LightningAddressShower"; export * from "./FederationInviteShower"; +export * from "./FederationPopup"; diff --git a/src/routes/Send.tsx b/src/routes/Send.tsx index 7dd22b1..2056d86 100644 --- a/src/routes/Send.tsx +++ b/src/routes/Send.tsx @@ -1,10 +1,5 @@ import { MutinyInvoice, TagItem } from "@mutinywallet/mutiny-wasm"; -import { - createAsync, - useLocation, - useNavigate, - useSearchParams -} from "@solidjs/router"; +import { useLocation, useNavigate, useSearchParams } from "@solidjs/router"; import { Eye, EyeOff, Link, X, Zap } from "lucide-solid"; import { createEffect, diff --git a/src/routes/Swap.tsx b/src/routes/Swap.tsx index 157543b..c48a9a8 100644 --- a/src/routes/Swap.tsx +++ b/src/routes/Swap.tsx @@ -1,6 +1,6 @@ import { createForm, required } from "@modular-forms/solid"; import { MutinyChannel } from "@mutinywallet/mutiny-wasm"; -import { createAsync, useNavigate } from "@solidjs/router"; +import { useNavigate } from "@solidjs/router"; import { createEffect, createMemo, diff --git a/src/routes/Transfer.tsx b/src/routes/Transfer.tsx index f15d78e..66fda21 100644 --- a/src/routes/Transfer.tsx +++ b/src/routes/Transfer.tsx @@ -36,10 +36,6 @@ export function Transfer() { const [loading, setLoading] = createSignal(false); const [params] = useSearchParams(); - const canTransfer = createMemo(() => { - return true; - }); - const [transferResult, setTransferResult] = createSignal(); @@ -62,9 +58,10 @@ export function Transfer() { }); const calculateMaxFederation = createAsync(async () => { - return federationBalances()?.find( + const balance = federationBalances()?.find( (f) => f.identity_federation_id === fromFed()?.federation_id )?.balance; + return balance || 0n; }); const toBalance = createAsync(async () => { @@ -77,6 +74,11 @@ export function Transfer() { return amountSats() === calculateMaxFederation(); }); + const canTransfer = createMemo(() => { + if (!calculateMaxFederation()) return false; + return amountSats() > 0n && amountSats() <= calculateMaxFederation()!; + }); + async function handleTransfer() { try { setLoading(true); @@ -111,8 +113,6 @@ export function Transfer() { } } - // const fromFederatationId = params.from; - return ( @@ -171,7 +171,11 @@ export function Transfer() { - + {i18n.t("transfer.title")}
diff --git a/src/routes/settings/ManageFederations.tsx b/src/routes/settings/ManageFederations.tsx index ffa5f83..2b8bf97 100644 --- a/src/routes/settings/ManageFederations.tsx +++ b/src/routes/settings/ManageFederations.tsx @@ -29,6 +29,7 @@ import { ExternalLink, FancyCard, FederationInviteShower, + FederationPopup, InfoBox, KeyValue, LabelCircle, @@ -40,6 +41,7 @@ import { NavBar, NiceP, showToast, + SimpleDialog, SubtleButton, TextField, VStack @@ -59,6 +61,8 @@ export type MutinyFederationIdentity = { federation_expiry_timestamp: number; invite_code: string; meta_external_url?: string; + popup_end_timestamp?: number; + popup_countdown_message?: string; }; export type Metadata = { @@ -91,7 +95,7 @@ export function AddFederationForm(props: { browseOnly?: boolean; }) { const i18n = useI18n(); - const [_state, actions, sw] = useMegaStore(); + const [state, actions, sw] = useMegaStore(); const navigate = useNavigate(); const [error, setError] = createSignal(); const [success, setSuccess] = createSignal(""); @@ -181,6 +185,9 @@ export function AddFederationForm(props: { return (
+ + + {i18n.t("settings.manage_federations.manual")} @@ -446,8 +453,15 @@ function FederationListItem(props: { setConfirmOpen(true); } + const [transferDialogOpen, setTransferDialogOpen] = createSignal(false); + async function transferFunds() { - navigate("/transfer?from=" + props.fed.federation_id); + // If there's only one federation we need to let them know to add another + if (state.federations?.length && state.federations.length < 2) { + setTransferDialogOpen(true); + } else { + navigate("/transfer?from=" + props.fed.federation_id); + } } const [confirmOpen, setConfirmOpen] = createSignal(false); @@ -457,7 +471,6 @@ function FederationListItem(props: { <> - {/*
{JSON.stringify(props.fed, null, 2)}
*/}
{props.fed.federation_name} @@ -466,6 +479,19 @@ function FederationListItem(props: {

{props.fed.welcome_message}

+ + + {i18n.t( + "settings.manage_federations.transfer_funds_message" + )} + + - - - - {i18n.t( - "settings.manage_federations.transfer_funds" - )} - - + + + {i18n.t("settings.manage_federations.transfer_funds")} + diff --git a/src/state/megaStore.tsx b/src/state/megaStore.tsx index 1633c04..126f475 100644 --- a/src/state/megaStore.tsx +++ b/src/state/megaStore.tsx @@ -90,7 +90,8 @@ export const makeMegaStoreContext = () => { balanceView: localStorage.getItem("balanceView") || "sats", expiration_warning: undefined as | { expiresTimestamp: number; expiresMessage: string } - | undefined + | undefined, + expiration_warning_seen: false }); const actions = { @@ -235,45 +236,14 @@ export const makeMegaStoreContext = () => { | { expiresTimestamp: number; expiresMessage: string } | undefined = undefined; - try { - if (federations.length) { - const activeFederation = federations[0]; - const metadataUrl = activeFederation.meta_external_url; - console.log("federation metadata url", metadataUrl); - if (metadataUrl) { - const response = await fetch(metadataUrl); - if (response.ok) { - const metadata = await response.json(); - console.log( - "all federation metadata", - metadata - ); - const specificFederation = - metadata[activeFederation.federation_id]; - console.log( - "specific federation metadata", - specificFederation - ); - const expiresTimestamp = - specificFederation.popup_end_timestamp; - console.log( - "federation expires", - expiresTimestamp - ); - const expiresMessage = - specificFederation.popup_countdown_message; - expiration_warning = { - expiresTimestamp, - expiresMessage - }; - } - } + federations.forEach((f) => { + if (f.popup_countdown_message && f.popup_end_timestamp) { + expiration_warning = { + expiresTimestamp: f.popup_end_timestamp, + expiresMessage: f.popup_countdown_message + }; } - } catch (e) { - console.error("Error getting federation metadata", e); - } - - console.log("expiration_warning", expiration_warning); + }); setState({ wallet_loading: false, @@ -513,7 +483,21 @@ export const makeMegaStoreContext = () => { }, async refreshFederations() { const federations = await sw.list_federations(); - setState({ federations }); + + let expiration_warning: + | { expiresTimestamp: number; expiresMessage: string } + | undefined = undefined; + + federations.forEach((f) => { + if (f.popup_countdown_message && f.popup_end_timestamp) { + expiration_warning = { + expiresTimestamp: f.popup_end_timestamp, + expiresMessage: f.popup_countdown_message + }; + } + }); + + setState({ federations, expiration_warning }); }, cycleBalanceView() { if (state.balanceView === "sats") { @@ -556,7 +540,7 @@ export const makeMegaStoreContext = () => { }, // Only show the expiration warning once per session clearExpirationWarning() { - setState({ expiration_warning: undefined }); + setState({ expiration_warning_seen: true }); } }; diff --git a/src/workers/walletWorker.ts b/src/workers/walletWorker.ts index c75fdaf..6814d03 100644 --- a/src/workers/walletWorker.ts +++ b/src/workers/walletWorker.ts @@ -217,7 +217,6 @@ export async function get_balance(): Promise { */ export async function list_federations(): Promise { const federations = await wallet!.list_federations(); - console.log("list_federations", federations); return federations as MutinyFederationIdentity[]; } @@ -1382,6 +1381,7 @@ export async function delete_federation_recommendation( */ export async function get_federation_balances(): Promise { const balances = await wallet!.get_federation_balances(); + if (!balances) return { balances: [] } as unknown as FederationBalances; // PAIN // Have to rebuild the balances from the raw data, which is a bit of a pain const newBalances: FederationBalance[] = [];