diff --git a/src/components/KitchenSink.tsx b/src/components/KitchenSink.tsx index bb464ae..fab52bb 100644 --- a/src/components/KitchenSink.tsx +++ b/src/components/KitchenSink.tsx @@ -1,15 +1,50 @@ import { useMegaStore } from "~/state/megaStore"; -import { Card, Hr, SmallHeader, Button, InnerCard } from "~/components/layout"; +import { Card, Hr, SmallHeader, Button, InnerCard, VStack } from "~/components/layout"; import PeerConnectModal from "~/components/PeerConnectModal"; -import { For, Show, Suspense, createResource, createSignal } from "solid-js"; +import { For, Show, Suspense, createEffect, createResource, createSignal, onCleanup } from "solid-js"; import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm"; -import { TextField } from "@kobalte/core"; +import { Collapsible, TextField, toaster } from "@kobalte/core"; import mempoolTxUrl from "~/utils/mempoolTxUrl"; import eify from "~/utils/eify"; +import { ConfirmDialog } from "./Dialog"; +import { ToastItem, showToast } from "./Toaster"; // TODO: hopefully I don't have to maintain this type forever but I don't know how to pass it around otherwise type RefetchPeersType = (info?: unknown) => MutinyPeer[] | Promise | null | undefined +function PeerItem(props: { peer: MutinyPeer }) { + const [state, _] = useMegaStore() + + const handleDisconnectPeer = async () => { + const nodes = await state.node_manager?.list_nodes(); + const firstNode = nodes[0] as string || "" + + if (props.peer.is_connected) { + await state.node_manager?.disconnect_peer(firstNode, props.peer.pubkey); + } else { + await state.node_manager?.delete_peer(firstNode, props.peer.pubkey); + } + }; + + return ( + + +

+ {">"} {props.peer.alias ? props.peer.alias : props.peer.pubkey} +

+
+ + +
+                        {JSON.stringify(props.peer, null, 2)}
+                    
+ +
+
+
+ ) +} + function PeersList() { const [state, _] = useMegaStore() @@ -19,6 +54,16 @@ function PeersList() { const [peers, { refetch }] = createResource(getPeers); + createEffect(() => { + // refetch peers every 5 seconds + const interval = setTimeout(() => { + refetch(); + }, 5000); + onCleanup(() => { + clearInterval(interval); + }); + }) + return ( <> @@ -26,13 +71,13 @@ function PeersList() { {/* By wrapping this in a suspense I don't cause the page to jump to the top */} - No peers}> - {(peer) => ( -
-                            {JSON.stringify(peer, null, 2)}
-                        
- )} -
+ + No peers}> + {(peer) => ( + + )} + +
@@ -81,6 +126,54 @@ function ConnectPeer(props: { refetchPeers: RefetchPeersType }) { type RefetchChannelsListType = (info?: unknown) => MutinyChannel[] | Promise | null | undefined +function ChannelItem(props: { channel: MutinyChannel, network?: string }) { + const [state, _] = useMegaStore() + + const [confirmOpen, setConfirmOpen] = createSignal(false); + const [confirmLoading, setConfirmLoading] = createSignal(false); + + function handleCloseChannel() { + setConfirmOpen(true); + } + + async function confirmCloseChannel() { + setConfirmLoading(true); + try { + await state.node_manager?.close_channel(props.channel.outpoint as string) + } catch (e) { + console.error(e); + showToast(eify(e)); + } + setConfirmLoading(false); + setConfirmOpen(false); + } + + return ( + + +

+ {">"} {props.channel.peer} +

+
+ + +
+                        {JSON.stringify(props.channel, null, 2)}
+                    
+ + Mempool Link + + + +
+ setConfirmOpen(false)} loading={confirmLoading()}> +

Are you sure you want to close this channel?

+
+
+
+ ) +} + function ChannelsList() { const [state, _] = useMegaStore() @@ -90,6 +183,16 @@ function ChannelsList() { const [channels, { refetch }] = createResource(getChannels); + createEffect(() => { + // refetch channels every 5 seconds + const interval = setTimeout(() => { + refetch(); + }, 5000); + onCleanup(() => { + clearInterval(interval); + }); + }) + const network = state.node_manager?.get_network(); return ( @@ -101,14 +204,7 @@ function ChannelsList() { No channels}> {(channel) => ( - <> -
-                                {JSON.stringify(channel, null, 2)}
-                            
- - Mempool Link - - + )}
diff --git a/src/components/Sent.tsx b/src/components/Sent.tsx index 3cc3f89..d9d46ae 100644 --- a/src/components/Sent.tsx +++ b/src/components/Sent.tsx @@ -1,5 +1,6 @@ import { Dialog } from "@kobalte/core"; import { ButtonLink, SmallHeader } from "~/components/layout"; +import close from "~/assets/icons/close.svg"; const OVERLAY = "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm" const DIALOG_POSITIONER = "fixed inset-0 z-50 flex items-center justify-center" @@ -12,14 +13,14 @@ export function SentModal(props: { details?: { nice: string } }) {
-
+
Sent! - - X + + Close
diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index 09ed47f..0e356f7 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -10,7 +10,7 @@ const SmallHeader: ParentComponent<{ class?: string }> = (props) => { const Card: ParentComponent<{ title?: string }> = (props) => { return ( -
+
{props.title && {props.title}} {props.children}
diff --git a/src/routes/Receive.tsx b/src/routes/Receive.tsx index 61ecbef..ee7c9bc 100644 --- a/src/routes/Receive.tsx +++ b/src/routes/Receive.tsx @@ -229,7 +229,7 @@ export default function Receive() { { if (!open) clearAll() }}>
- party + party
@@ -237,7 +237,7 @@ export default function Receive() { { if (!open) clearAll() }}>