Skip to content

Commit

Permalink
show federation popups
Browse files Browse the repository at this point in the history
  • Loading branch information
futurepaul committed May 8, 2024
1 parent fa9b0c0 commit de028bc
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 94 deletions.
3 changes: 2 additions & 1 deletion public/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,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",
Expand Down
40 changes: 3 additions & 37 deletions src/components/Activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
createSignal,
For,
Match,
onMount,
Show,
Suspense,
Switch
Expand All @@ -19,6 +18,7 @@ import {
Button,
ButtonCard,
ContactButton,
FederationPopup,
LoadingShimmer,
NiceP,
SimpleDialog
Expand Down Expand Up @@ -375,7 +375,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);
Expand Down Expand Up @@ -418,17 +418,6 @@ export function CombinedActivity() {

const [newContact, setNewContact] = createSignal<PseudoContact>();

const [
showFederationExpirationWarning,
setShowFederationExpirationWarning
] = createSignal(false);

onMount(() => {
if (state.expiration_warning) {
setShowFederationExpirationWarning(true);
}
});

return (
<>
<Show when={detailsId() && detailsKind()}>
Expand All @@ -447,30 +436,7 @@ export function CombinedActivity() {
</Show>
<Suspense fallback={<LoadingShimmer />}>
<Show when={state.expiration_warning}>
<SimpleDialog
title={i18n.t("activity.federation_message")}
open={showFederationExpirationWarning()}
setOpen={(open: boolean) => {
if (!open) {
setShowFederationExpirationWarning(false);
actions.clearExpirationWarning();
}
}}
>
<NiceP>
{state.expiration_warning?.expiresMessage}
</NiceP>
<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>
</SimpleDialog>
<FederationPopup />
</Show>
<Show when={!state.has_backed_up}>
<ButtonCard
Expand Down
45 changes: 45 additions & 0 deletions src/components/FederationPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useNavigate } from "@solidjs/router";
import { Users } from "lucide-solid";
import { createSignal } from "solid-js";

import { ButtonCard, NiceP, SimpleDialog } from "~/components/layout";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";

export function FederationPopup() {
const [state, actions, _sw] = useMegaStore();
const [
showFederationExpirationWarning,
setShowFederationExpirationWarning
] = createSignal(!state.expiration_warning_seen);

const i18n = useI18n();
const navigate = useNavigate();

return (
<SimpleDialog
title={i18n.t("activity.federation_message")}
open={showFederationExpirationWarning()}
setOpen={(open: boolean) => {
if (!open) {
setShowFederationExpirationWarning(false);
actions.clearExpirationWarning();
}
}}
>
<NiceP>{state.expiration_warning?.expiresMessage}</NiceP>
<ButtonCard
onClick={() => {
actions.clearExpirationWarning();
setShowFederationExpirationWarning(false);
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>
</SimpleDialog>
);
}
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ export * from "./EditProfileForm";
export * from "./ImportNsecForm";
export * from "./LightningAddressShower";
export * from "./FederationInviteShower";
export * from "./FederationPopup";
6 changes: 5 additions & 1 deletion src/routes/Transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,11 @@ export function Transfer() {
</Match>
</Switch>
</SuccessModal>
<BackLink href="/settings/federations" />
<BackLink
title={i18n.t("common.back")}
href="/settings/federations"
showOnDesktop
/>
<LargeHeader>{i18n.t("transfer.title")}</LargeHeader>
<div class="flex flex-1 flex-col justify-between gap-2">
<div class="flex-1" />
Expand Down
49 changes: 33 additions & 16 deletions src/routes/settings/ManageFederations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
ExternalLink,
FancyCard,
FederationInviteShower,
FederationPopup,
InfoBox,
KeyValue,
LabelCircle,
Expand All @@ -40,6 +41,7 @@ import {
NavBar,
NiceP,
showToast,
SimpleDialog,
SubtleButton,
TextField,
VStack
Expand All @@ -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 = {
Expand Down Expand Up @@ -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<Error>();
const [success, setSuccess] = createSignal("");
Expand Down Expand Up @@ -181,6 +185,9 @@ export function AddFederationForm(props: {

return (
<div class="flex w-full flex-col gap-4">
<Show when={state.expiration_warning}>
<FederationPopup />
</Show>
<Show when={!props.setup && !props.browseOnly}>
<MediumHeader>
{i18n.t("settings.manage_federations.manual")}
Expand Down Expand Up @@ -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);
Expand All @@ -457,7 +471,6 @@ function FederationListItem(props: {
<>
<FancyCard>
<VStack>
{/* <pre>{JSON.stringify(props.fed, null, 2)}</pre> */}
<Show when={props.fed.federation_name}>
<header class={`font-semibold`}>
{props.fed.federation_name}
Expand All @@ -466,6 +479,19 @@ function FederationListItem(props: {
<Show when={props.fed.welcome_message}>
<p>{props.fed.welcome_message}</p>
</Show>
<SimpleDialog
title={i18n.t(
"settings.manage_federations.transfer_funds"
)}
open={transferDialogOpen()}
setOpen={setTransferDialogOpen}
>
<NiceP>
{i18n.t(
"settings.manage_federations.transfer_funds_message"
)}
</NiceP>
</SimpleDialog>
<Show when={props.balance !== undefined}>
<KeyValue
key={i18n.t("activity.transaction_details.balance")}
Expand Down Expand Up @@ -499,19 +525,10 @@ function FederationListItem(props: {
inviteCode={props.fed.invite_code}
/>
</KeyValue>
<Show
when={
state.federations?.length &&
state.federations.length === 2
}
>
<SubtleButton onClick={transferFunds}>
<ArrowLeftRight class="h-4 w-4" />
{i18n.t(
"settings.manage_federations.transfer_funds"
)}
</SubtleButton>
</Show>
<SubtleButton onClick={transferFunds}>
<ArrowLeftRight class="h-4 w-4" />
{i18n.t("settings.manage_federations.transfer_funds")}
</SubtleButton>
<Suspense>
<RecommendButton fed={props.fed} />
</Suspense>
Expand Down
64 changes: 25 additions & 39 deletions src/state/megaStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -235,43 +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);

Expand Down Expand Up @@ -513,7 +485,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") {
Expand Down Expand Up @@ -556,7 +542,7 @@ export const makeMegaStoreContext = () => {
},
// Only show the expiration warning once per session
clearExpirationWarning() {
setState({ expiration_warning: undefined });
setState({ expiration_warning_seen: true });
}
};

Expand Down
1 change: 1 addition & 0 deletions src/workers/walletWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,7 @@ export async function delete_federation_recommendation(
*/
export async function get_federation_balances(): Promise<FederationBalances> {
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[] = [];
Expand Down

0 comments on commit de028bc

Please sign in to comment.