diff --git a/src/assets/icons/forward.svg b/src/assets/icons/forward.svg new file mode 100644 index 0000000..d632e06 --- /dev/null +++ b/src/assets/icons/forward.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/BalanceBox.tsx b/src/components/BalanceBox.tsx index 6373adf..1876ceb 100644 --- a/src/components/BalanceBox.tsx +++ b/src/components/BalanceBox.tsx @@ -1,5 +1,5 @@ import { Show } from "solid-js"; -import { Button, FancyCard, Hr, Indicator } from "~/components/layout"; +import { Button, FancyCard, Indicator } from "~/components/layout"; import { useMegaStore } from "~/state/megaStore"; import { Amount } from "./Amount"; import { A, useNavigate } from "solid-start"; diff --git a/src/components/KitchenSink.tsx b/src/components/KitchenSink.tsx index c784eeb..ca2f6fd 100644 --- a/src/components/KitchenSink.tsx +++ b/src/components/KitchenSink.tsx @@ -1,6 +1,5 @@ import { useMegaStore } from "~/state/megaStore"; import { Hr, Button, InnerCard, VStack } from "~/components/layout"; -import NostrWalletConnectModal from "~/components/NostrWalletConnectModal"; import { For, Match, @@ -16,10 +15,8 @@ import mempoolTxUrl from "~/utils/mempoolTxUrl"; import eify from "~/utils/eify"; import { ConfirmDialog } from "~/components/Dialog"; import { showToast } from "~/components/Toaster"; -import { ImportExport } from "~/components/ImportExport"; import { Network } from "~/logic/mutinyWalletSetup"; import { ExternalLink } from "./layout/ExternalLink"; -import { Logs } from "./Logs"; import { Restart } from "./Restart"; import { ResyncOnchain } from "./ResyncOnchain"; import { MiniStringShower } from "./DetailsModal"; @@ -399,53 +396,6 @@ function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) { ); } -function LnUrlAuth() { - const [state, _] = useMegaStore(); - - const [value, setValue] = createSignal(""); - - const onSubmit = async (e: SubmitEvent) => { - e.preventDefault(); - - const lnurl = value().trim(); - await state.mutiny_wallet?.lnurl_auth(0, lnurl); - - setValue(""); - }; - - return ( - -
- - - LNURL Auth - - - - Expecting something like LNURL... - - - -
-
- ); -} - function ListNodes() { const [state, _] = useMegaStore(); @@ -470,24 +420,16 @@ function ListNodes() { export default function KitchenSink() { return ( <> - -

- -


- -


- -
); } diff --git a/src/components/LiquidityMonitor.tsx b/src/components/LiquidityMonitor.tsx deleted file mode 100644 index e3c4240..0000000 --- a/src/components/LiquidityMonitor.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { Show, createResource } from "solid-js"; -import { useMegaStore } from "~/state/megaStore"; -import { Card, NiceP, SmallHeader, TinyText, VStack } from "./layout"; -import { AmountSmall } from "./Amount"; - -function BalanceBar(props: { inbound: number; outbound: number }) { - return ( - -
- Outbound - Inbound -
-
-
- -
-
- -
-
-
- ); -} - -export function LiquidityMonitor() { - const [state, _actions] = useMegaStore(); - - const [channelInfo] = createResource(async () => { - try { - const channels = await state.mutiny_wallet?.list_channels(); - let inbound = 0n; - - for (const channel of channels) { - inbound = - inbound + - BigInt(channel.size) - - BigInt(channel.balance + channel.reserve); - } - - return { inbound, channelCount: channels?.length }; - } catch (e) { - console.error(e); - return { inbound: 0, channelCount: 0 }; - } - }); - - return ( - - - - You have {channelInfo()?.channelCount} lightning{" "} - {channelInfo()?.channelCount === 1 ? "channel" : "channels"} - . - {" "} - - - Outbound is the amount of money you can spend on lightning. - Inbound is the amount you can receive without incurring a - lightning service fee. - - - - ); -} diff --git a/src/components/NostrWalletConnectModal.tsx b/src/components/NostrWalletConnectModal.tsx deleted file mode 100644 index c54d1eb..0000000 --- a/src/components/NostrWalletConnectModal.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { QRCodeSVG } from "solid-qr-code"; -import { As, Dialog } from "@kobalte/core"; -import { Button, Card, InnerCard, NiceP } from "~/components/layout"; -import { useMegaStore } from "~/state/megaStore"; -import { createResource, Show } from "solid-js"; - -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"; -const DIALOG_CONTENT = - "w-[80vw] max-w-[400px] max-h-[100dvh] overflow-y-auto disable-scrollbars p-4 bg-gray/50 backdrop-blur-md shadow-xl rounded-xl border border-white/10"; -const SMALL_HEADER = "text-sm font-semibold uppercase"; - -export default function NostrWalletConnectModal() { - const [state, actions] = useMegaStore(); - - const getConnectionURI = () => { - if (state.mutiny_wallet) { - return state.mutiny_wallet.get_nwc_uri(); - } else { - return undefined; - } - }; - - const [connectionURI] = createResource(getConnectionURI); - - 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); - } - }; - - // TODO: a lot of this markup is probably reusable as a "Modal" component - return ( - - Test out some nostr stuff. -
- - - Show Nostr Wallet Connect URI - - - -
- -
- - Nostr Wallet Connect - - - X - -
- - -
- -
- - - {connectionURI() || ""} - - -
- -
-
-
-
-
- - ); -} diff --git a/src/components/OnboardWarning.tsx b/src/components/OnboardWarning.tsx index 6546ae0..bf61b68 100644 --- a/src/components/OnboardWarning.tsx +++ b/src/components/OnboardWarning.tsx @@ -83,7 +83,7 @@ export function OnboardWarning() { intent="blue" layout="xs" class="self-auto" - href="/backup" + href="/settings/backup" > Backup diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx index ecb2e56..632f776 100644 --- a/src/components/layout/index.tsx +++ b/src/components/layout/index.tsx @@ -60,6 +60,22 @@ export const FancyCard: ParentComponent<{ ); }; +export const SettingsCard: ParentComponent<{ + title?: string; +}> = (props) => { + return ( + +
+ {props.title} +
+
+ {props.children} +
+
+ ); +}; + + export const SafeArea: ParentComponent = (props) => { return (
diff --git a/src/routes/Activity.tsx b/src/routes/Activity.tsx index 5506e1c..f36c6c6 100644 --- a/src/routes/Activity.tsx +++ b/src/routes/Activity.tsx @@ -12,8 +12,6 @@ import { } from "~/components/layout"; import { BackLink } from "~/components/layout/BackLink"; import { CombinedActivity } from "~/components/Activity"; -import { A } from "solid-start"; -import settings from "~/assets/icons/settings.svg"; import { Tabs } from "@kobalte/core"; import { gradientsPerContact } from "~/utils/gradientHash"; import { ContactEditor } from "~/components/ContactEditor"; diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx deleted file mode 100644 index 8bf5cb4..0000000 --- a/src/routes/Settings.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { - ButtonLink, - Card, - DefaultMain, - LargeHeader, - MutinyWalletGuard, - NiceP, - SafeArea, - VStack -} from "~/components/layout"; -import { BackLink } from "~/components/layout/BackLink"; -import NavBar from "~/components/NavBar"; -import { SeedWords } from "~/components/SeedWords"; -import { SettingsStringsEditor } from "~/components/SettingsStringsEditor"; -import { useMegaStore } from "~/state/megaStore"; -import { LiquidityMonitor } from "~/components/LiquidityMonitor"; -import { A } from "solid-start"; -import { Suspense } from "solid-js"; - -export default function Settings() { - const [store, _actions] = useMegaStore(); - - return ( - - - - - Settings - - - - - - These 12 words allow you to recover your - on-chain funds in case you lose your device - or clear your browser storage. - - - - - - - - Having some serious problems with your wallet? - Check out the{" "} - emergency kit. - - - - - - We have some not-very-pretty debug tools we - use to test the wallet. Use wisely! - -
- - Secret Debug Tools - -
-
-
-
-
- -
-
- ); -} diff --git a/src/routes/Admin.tsx b/src/routes/settings/Admin.tsx similarity index 96% rename from src/routes/Admin.tsx rename to src/routes/settings/Admin.tsx index 78aa1a1..7307b37 100644 --- a/src/routes/Admin.tsx +++ b/src/routes/settings/Admin.tsx @@ -35,7 +35,7 @@ export default function Admin() {
- + ); diff --git a/src/routes/Backup.tsx b/src/routes/settings/Backup.tsx similarity index 95% rename from src/routes/Backup.tsx rename to src/routes/settings/Backup.tsx index 6b21b01..32726c4 100644 --- a/src/routes/Backup.tsx +++ b/src/routes/settings/Backup.tsx @@ -49,7 +49,7 @@ function Quiz(props: { setHasCheckedAll: (hasChecked: boolean) => void }) { ); } -export default function App() { +export default function Backup() { const [store, actions] = useMegaStore(); const navigate = useNavigate(); @@ -65,7 +65,7 @@ export default function App() { - + Backup @@ -98,7 +98,7 @@ export default function App() { - + ); diff --git a/src/routes/settings/Channels.tsx b/src/routes/settings/Channels.tsx new file mode 100644 index 0000000..ede3f96 --- /dev/null +++ b/src/routes/settings/Channels.tsx @@ -0,0 +1,115 @@ +import { Match, Switch, createResource } from "solid-js"; +import { useMegaStore } from "~/state/megaStore"; +import { + Card, + DefaultMain, + LargeHeader, + MutinyWalletGuard, + NiceP, + SafeArea, + SmallHeader, + TinyText, + VStack +} from "~/components/layout"; +import { AmountSmall } from "~/components/Amount"; +import { BackLink } from "~/components/layout/BackLink"; +import NavBar from "~/components/NavBar"; + +function BalanceBar(props: { inbound: number; outbound: number }) { + return ( + +
+ Outbound + Inbound +
+
+
+ +
+
+ +
+
+
+ ); +} + +export function LiquidityMonitor() { + const [state, _actions] = useMegaStore(); + + const [channelInfo] = createResource(async () => { + try { + const channels = await state.mutiny_wallet?.list_channels(); + let inbound = 0n; + + for (const channel of channels) { + inbound = + inbound + + BigInt(channel.size) - + BigInt(channel.balance + channel.reserve); + } + + return { inbound, channelCount: channels?.length }; + } catch (e) { + console.error(e); + return { inbound: 0, channelCount: 0 }; + } + }); + + return ( + + + + + You have {channelInfo()?.channelCount} lightning{" "} + {channelInfo()?.channelCount === 1 + ? "channel" + : "channels"} + . + {" "} + + + Outbound is the amount of money you can spend on + lightning. Inbound is the amount you can receive without + incurring a lightning service fee. + + + + + + It looks like you don't have any channels yet. To get + started, receive some sats over lightning, or swap some + on-chain funds into a channel. Get your hands dirty! + + + + ); +} + +export default function Channels() { + return ( + + + + + Lightning Channels + + + + + + ); +} diff --git a/src/routes/settings/Connections.tsx b/src/routes/settings/Connections.tsx new file mode 100644 index 0000000..50dbb93 --- /dev/null +++ b/src/routes/settings/Connections.tsx @@ -0,0 +1,68 @@ +import { Show, createMemo } from "solid-js"; +import { QRCodeSVG } from "solid-qr-code"; +import NavBar from "~/components/NavBar"; +import { ShareCard } from "~/components/ShareCard"; +import { + Button, + DefaultMain, + LargeHeader, + MutinyWalletGuard, + NiceP, + SafeArea +} from "~/components/layout"; +import { BackLink } from "~/components/layout/BackLink"; +import { useMegaStore } from "~/state/megaStore"; + +export default function Connections() { + const [state, actions] = useMegaStore(); + + const connectionURI = createMemo(() => { + if (state.nwc_enabled) { + return state.mutiny_wallet?.get_nwc_uri(); + } + }); + + 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); + } + }; + + return ( + + + + + Wallet Connections + + Authorize Mutiny Wallet with external services like + Nostr clients. + + + + +
+ +
+ +
+
+ + + + + ); +} diff --git a/src/routes/EmergencyKit.tsx b/src/routes/settings/EmergencyKit.tsx similarity index 93% rename from src/routes/EmergencyKit.tsx rename to src/routes/settings/EmergencyKit.tsx index 0d074da..e9a6a71 100644 --- a/src/routes/EmergencyKit.tsx +++ b/src/routes/settings/EmergencyKit.tsx @@ -17,7 +17,7 @@ export default function EmergencyKit() { return ( - + Emergency Kit @@ -39,7 +39,7 @@ export default function EmergencyKit() {
- +
); } diff --git a/src/routes/settings/LnUrlAuth.tsx b/src/routes/settings/LnUrlAuth.tsx new file mode 100644 index 0000000..51b4fbd --- /dev/null +++ b/src/routes/settings/LnUrlAuth.tsx @@ -0,0 +1,69 @@ +import { TextField } from "@kobalte/core"; +import { createSignal } from "solid-js"; +import NavBar from "~/components/NavBar"; +import { + Button, + DefaultMain, + InnerCard, + LargeHeader, + MutinyWalletGuard, + SafeArea +} from "~/components/layout"; +import { BackLink } from "~/components/layout/BackLink"; +import { useMegaStore } from "~/state/megaStore"; + +export default function LnUrlAuth() { + const [state, _] = useMegaStore(); + + const [value, setValue] = createSignal(""); + + const onSubmit = async (e: SubmitEvent) => { + e.preventDefault(); + + const lnurl = value().trim(); + await state.mutiny_wallet?.lnurl_auth(0, lnurl); + + setValue(""); + }; + + return ( + + + + + LNURL Auth + +
+ + + LNURL Auth + + + + Expecting something like LNURL... + + + +
+
+
+ +
+
+ ); +} diff --git a/src/components/SettingsStringsEditor.tsx b/src/routes/settings/Servers.tsx similarity index 83% rename from src/components/SettingsStringsEditor.tsx rename to src/routes/settings/Servers.tsx index 480fc6e..b6d9d21 100644 --- a/src/components/SettingsStringsEditor.tsx +++ b/src/routes/settings/Servers.tsx @@ -5,10 +5,20 @@ import { getExistingSettings, setAndGetMutinySettings } from "~/logic/mutinyWalletSetup"; -import { Button, Card, NiceP } from "~/components/layout"; -import { showToast } from "./Toaster"; +import { + Button, + Card, + DefaultMain, + LargeHeader, + MutinyWalletGuard, + NiceP, + SafeArea +} from "~/components/layout"; +import { showToast } from "~/components/Toaster"; import eify from "~/utils/eify"; -import { ExternalLink } from "./layout/ExternalLink"; +import { ExternalLink } from "~/components/layout/ExternalLink"; +import { BackLink } from "~/components/layout/BackLink"; +import NavBar from "~/components/NavBar"; export function SettingsStringsEditor() { const existingSettings = getExistingSettings(); @@ -107,3 +117,18 @@ export function SettingsStringsEditor() { ); } + +export default function Servers() { + return ( + + + + + Backup + + + + + + ); +} diff --git a/src/routes/settings/index.tsx b/src/routes/settings/index.tsx new file mode 100644 index 0000000..c09e3bb --- /dev/null +++ b/src/routes/settings/index.tsx @@ -0,0 +1,118 @@ +import { + DefaultMain, + LargeHeader, + MutinyWalletGuard, + SafeArea, + SettingsCard, + VStack +} from "~/components/layout"; +import { BackLink } from "~/components/layout/BackLink"; +import NavBar from "~/components/NavBar"; +import { A } from "solid-start"; +import { For, Show } from "solid-js"; +import forward from "~/assets/icons/forward.svg"; + +function SettingsLinkList(props: { + header: string; + links: { + href: string; + text: string; + caption?: string; + accent?: "red" | "green"; + }[]; +}) { + return ( + + + {(link) => ( + +
+ + {link.text} + + go +
+ +
+ {link.caption} +
+
+
+ )} +
+
+ ); +} + +export default function Settings() { + return ( + + + + Settings + + + + + + + + + ); +} diff --git a/tailwind.config.cjs b/tailwind.config.cjs index d567037..794677f 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -29,8 +29,10 @@ module.exports = { "m-red": "hsla(343, 92%, 54%, 1)", "m-red-dark": "hsla(343, 92%, 44%, 1)", "sidebar-gray": "hsla(222, 15%, 7%, 1)", + "m-grey-400": "hsla(0, 0%, 64%, 1)", "m-grey-800": "hsla(0, 0%, 12%, 1)", - "m-grey-750": "hsla(0, 0%, 17%, 1)" + "m-grey-750": "hsla(0, 0%, 17%, 1)", + "m-grey-900": "hsla(0, 0%, 9%, 1)" }, backgroundImage: { "fade-to-blue":