diff --git a/src/assets/icons/down.svg b/src/assets/icons/down.svg new file mode 100644 index 0000000..f8c96ba --- /dev/null +++ b/src/assets/icons/down.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/DetailsModal.tsx b/src/components/DetailsModal.tsx index a3f8c17..b5ad802 100644 --- a/src/components/DetailsModal.tsx +++ b/src/components/DetailsModal.tsx @@ -149,10 +149,10 @@ function OnchainHeader(props: { ); } -const KeyValue: ParentComponent<{ key: string }> = (props) => { +export const KeyValue: ParentComponent<{ key: string }> = (props) => { return (
  • - + {props.key} {props.children} diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index 1e6baae..981c323 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -1,20 +1,23 @@ import { JSX, + Match, ParentComponent, Show, Suspense, + Switch, createResource, createSignal } from "solid-js"; import Linkify from "./Linkify"; import { Button, ButtonLink } from "./Button"; -import { Dialog, Checkbox as KCheckbox, Separator } from "@kobalte/core"; +import { Collapsible, Checkbox as KCheckbox, Dialog, Separator } from "@kobalte/core"; import { useMegaStore } from "~/state/megaStore"; import check from "~/assets/icons/check.svg"; import { MutinyTagItem } from "~/utils/tags"; import { generateGradient } from "~/utils/gradientHash"; import close from "~/assets/icons/close.svg"; import { A } from "solid-start"; +import down from "~/assets/icons/down.svg"; export { Button, ButtonLink, Linkify }; @@ -75,6 +78,39 @@ export const SettingsCard: ParentComponent<{ ); }; +export const Collapser: ParentComponent<{ + title: string; + defaultOpen?: boolean; + activityLight?: "on" | "off"; +}> = (props) => { + return ( + + +
    + + +
    + + +
    + + + {props.title} +
    + expand / collapse + + + {props.children} + + + ); +}; + + export const SafeArea: ParentComponent = (props) => { return (
    diff --git a/src/routes/settings/Connections.tsx b/src/routes/settings/Connections.tsx index 50dbb93..b127946 100644 --- a/src/routes/settings/Connections.tsx +++ b/src/routes/settings/Connections.tsx @@ -1,39 +1,171 @@ -import { Show, createMemo } from "solid-js"; +import { NwcProfile } from "@mutinywallet/mutiny-wasm"; +import { For, Show, createResource, createSignal } from "solid-js"; import { QRCodeSVG } from "solid-qr-code"; +import { KeyValue, MiniStringShower } from "~/components/DetailsModal"; +import { InfoBox } from "~/components/InfoBox"; import NavBar from "~/components/NavBar"; import { ShareCard } from "~/components/ShareCard"; import { Button, + Collapser, DefaultMain, LargeHeader, MutinyWalletGuard, NiceP, - SafeArea + SafeArea, + SettingsCard, + SimpleDialog, + VStack } from "~/components/layout"; import { BackLink } from "~/components/layout/BackLink"; +import { TextField } from "~/components/layout/TextField"; import { useMegaStore } from "~/state/megaStore"; +import eify from "~/utils/eify"; -export default function Connections() { - const [state, actions] = useMegaStore(); +function Nwc() { + const [state, _actions] = useMegaStore(); - const connectionURI = createMemo(() => { - if (state.nwc_enabled) { - return state.mutiny_wallet?.get_nwc_uri(); + const [nwcProfiles, { refetch }] = createResource(async () => { + try { + const profiles: NwcProfile[] = + await state.mutiny_wallet?.get_nwc_profiles(); + + console.log("profiles:", profiles); + + return profiles; + } catch (e) { + console.error(e); } }); - const toggleNwc = async () => { - if (state.nwc_enabled) { - actions.setNwc(false); - window.location.reload(); - } else { - actions.setNwc(true); - const nodes = await state.mutiny_wallet?.list_nodes(); - const firstNode = (nodes[0] as string) || ""; - await state.mutiny_wallet?.start_nostr_wallet_connect(firstNode); - } - }; + const [dialogOpen, setDialogOpen] = createSignal(false); + const [formName, setFormName] = createSignal(""); + const [createLoading, setCreateLoading] = createSignal(false); + const [error, setError] = createSignal(""); + async function createConnection() { + try { + setError(""); + setCreateLoading(true); + + if (formName() === "") { + setError("Name cannot be empty"); + return; + } + const profile = await state.mutiny_wallet?.create_nwc_profile( + formName(), + 10000n + ); + + if (!profile) { + setError("Failed to create Wallet Connection"); + return; + } else { + refetch(); + } + + setFormName(""); + setDialogOpen(false); + } catch (e) { + setError(eify(e).message); + console.error(e); + } finally { + setCreateLoading(false); + } + } + + async function toggleEnabled(profile: NwcProfile) { + try { + await state.mutiny_wallet?.edit_nwc_profile({ + ...profile, + enabled: !profile.enabled + }); + refetch(); + } catch (e) { + console.error(e); + } + } + + // this is because the TextField component has a bunch of required props + function noop() { + // do nothing + return; + } + + return ( + + + 0}> + + + {(profile) => ( + + + + + + +
    + +
    + + +
    +
    + )} +
    +
    +
    + +
    + setFormName(e.currentTarget.value)} + error={""} + onBlur={noop} + onChange={noop} + placeholder="My favorite nostr client..." + /> + + {error()} + +
    + + +
    +
    + ); +} + +export default function Connections() { return ( @@ -41,24 +173,10 @@ export default function Connections() { Wallet Connections - Authorize Mutiny Wallet with external services like - Nostr clients. + Authorize external services to request payments from + your wallet. Pairs great with Nostr clients. - - - -
    - -
    - -
    +
    diff --git a/src/state/megaStore.tsx b/src/state/megaStore.tsx index 15b5aab..d6a41ef 100644 --- a/src/state/megaStore.tsx +++ b/src/state/megaStore.tsx @@ -56,7 +56,6 @@ export type MegaStore = [ dismissRestorePrompt(): void; setHasBackedUp(): void; listTags(): Promise; - setNwc(enabled: boolean): void; syncActivity(): Promise; checkBrowserCompat(): Promise; }