diff --git a/src/assets/plus.png b/src/assets/plus.png index f588f272..5225e14b 100644 Binary files a/src/assets/plus.png and b/src/assets/plus.png differ diff --git a/src/components/Activity.tsx b/src/components/Activity.tsx index 75542b96..8b46be55 100644 --- a/src/components/Activity.tsx +++ b/src/components/Activity.tsx @@ -5,7 +5,6 @@ import { createEffect, createSignal, For, Match, Show, Switch } from "solid-js"; import shuffle from "~/assets/icons/shuffle.svg"; import { ActivityDetailsModal, - ActivityItem, Card, HackActivityType, NiceP @@ -44,11 +43,16 @@ export function UnifiedActivityItem(props: { return props.item.contacts[0]; }; + // TODO: figure out what other shit we should filter out const message = () => { - if (props.item.labels.length === 0) { + const filtered = props.item.labels.filter( + (l) => l !== "SWAP" && !l.startsWith("LN Channel:") + ); + if (filtered.length === 0) { return undefined; } - return props.item.labels[0]; + + return filtered[0]; }; const shouldShowShuffle = () => { @@ -69,6 +73,13 @@ export function UnifiedActivityItem(props: { if (props.item.labels.length > 0 && props.item.labels[0] === "SWAP") { return "swapped to"; } + if ( + props.item.labels.length > 0 && + props.item.labels[0] === "Swept Force Close" + ) { + return undefined; + } + return "sent"; }; @@ -104,29 +115,34 @@ export function UnifiedActivityItem(props: { return ( <> - + {/*
{JSON.stringify(props.item, null, 2)}
*/} // Don't forget to back up your seed words! - props.limit}> -
- - {(activityItem) => ( - - )} - -
-
= 0}>
@@ -244,15 +248,6 @@ export function CombinedActivity(props: { limit?: number }) {
- {/* Only show on the home screen */} - - - {i18n.t("activity.view_all")} - - ); } diff --git a/src/components/ActivityDetailsModal.tsx b/src/components/ActivityDetailsModal.tsx index 35edf512..50d31498 100644 --- a/src/components/ActivityDetailsModal.tsx +++ b/src/components/ActivityDetailsModal.tsx @@ -217,11 +217,13 @@ function LightningDetails(props: { info: MutinyInvoice; tags?: TagItem }) { - - {props.info.paid - ? i18n.t("activity.transaction_details.paid") - : i18n.t("activity.transaction_details.unpaid")} - + + + i18n.t("activity.transaction_details.unpaid") + + @@ -235,12 +237,7 @@ function LightningDetails(props: { info: MutinyInvoice; tags?: TagItem }) { - - - - + - - - - -
{/* Have to do all these shenanigans because css / html is hard */} diff --git a/src/components/ContactButton.tsx b/src/components/ContactButton.tsx index 951b8b0e..02c6d1c4 100644 --- a/src/components/ContactButton.tsx +++ b/src/components/ContactButton.tsx @@ -8,13 +8,12 @@ export function ContactButton(props: { onClick: () => void; }) { return ( -
+
+ ); } diff --git a/src/components/ContactViewer.tsx b/src/components/ContactViewer.tsx index 2592c7ae..c68eb401 100644 --- a/src/components/ContactViewer.tsx +++ b/src/components/ContactViewer.tsx @@ -11,7 +11,6 @@ import { MiniStringShower, showToast, SimpleDialog, - SmallHeader, VStack } from "~/components"; import { useI18n } from "~/i18n/context"; diff --git a/src/components/Fab.tsx b/src/components/Fab.tsx index 7e87c1d7..ad377b8c 100644 --- a/src/components/Fab.tsx +++ b/src/components/Fab.tsx @@ -33,10 +33,10 @@ export function FabMenu(props: { return (
-
+
{/* TITLE TEXT */} -

- - {props.primaryName} - - {` ${props.verb} `} - - {props.secondaryName} - -

+ +

+ + {props.primaryName} + + {` ${props.verb} `} + + {props.secondaryName} + +

+
{/* AMOUNT */} @@ -102,11 +104,11 @@ export function GenericItem(props: { {/* DATE WITH SECOND AVATAR */}
- + {/* */} - + {/* */} @@ -151,19 +153,19 @@ export function GenericItem(props: { >
diff --git a/src/components/NostrActivity.tsx b/src/components/NostrActivity.tsx index 723f42f8..3d5f1996 100644 --- a/src/components/NostrActivity.tsx +++ b/src/components/NostrActivity.tsx @@ -9,9 +9,8 @@ import { Switch } from "solid-js"; -import avatar from "~/assets/generic-avatar.jpg"; import rightArrow from "~/assets/icons/right-arrow.svg"; -import { AmountSats, VStack } from "~/components"; +import { AmountSats } from "~/components"; import { useI18n } from "~/i18n/context"; import { useMegaStore } from "~/state/megaStore"; import { fetchZaps, getPrimalImageUrl, hexpubFromNpub } from "~/utils"; @@ -153,7 +152,9 @@ export function NostrActivity() { amount={zap.amount_sats} message={zap.content ? zap.content : undefined} date={timeAgo(zap.timestamp, data.latest?.until)} - public={zap.kind === "public"} + visibility={ + zap.kind === "public" ? "public" : "private" + } genericAvatar={ zap.kind === "anonymous" || zap.kind === "private" diff --git a/src/components/PendingNwc.tsx b/src/components/PendingNwc.tsx index f28aa823..9bcdf931 100644 --- a/src/components/PendingNwc.tsx +++ b/src/components/PendingNwc.tsx @@ -81,11 +81,13 @@ export function PendingNwc() { { storage: createDeepSignal } ); - const [paying, setPaying] = createSignal(""); + // const [paying, setPaying] = createSignal(""); + const [payList, setPayList] = createSignal([]); async function payItem(item: PendingItem) { try { - setPaying(item.id); + // setPaying(item.id); + setPayList([...payList(), item.id]); await state.mutiny_wallet?.approve_invoice(item.id); await vibrateSuccess(); } catch (e) { @@ -104,7 +106,7 @@ export function PendingNwc() { console.error(e); } } finally { - setPaying(""); + setPayList(payList().filter((id) => id !== item.id)); refetch(); } } @@ -130,13 +132,13 @@ export function PendingNwc() { async function rejectItem(item: PendingItem) { try { - setPaying(item.id); + setPayList([...payList(), item.id]); await state.mutiny_wallet?.deny_invoice(item.id); } catch (e) { setError(eify(e)); console.error(e); } finally { - setPaying(""); + setPayList(payList().filter((id) => id !== item.id)); refetch(); } } @@ -207,7 +209,9 @@ export function PendingNwc() { primaryName={pendingItem.name_of_connection} approveAction={() => payItem(pendingItem)} rejectAction={() => rejectItem(pendingItem)} - shouldSpinny={paying() === pendingItem.id} + shouldSpinny={payList().includes( + pendingItem.id + )} /> )} diff --git a/src/components/ReceiveWarnings.tsx b/src/components/ReceiveWarnings.tsx index aa4d2dd1..835477eb 100644 --- a/src/components/ReceiveWarnings.tsx +++ b/src/components/ReceiveWarnings.tsx @@ -7,7 +7,7 @@ import { useMegaStore } from "~/state/megaStore"; export function ReceiveWarnings(props: { amountSats: string | bigint; - from_fedi_to_ln: boolean; + from_fedi_to_ln?: boolean; }) { const i18n = useI18n(); const [state, _actions] = useMegaStore(); @@ -29,7 +29,7 @@ export function ReceiveWarnings(props: { }); const warningText = () => { - if (state.federations?.length !== 0 && props.from_fedi_to_ln != true) { + if (state.federations?.length !== 0 && props.from_fedi_to_ln !== true) { return undefined; } if ((state.balance?.lightning || 0n) === 0n) { diff --git a/src/components/layout/BackButton.tsx b/src/components/layout/BackButton.tsx index fd4455b4..1cc0529a 100644 --- a/src/components/layout/BackButton.tsx +++ b/src/components/layout/BackButton.tsx @@ -10,11 +10,11 @@ export function BackButton(props: { return ( ); } diff --git a/src/components/layout/BackLink.tsx b/src/components/layout/BackLink.tsx index d2759b23..556dcb63 100644 --- a/src/components/layout/BackLink.tsx +++ b/src/components/layout/BackLink.tsx @@ -8,7 +8,7 @@ export function BackLink(props: { href?: string; title?: string }) { return ( {props.title ? props.title : i18n.t("common.home")} diff --git a/src/components/layout/BackPop.tsx b/src/components/layout/BackPop.tsx index 2673c3aa..b5f57493 100644 --- a/src/components/layout/BackPop.tsx +++ b/src/components/layout/BackPop.tsx @@ -8,7 +8,7 @@ export type StateWithPrevious = { previous?: string; }; -export function BackPop(props: { default?: string }) { +export function BackPop(props: { default?: string; title?: string }) { const i18n = useI18n(); const navigate = useNavigate(); const location = useLocation(); @@ -30,9 +30,11 @@ export function BackPop(props: { default?: string }) { return ( navigate(backPath())} showOnDesktop diff --git a/src/routes/Activity.tsx b/src/routes/Activity.tsx deleted file mode 100644 index d32e9c97..00000000 --- a/src/routes/Activity.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { Tabs } from "@kobalte/core"; -import { TagItem } from "@mutinywallet/mutiny-wasm"; -import { - createEffect, - createResource, - ErrorBoundary, - For, - Match, - Show, - Suspense, - Switch -} from "solid-js"; - -import { - BackLink, - Card, - CombinedActivity, - ContactEditor, - ContactFormValues, - ContactViewer, - DefaultMain, - LargeHeader, - LoadingShimmer, - MutinyWalletGuard, - NavBar, - NiceP, - NostrActivity, - SafeArea, - showToast, - SimpleErrorDisplay, - SyncContactsForm, - VStack -} from "~/components"; -import { useI18n } from "~/i18n/context"; -import { useMegaStore } from "~/state/megaStore"; -import { eify, gradientsPerContact, hexpubFromNpub } from "~/utils"; - -function ContactRow() { - const [state, _actions] = useMegaStore(); - const [contacts, { refetch }] = createResource(async () => { - try { - const contacts: TagItem[] = - state.mutiny_wallet?.get_contacts_sorted(); - return contacts || []; - } catch (e) { - console.error(e); - return []; - } - }); - - // If the user sets an npub we should refetch the contacts list - createEffect(() => { - if (state.npub) { - refetch(); - } - }); - const [gradients] = createResource(contacts, gradientsPerContact); - - async function createContact(contact: ContactFormValues) { - try { - await state.mutiny_wallet?.create_new_contact( - contact.name, - contact.npub ? contact.npub.trim() : undefined, - contact.ln_address ? contact.ln_address.trim() : undefined, - undefined, - undefined - ); - } catch (e) { - console.error(e); - } - refetch(); - } - - async function saveContact(id: string, contact: ContactFormValues) { - console.log("saving contact", id, contact); - const hexpub = await hexpubFromNpub(contact.npub?.trim()); - try { - const existing = state.mutiny_wallet?.get_tag_item(id); - // This shouldn't happen - if (!existing) throw new Error("No existing contact"); - await state.mutiny_wallet?.edit_contact( - id, - contact.name, - hexpub ? hexpub : undefined, - contact.ln_address ? contact.ln_address.trim() : undefined, - existing.lnurl, - existing.image_url - ); - } catch (e) { - console.error(e); - showToast(eify(e)); - } - - refetch(); - } - - async function deleteContact(id: string) { - try { - await state.mutiny_wallet?.delete_contact(id); - } catch (e) { - console.error(e); - showToast(eify(e)); - } - refetch(); - } - - return ( -
- - -
- - {(contact) => ( - - )} - -
-
-
- ); -} - -const TAB = - "flex-1 inline-block px-8 py-4 text-lg font-semibold rounded-lg ui-selected:bg-white/10 bg-neutral-950 hover:bg-white/10"; - -export function Activity() { - const i18n = useI18n(); - const [state, _actions] = useMegaStore(); - return ( - - - - - {i18n.t("activity.title")} - - - - - {i18n.t("activity.wallet")} - - - {i18n.t("activity.nostr")} - - {/* */} - - - {/* */} - -
- - - } - > - - - - - - - - - - ( - - )} - > - }> - - - - - - - - {i18n.t("activity.import_contacts")} - - - - - - - - - {/* */} - - - ); -} diff --git a/src/routes/Chat.tsx b/src/routes/Chat.tsx index 8d1d6079..f2e762d3 100644 --- a/src/routes/Chat.tsx +++ b/src/routes/Chat.tsx @@ -1,10 +1,7 @@ -/* refresh skip */ - import { TagItem } from "@mutinywallet/mutiny-wasm"; import { createAsync, useNavigate, useParams } from "@solidjs/router"; import { createEffect, - createMemo, createResource, createSignal, For, @@ -15,12 +12,10 @@ import { Suspense, Switch } from "solid-js"; -import { Transition } from "solid-transition-group"; import bolt from "~/assets/icons/bolt.svg"; import receive from "~/assets/icons/receive.svg"; import send from "~/assets/icons/send.svg"; -import plus from "~/assets/plus.png"; import { ActivityDetailsModal, AmountSats, @@ -41,7 +36,7 @@ import { import { MiniFab } from "~/components/Fab"; import { ParsedParams, toParsedParams } from "~/logic/waila"; import { useMegaStore } from "~/state/megaStore"; -import { createDeepSignal, eify, hexpubFromNpub, timeAgo } from "~/utils"; +import { eify, hexpubFromNpub, timeAgo } from "~/utils"; type CombinedMessagesAndActivity = | { kind: "message"; content: FakeDirectMessage } @@ -55,6 +50,14 @@ type FakeDirectMessage = { date: number; }; +function isActivityItem(content: unknown): content is IActivityItem { + return (content as IActivityItem).last_updated !== undefined; +} + +function isDirectMessage(content: unknown): content is FakeDirectMessage { + return (content as FakeDirectMessage).date !== undefined; +} + function SingleMessage(props: { dm: FakeDirectMessage; counterPartyNpub: string; @@ -215,7 +218,7 @@ function MessageList(props: { <>
- {(combined, index) => ( + {(combined, _index) => ( <>
{ // if (!contact() || !contact()?.npub) return undefined; - if (!contact.npub) return []; + if (!contact.npub) return [] as CombinedMessagesAndActivity[]; try { const activity = await state.mutiny_wallet?.get_label_activity( params.id ); + console.log("activity", activity); const refetchingTimestamp = info.refetching as bigint; console.log("refetching since", refetchingTimestamp); @@ -320,7 +324,8 @@ export function Chat() { return lastConvo; } else { console.log("new messages or activity"); - dms.push(convo); + // dms.push(lastConvo); + // dms.push(convo); } } @@ -339,35 +344,47 @@ export function Chat() { ]; combined.sort((a, b) => { - let a_time = 0; - let b_time = 0; - if (a.kind === "message") { - const a_msg = a.content as FakeDirectMessage; - a_time = a_msg.date; - } else { - const a_act = a.content as IActivityItem; - a_time = a_act.last_updated; - } - - if (b.kind === "message") { - const b_msg = b.content as FakeDirectMessage; - b_time = b_msg.date; - } else { - const b_act = b.content as IActivityItem; - b_time = b_act.last_updated; - } - - return b_time - a_time; + // let a_time = 0; + // let b_time = 0; + // if (a.kind === "message") { + // const a_msg = a.content as FakeDirectMessage; + // a_time = a_msg.date; + // } else { + // const a_act = a.content as IActivityItem; + // a_time = a_act.last_updated; + // } + + // if (b.kind === "message") { + // const b_msg = b.content as FakeDirectMessage; + // b_time = b_msg.date; + // } else { + // const b_act = b.content as IActivityItem; + // b_time = b_act.last_updated; + // } + + // return b_time - a_time; + + const a_time = isDirectMessage(a.content) + ? a.content.date + : isActivityItem(a.content) + ? a.content.last_updated + : 0; + const b_time = isDirectMessage(b.content) + ? b.content.date + : isActivityItem(b.content) + ? b.content.last_updated + : 0; + + return b_time - a_time; // Descending order }); + console.log("combined activity", combined); + return combined as CombinedMessagesAndActivity[]; } catch (e) { console.error("error getting convo:", e); - return []; + return [] as CombinedMessagesAndActivity[]; } - }, - { - storage: createDeepSignal } ); @@ -474,42 +491,14 @@ export function Chat() { } return ( - { - if (el instanceof HTMLElement) el.style.opacity = "100"; - }} - onEnter={(el, done) => { - el.animate( - [ - { transform: "translate(50vw)" }, - { transform: "translate(0)" } - ], - { duration: 100, fill: "both" } - ) - .finished.then(done) - .catch(done); - }} - onExit={(el, done) => { - el.animate( - [ - { transform: `translate(0)` }, - { transform: "translate(-50vw)" } - ], - { duration: 100 } - ) - .finished.then(done) - .catch(done); - }} - > - -
-
-
- {/* */} - - -
+ +
+
+
+
+
+ + {}} /> -
- {}}> - - Send - - {}}> - - - Request - - {}}> - Edit - {" "} -
-
- -
-
- {/*
-                            {JSON.stringify(convo(), null, 2)}
-                        
*/} -
- - - }> - - - - - - {/*
*/} +
+
+ { + sendToContact(contact()); + }} + > + + Send + + + requestFromContact(contact()) + } + > + + + Request + +
-
- {/* TODO handle onscan */} - {}} - onSend={() => { - sendToContact(contact()); - }} - onRequest={() => requestFromContact(contact())} - /> - - setMessageValue(e.currentTarget.value) - } - placeholder="Message" - /> -
- - +
+ {/*
+                            {JSON.stringify(convo(), null, 2)}
+                        
*/} +
+ + + }> + + {/* TODO: figure out how not to do typecasting here */} + + + -
+ + {/*
*/} +
+
+
+ {/* TODO handle onscan */} + {}} + onSend={() => { + sendToContact(contact()); + }} + onRequest={() => requestFromContact(contact())} + /> + setMessageValue(e.currentTarget.value)} + placeholder="Message" + /> +
+ + +
-
-
- +
+
+
); } diff --git a/src/routes/Main.tsx b/src/routes/Main.tsx index c2143dcb..00581e95 100644 --- a/src/routes/Main.tsx +++ b/src/routes/Main.tsx @@ -1,11 +1,6 @@ import { createAsync, useNavigate } from "@solidjs/router"; import { createMemo, createSignal, Show, Suspense } from "solid-js"; -import receive from "~/assets/icons/receive.svg"; -import scan from "~/assets/icons/scan.svg"; -import send from "~/assets/icons/send.svg"; -import plus from "~/assets/plus.png"; -import wave from "~/assets/wave.gif"; import { BalanceBox, BetaWarningModal, diff --git a/src/routes/Profile.tsx b/src/routes/Profile.tsx index 7170060c..18f15bae 100644 --- a/src/routes/Profile.tsx +++ b/src/routes/Profile.tsx @@ -6,8 +6,10 @@ import { BackLink, BalanceBox, DefaultMain, + FancyCard, + KeyValue, LabelCircle, - LargeHeader, + MiniStringShower, MutinyWalletGuard, NavBar, SafeArea @@ -57,9 +59,7 @@ export function Profile() {

{profile().lud16}

-

- {npub()} -

+
{/* Accounts */} + + + + +
diff --git a/src/routes/Request.tsx b/src/routes/Request.tsx index ad0b95a6..8d101bc7 100644 --- a/src/routes/Request.tsx +++ b/src/routes/Request.tsx @@ -1,11 +1,9 @@ -/* @refresh skip */ - import { useNavigate, useParams } from "@solidjs/router"; import { createResource, createSignal, Suspense } from "solid-js"; import { AmountEditable, - BackButton, + BackPop, Button, DefaultMain, LabelCircle, @@ -35,8 +33,6 @@ export function RequestRoute() { const [loading, setLoading] = createSignal(false); - function handleBack() {} - async function handleSubmit() { setLoading(true); console.log("requesting", amount(), whatForInput()); @@ -84,7 +80,7 @@ export function RequestRoute() { return ( - + {i18n.t("request.request_bitcoin")}
); diff --git a/src/routes/Send.tsx b/src/routes/Send.tsx index 3846bde4..c2d51219 100644 --- a/src/routes/Send.tsx +++ b/src/routes/Send.tsx @@ -1,5 +1,5 @@ import { MutinyInvoice, TagItem } from "@mutinywallet/mutiny-wasm"; -import { A, useLocation, useNavigate, useSearchParams } from "@solidjs/router"; +import { useLocation, useNavigate, useSearchParams } from "@solidjs/router"; import { createEffect, createMemo,