format project with plugins

This commit is contained in:
gawlk
2023-08-18 18:40:22 +02:00
committed by Paul Miller
parent 6f3a83f6e5
commit 32dfd30136
78 changed files with 742 additions and 679 deletions

View File

@@ -1,24 +1,25 @@
import { Contact } from "@mutinywallet/mutiny-wasm";
import {
createEffect,
createResource,
createSignal,
For,
Match,
Show,
Switch,
createEffect,
createResource,
createSignal
Switch
} from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { useI18n } from "~/i18n/context";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { A } from "solid-start";
import { createDeepSignal } from "~/utils/deepSignal";
import {
NiceP,
DetailsIdModal,
LoadingShimmer,
ActivityItem,
HackActivityType
DetailsIdModal,
HackActivityType,
LoadingShimmer,
NiceP
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { createDeepSignal } from "~/utils/deepSignal";
export const THREE_COLUMNS =
"grid grid-cols-[auto,1fr,auto] gap-4 py-2 px-2 border-b border-neutral-800 last:border-b-0";
@@ -117,7 +118,7 @@ export function CombinedActivity(props: { limit?: number }) {
</Show>
<Switch>
<Match when={activity.latest.length === 0}>
<div class="w-full text-center pb-4">
<div class="w-full pb-4 text-center">
<NiceP>
{i18n.t(
"activity.receive_some_sats_to_get_started"
@@ -151,7 +152,7 @@ export function CombinedActivity(props: { limit?: number }) {
<Show when={props.limit && activity.latest.length > 0}>
<A
href="/activity"
class="text-m-red active:text-m-red/80 font-semibold no-underline self-center"
class="self-center font-semibold text-m-red no-underline active:text-m-red/80"
>
{i18n.t("activity.view_all")}
</A>

View File

@@ -1,16 +1,16 @@
import { Match, ParentComponent, Switch, createResource } from "solid-js";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { createResource, Match, ParentComponent, Switch } from "solid-js";
import bolt from "~/assets/icons/bolt.svg";
import chain from "~/assets/icons/chain.svg";
import off from "~/assets/icons/download-channel.svg";
import shuffle from "~/assets/icons/shuffle.svg";
import on from "~/assets/icons/upload-channel.svg";
import off from "~/assets/icons/download-channel.svg";
import { timeAgo } from "~/utils/prettyPrintTime";
import { generateGradient } from "~/utils/gradientHash";
import { useMegaStore } from "~/state/megaStore";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { useI18n } from "~/i18n/context";
import { AmountFiat, AmountSats } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { generateGradient } from "~/utils/gradientHash";
import { timeAgo } from "~/utils/prettyPrintTime";
export const ActivityAmount: ParentComponent<{
amount: string;
@@ -69,7 +69,7 @@ function LabelCircle(props: {
return (
<div
class="flex-none h-[3rem] w-[3rem] rounded-full bg-neutral-700 flex items-center justify-center text-3xl uppercase border-t border-b border-t-white/50 border-b-white/10"
class="flex h-[3rem] w-[3rem] flex-none items-center justify-center rounded-full border-b border-t border-b-white/10 border-t-white/50 bg-neutral-700 text-3xl uppercase"
style={{ background: bg() }}
>
<Switch>
@@ -110,10 +110,10 @@ export function ActivityItem(props: {
return (
<div
onClick={() => props.onClick && props.onClick()}
class="grid grid-cols-[auto_minmax(0,_1fr)_minmax(0,_max-content)] pb-4 gap-4 border-b border-neutral-800 last:border-b-0"
class="grid grid-cols-[auto_minmax(0,_1fr)_minmax(0,_max-content)] gap-4 border-b border-neutral-800 pb-4 last:border-b-0"
classList={{ "cursor-pointer": !!props.onClick }}
>
<div class="flex gap-2 md:gap-4 items-center">
<div class="flex items-center gap-2 md:gap-4">
<div class="">
<Switch>
<Match when={props.kind === "Lightning"}>
@@ -154,12 +154,12 @@ export function ActivityItem(props: {
</span>{" "}
</Match>
<Match when={firstContact()?.name}>
<span class="text-base font-semibold truncate">
<span class="truncate text-base font-semibold">
{firstContact()?.name}
</span>
</Match>
<Match when={props.labels.length > 0}>
<span class="text-base font-semibold truncate">
<span class="truncate text-base font-semibold">
{props.labels[0]}
</span>
</Match>

View File

@@ -1,9 +1,10 @@
import { Show } from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd } from "~/utils/conversions";
import bolt from "~/assets/icons/bolt.svg";
import chain from "~/assets/icons/chain.svg";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd } from "~/utils/conversions";
function prettyPrintAmount(n?: number | bigint): string {
if (!n || n.valueOf() === 0) {
@@ -20,14 +21,14 @@ export function AmountSats(props: {
}) {
const i18n = useI18n();
return (
<div class="flex gap-2 items-center">
<div class="flex items-center gap-2">
<Show when={props.icon === "lightning"}>
<img src={bolt} alt="lightning" class="h-[18px]" />
</Show>
<Show when={props.icon === "chain"}>
<img src={chain} alt="chain" class="h-[18px]" />
</Show>
<h1 class="font-light text-right">
<h1 class="text-right font-light">
<Show when={props.icon === "plus"}>
<span>+</span>
</Show>
@@ -37,7 +38,7 @@ export function AmountSats(props: {
{props.loading ? "..." : prettyPrintAmount(props.amountSats)}
&nbsp;
<span
class="font-light text-base"
class="text-base font-light"
classList={{
"text-sm": props.denominationSize === "sm",
"text-lg": props.denominationSize === "lg",

View File

@@ -1,8 +1,9 @@
import { Match, ParentComponent, Show, Switch, createMemo } from "solid-js";
import { Card, VStack, AmountEditable } from "~/components";
import { createMemo, Match, ParentComponent, Show, Switch } from "solid-js";
import { AmountEditable, Card, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd } from "~/utils/conversions";
import { useI18n } from "~/i18n/context";
const noop = () => {
// do nothing
@@ -11,7 +12,7 @@ const noop = () => {
const KeyValue: ParentComponent<{ key: string; gray?: boolean }> = (props) => {
return (
<div
class="flex justify-between items-center"
class="flex items-center justify-between"
classList={{ "text-neutral-400": props.gray }}
>
<div class="font-semibold uppercase">{props.key}</div>

View File

@@ -1,26 +1,27 @@
import { Dialog } from "@kobalte/core";
import {
For,
ParentComponent,
Show,
createResource,
createSignal,
onMount,
For,
Match,
onCleanup,
Switch,
Match
onMount,
ParentComponent,
Show,
Switch
} from "solid-js";
import { Button, InlineAmount, InfoBox, FeesModal } from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { satsToUsd, usdToSats } from "~/utils/conversions";
import { Dialog } from "@kobalte/core";
import close from "~/assets/icons/close.svg";
import pencil from "~/assets/icons/pencil.svg";
import currencySwap from "~/assets/icons/currency-swap.svg";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { Network } from "~/logic/mutinyWalletSetup";
import { useI18n } from "~/i18n/context";
import { useNavigate } from "solid-start";
import close from "~/assets/icons/close.svg";
import currencySwap from "~/assets/icons/currency-swap.svg";
import pencil from "~/assets/icons/pencil.svg";
import { Button, FeesModal, InfoBox, InlineAmount } from "~/components";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { satsToUsd, usdToSats } from "~/utils/conversions";
function fiatInputSanitizer(input: string): string {
// Make sure only numbers and a single decimal point are allowed
const numeric = input.replace(/[^0-9.]/g, "").replace(/(\..*)\./g, "$1");
@@ -90,7 +91,7 @@ function SingleDigitButton(props: {
fallback={<div />}
>
<button
class="disabled:opacity-50 flex justify-center items-center p-2 rounded-lg md:hover:bg-white/10 active:bg-m-blue text-white text-4xl font-semi font-inter"
class="font-semi font-inter flex items-center justify-center rounded-lg p-2 text-4xl text-white active:bg-m-blue disabled:opacity-50 md:hover:bg-white/10"
onMouseDown={onHold}
onMouseUp={endHold}
onMouseLeave={endHold}
@@ -108,7 +109,7 @@ function BigScalingText(props: { text: string; fiat: boolean }) {
return (
<h1
class="font-light px-2 text-center transition-transform ease-out duration-300 text-4xl"
class="px-2 text-center text-4xl font-light transition-transform duration-300 ease-out"
classList={{
"scale-90": chars() >= 11,
"scale-95": chars() === 10,
@@ -136,7 +137,7 @@ function SmallSubtleAmount(props: { text: string; fiat: boolean }) {
{props.fiat ? i18n.t("common.usd") : i18n.t("common.sats")}
</span>
<img
class={"pl-[4px] pb-[4px] hover:cursor-pointer"}
class={"pb-[4px] pl-[4px] hover:cursor-pointer"}
src={currencySwap}
height={24}
width={24}
@@ -438,7 +439,7 @@ export const AmountEditable: ParentComponent<{
<Dialog.Root open={isOpen()}>
<button
onClick={() => setIsOpen(true)}
class="px-4 py-2 rounded-xl border-2 border-m-blue flex gap-2 items-center"
class="flex items-center gap-2 rounded-xl border-2 border-m-blue px-4 py-2"
>
<Show
when={localSats() !== "0"}
@@ -461,10 +462,10 @@ export const AmountEditable: ParentComponent<{
onEscapeKeyDown={handleClose}
>
{/* TODO: figure out how to submit on enter */}
<div class="w-full flex justify-end">
<div class="flex w-full justify-end">
<button
onClick={handleClose}
class="hover:bg-white/10 rounded-lg active:bg-m-blue w-8 h-8"
class="h-8 w-8 rounded-lg hover:bg-white/10 active:bg-m-blue"
>
<img src={close} alt="Close" />
</button>
@@ -472,7 +473,7 @@ export const AmountEditable: ParentComponent<{
{/* <form onSubmit={handleSubmit} class="text-black"> */}
<form
onSubmit={handleSubmit}
class="opacity-0 absolute -z-10"
class="absolute -z-10 opacity-0"
>
<input
ref={(el) => (satsInputRef = el)}
@@ -492,10 +493,10 @@ export const AmountEditable: ParentComponent<{
/>
</form>
<div class="flex flex-col flex-1 justify-around gap-2 max-w-[400px] mx-auto w-full">
<div class="mx-auto flex w-full max-w-[400px] flex-1 flex-col justify-around gap-2">
<div class="flex justify-center">
<div
class="p-4 flex flex-col gap-4 w-max items-center justify-center"
class="flex w-max flex-col items-center justify-center gap-4 p-4"
onClick={toggle}
>
<BigScalingText
@@ -530,7 +531,7 @@ export const AmountEditable: ParentComponent<{
</InfoBox>
</Match>
</Switch>
<div class="flex justify-center gap-4 my-2">
<div class="my-2 flex justify-center gap-4">
<For
each={
mode() === "fiat"
@@ -544,7 +545,7 @@ export const AmountEditable: ParentComponent<{
setFixedAmount(amount.amount);
focus();
}}
class="py-2 px-4 rounded-lg bg-white/10"
class="rounded-lg bg-white/10 px-4 py-2"
>
{amount.label}
</button>
@@ -558,13 +559,13 @@ export const AmountEditable: ParentComponent<{
);
focus();
}}
class="py-2 px-4 rounded-lg bg-white/10"
class="rounded-lg bg-white/10 px-4 py-2"
>
{i18n.t("receive.amount_editable.max")}
</button>
</Show>
</div>
<div class="grid grid-cols-3 w-full flex-none">
<div class="grid w-full flex-none grid-cols-3">
<For each={CHARACTERS}>
{(character) => (
<SingleDigitButton

View File

@@ -1,27 +1,28 @@
import {
DefaultMain,
SafeArea,
VStack,
Card,
LoadingShimmer,
BalanceBox,
ReloadPrompt,
NavBar,
OnboardWarning,
CombinedActivity,
BetaWarningModal,
PendingNwc,
DecryptDialog,
LoadingIndicator
} from "~/components";
import { A } from "solid-start";
import { useMegaStore } from "~/state/megaStore";
import { Match, Show, Suspense, Switch } from "solid-js";
import { A } from "solid-start";
import settings from "~/assets/icons/settings.svg";
import pixelLogo from "~/assets/mutiny-pixel-logo.png";
import plusLogo from "~/assets/mutiny-plus-logo.png";
import { FeedbackLink } from "~/routes/Feedback";
import {
BalanceBox,
BetaWarningModal,
Card,
CombinedActivity,
DecryptDialog,
DefaultMain,
LoadingIndicator,
LoadingShimmer,
NavBar,
OnboardWarning,
PendingNwc,
ReloadPrompt,
SafeArea,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { FeedbackLink } from "~/routes/Feedback";
import { useMegaStore } from "~/state/megaStore";
export function App() {
const i18n = useI18n();
@@ -31,7 +32,7 @@ export function App() {
<SafeArea>
<DefaultMain>
<LoadingIndicator />
<header class="w-full flex justify-between items-center mt-4 mb-2">
<header class="mb-2 mt-4 flex w-full items-center justify-between">
<div class="flex items-center gap-2">
<Switch>
<Match when={state.mutiny_plus}>
@@ -57,13 +58,13 @@ export function App() {
state.mutiny_wallet?.get_network() !== "bitcoin"
}
>
<div class="box-border px-2 py-1 -my-1 text-white-400 bg-neutral-800 rounded text-xs uppercase w-fit">
<div class="text-white-400 -my-1 box-border w-fit rounded bg-neutral-800 px-2 py-1 text-xs uppercase">
{state.mutiny_wallet?.get_network()}
</div>
</Show>
</div>
<A
class="md:hidden p-2 hover:bg-white/5 rounded-lg active:bg-m-blue"
class="rounded-lg p-2 hover:bg-white/5 active:bg-m-blue md:hidden"
href="/settings"
>
<img src={settings} alt="Settings" class="h-6 w-6" />
@@ -92,7 +93,7 @@ export function App() {
</Suspense>
</VStack>
</Card>
<div class="self-center mt-4">
<div class="mt-4 self-center">
<FeedbackLink />
</div>
</DefaultMain>

View File

@@ -1,25 +1,26 @@
import { Match, Show, Switch } from "solid-js";
import { A, useNavigate } from "solid-start";
import shuffle from "~/assets/icons/shuffle.svg";
import {
AmountFiat,
AmountSats,
Button,
FancyCard,
Indicator,
AmountSats,
AmountFiat,
InfoBox
} from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { A, useNavigate } from "solid-start";
import shuffle from "~/assets/icons/shuffle.svg";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
export function LoadingShimmer() {
return (
<div class="flex flex-col gap-2 animate-pulse">
<div class="flex animate-pulse flex-col gap-2">
<h1 class="text-4xl font-light">
<div class="w-[12rem] rounded bg-neutral-700 h-[2.5rem]" />
<div class="h-[2.5rem] w-[12rem] rounded bg-neutral-700" />
</h1>
<h2 class="text-xl font-light text-white/70">
<div class="w-[8rem] rounded bg-neutral-700 h-[1.75rem]" />
<div class="h-[1.75rem] w-[8rem] rounded bg-neutral-700" />
</h2>
</div>
);
@@ -99,7 +100,7 @@ export function BalanceBox(props: { loading?: boolean }) {
/>
</div>
</div>
<div class="flex flex-col items-end gap-1 justify-between">
<div class="flex flex-col items-end justify-between gap-1">
<Show when={state.balance?.unconfirmed != 0n}>
<Indicator>
{i18n.t("common.pending")}

View File

@@ -1,15 +1,16 @@
import { Dialog } from "@kobalte/core";
import { ParentComponent, createSignal } from "solid-js";
import { ExternalLink } from "@mutinywallet/ui";
import { createSignal, ParentComponent } from "solid-js";
import {
DIALOG_CONTENT,
DIALOG_POSITIONER,
OVERLAY,
ModalCloseButton,
OVERLAY,
SmallHeader
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { ExternalLink } from "@mutinywallet/ui";
export function BetaWarningModal() {
const i18n = useI18n();
@@ -57,7 +58,7 @@ export const WarningModal: ParentComponent<{
<Dialog.Overlay class={OVERLAY} />
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<Dialog.Title class="flex justify-between mb-2 items-center">
<Dialog.Title class="mb-2 flex items-center justify-between">
<SmallHeader>{props.title}</SmallHeader>
<Dialog.CloseButton>
<ModalCloseButton />

View File

@@ -1,15 +1,16 @@
import { Match, Switch, createSignal } from "solid-js";
import { Dialog } from "@kobalte/core";
import close from "~/assets/icons/close.svg";
import { SubmitHandler } from "@modular-forms/solid";
import { createSignal, Match, Switch } from "solid-js";
import close from "~/assets/icons/close.svg";
import {
ContactFormValues,
ContactForm,
ContactFormValues,
SmallHeader,
TinyButton
} from "~/components";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { useI18n } from "~/i18n/context";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
export function ContactEditor(props: {
createContact: (contact: ContactFormValues) => void;
@@ -34,7 +35,7 @@ export function ContactEditor(props: {
onClick={() => setIsOpen(true)}
class="flex flex-col items-center gap-2"
>
<div class="bg-neutral-500 flex-none h-16 w-16 rounded-full flex items-center justify-center text-4xl uppercase ">
<div class="flex h-16 w-16 flex-none items-center justify-center rounded-full bg-neutral-500 text-4xl uppercase ">
<span class="leading-[4rem]">+</span>
</div>
<SmallHeader class="overflow-ellipsis">
@@ -54,11 +55,11 @@ export function ContactEditor(props: {
class={DIALOG_CONTENT}
onEscapeKeyDown={() => setIsOpen(false)}
>
<div class="w-full flex justify-end">
<div class="flex w-full justify-end">
<button
tabindex="-1"
onClick={() => setIsOpen(false)}
class="hover:bg-white/10 rounded-lg active:bg-m-blue"
class="rounded-lg hover:bg-white/10 active:bg-m-blue"
>
<img src={close} alt="Close" />
</button>

View File

@@ -1,10 +1,11 @@
import { SubmitHandler, createForm, required } from "@modular-forms/solid";
import { createForm, required, SubmitHandler } from "@modular-forms/solid";
import {
Button,
ContactFormValues,
LargeHeader,
VStack,
TextField,
ContactFormValues
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
@@ -22,7 +23,7 @@ export function ContactForm(props: {
return (
<Form
onSubmit={props.handleSubmit}
class="flex flex-col flex-1 justify-around gap-4 max-w-[400px] mx-auto w-full"
class="mx-auto flex w-full max-w-[400px] flex-1 flex-col justify-around gap-4"
>
<div>
<LargeHeader>{props.title}</LargeHeader>

View File

@@ -1,18 +1,19 @@
import { Match, Switch, createSignal } from "solid-js";
import { Dialog } from "@kobalte/core";
import { SubmitHandler } from "@modular-forms/solid";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { createSignal, Match, Switch } from "solid-js";
import close from "~/assets/icons/close.svg";
import {
Button,
Card,
NiceP,
SmallHeader,
ContactForm,
showToast
NiceP,
showToast,
SmallHeader
} from "~/components";
import { Dialog } from "@kobalte/core";
import close from "~/assets/icons/close.svg";
import { SubmitHandler } from "@modular-forms/solid";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { useI18n } from "~/i18n/context";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
export type ContactFormValues = {
name: string;
@@ -42,15 +43,15 @@ export function ContactViewer(props: {
<Dialog.Root open={isOpen()}>
<button
onClick={() => setIsOpen(true)}
class="flex flex-col items-center gap-2 w-16 flex-shrink-0 overflow-x-hidden"
class="flex w-16 flex-shrink-0 flex-col items-center gap-2 overflow-x-hidden"
>
<div
class="flex-none h-16 w-16 rounded-full flex items-center justify-center text-4xl uppercase border-t border-b border-t-white/50 border-b-white/10"
class="flex h-16 w-16 flex-none items-center justify-center rounded-full border-b border-t border-b-white/10 border-t-white/50 text-4xl uppercase"
style={{ background: props.gradient }}
>
{props.contact.name[0]}
</div>
<SmallHeader class="overflow-ellipsis w-16 text-center overflow-hidden h-4">
<SmallHeader class="h-4 w-16 overflow-hidden overflow-ellipsis text-center">
{props.contact.name}
</SmallHeader>
</button>
@@ -63,14 +64,14 @@ export function ContactViewer(props: {
setIsEditing(false);
}}
>
<div class="w-full flex justify-end">
<div class="flex w-full justify-end">
<button
tabindex="-1"
onClick={() => {
setIsOpen(false);
setIsEditing(false);
}}
class="hover:bg-white/10 rounded-lg active:bg-m-blue"
class="rounded-lg hover:bg-white/10 active:bg-m-blue"
>
<img src={close} alt="Close" />
</button>
@@ -85,17 +86,17 @@ export function ContactViewer(props: {
/>
</Match>
<Match when={!isEditing()}>
<div class="flex flex-col flex-1 justify-around items-center gap-4 max-w-[400px] mx-auto w-full">
<div class="flex flex-col items-center w-full">
<div class="mx-auto flex w-full max-w-[400px] flex-1 flex-col items-center justify-around gap-4">
<div class="flex w-full flex-col items-center">
<div
class="flex-none h-32 w-32 rounded-full flex items-center justify-center text-8xl uppercase border-t border-b border-t-white/50 border-b-white/10"
class="flex h-32 w-32 flex-none items-center justify-center rounded-full border-b border-t border-b-white/10 border-t-white/50 text-8xl uppercase"
style={{
background: props.gradient
}}
>
{props.contact.name[0]}
</div>
<h1 class="text-2xl font-semibold uppercase mt-2 mb-4">
<h1 class="mb-4 mt-2 text-2xl font-semibold uppercase">
{props.contact.name}
</h1>
<Card

View File

@@ -1,5 +1,6 @@
import { Show } from "solid-js";
import { QRCodeSVG } from "solid-qr-code";
import { useI18n } from "~/i18n/context";
import { useCopy } from "~/utils/useCopy";
@@ -9,17 +10,17 @@ export function CopyableQR(props: { value: string }) {
return (
<div
id="qr"
class="w-full bg-white rounded-xl relative"
class="relative w-full rounded-xl bg-white"
onClick={() => copy(props.value)}
>
<Show when={copied()}>
<div class="absolute w-full h-full bg-neutral-900/60 z-50 rounded-xl flex flex-col items-center justify-center transition-all">
<div class="absolute z-50 flex h-full w-full flex-col items-center justify-center rounded-xl bg-neutral-900/60 transition-all">
<p class="text-xl font-bold">{i18n.t("common.copied")}</p>
</div>
</Show>
<QRCodeSVG
value={props.value}
class="w-full h-full p-8 max-h-[400px]"
class="h-full max-h-[400px] w-full p-8"
/>
</div>
);

View File

@@ -1,9 +1,10 @@
import { Show, createSignal } from "solid-js";
import { Button, SimpleDialog, TextField, InfoBox } from "~/components";
import { createSignal, Show } from "solid-js";
import { A } from "solid-start";
import { Button, InfoBox, SimpleDialog, TextField } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import { A } from "solid-start";
import { useI18n } from "~/i18n/context";
export function DecryptDialog() {
const i18n = useI18n();

View File

@@ -1,6 +1,7 @@
import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { createSignal } from "solid-js";
import { ConfirmDialog, Button, showToast } from "~/components";
import { Button, ConfirmDialog, showToast } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";

View File

@@ -1,42 +1,41 @@
import { Dialog } from "@kobalte/core";
import { MutinyChannel, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import { ExternalLink } from "@mutinywallet/ui";
import {
createEffect,
createMemo,
createResource,
For,
Match,
ParentComponent,
Show,
Suspense,
Switch,
createEffect,
createMemo,
createResource
Switch
} from "solid-js";
import {
InfoBox,
Hr,
ModalCloseButton,
TinyButton,
VStack,
ActivityAmount,
HackActivityType,
CopyButton,
TruncateMiddle,
AmountSmall
} from "~/components";
import { MutinyChannel, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import bolt from "~/assets/icons/bolt-black.svg";
import chain from "~/assets/icons/chain-black.svg";
import copyIcon from "~/assets/icons/copy.svg";
import shuffle from "~/assets/icons/shuffle-black.svg";
import { prettyPrintTime } from "~/utils/prettyPrintTime";
import {
ActivityAmount,
AmountSmall,
CopyButton,
HackActivityType,
Hr,
InfoBox,
ModalCloseButton,
TinyButton,
TruncateMiddle,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { prettyPrintTime } from "~/utils/prettyPrintTime";
import { MutinyTagItem, tagToMutinyTag } from "~/utils/tags";
import { useCopy } from "~/utils/useCopy";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { Network } from "~/logic/mutinyWalletSetup";
import { ExternalLink } from "@mutinywallet/ui";
import { useI18n } from "~/i18n/context";
interface ChannelClosure {
channel_id: string;
@@ -74,10 +73,10 @@ function LightningHeader(props: {
return (
<div class="flex flex-col items-center gap-4">
<div class="p-4 bg-neutral-100 rounded-full">
<img src={bolt} alt="lightning bolt" class="w-8 h-8" />
<div class="rounded-full bg-neutral-100 p-4">
<img src={bolt} alt="lightning bolt" class="h-8 w-8" />
</div>
<h1 class="uppercase font-semibold">
<h1 class="font-semibold uppercase">
{props.info.inbound
? i18n.t("modals.transaction_details.lightning_receive")
: i18n.t("modals.transaction_details.lightning_send")}
@@ -126,7 +125,7 @@ function OnchainHeader(props: {
return (
<div class="flex flex-col items-center gap-4">
<div class="p-4 bg-neutral-100 rounded-full">
<div class="rounded-full bg-neutral-100 p-4">
<Switch>
<Match
when={
@@ -134,14 +133,14 @@ function OnchainHeader(props: {
props.kind === "ChannelClose"
}
>
<img src={shuffle} alt="swap" class="w-8 h-8" />
<img src={shuffle} alt="swap" class="h-8 w-8" />
</Match>
<Match when={true}>
<img src={chain} alt="blockchain" class="w-8 h-8" />
<img src={chain} alt="blockchain" class="h-8 w-8" />
</Match>
</Switch>
</div>
<h1 class="uppercase font-semibold">
<h1 class="font-semibold uppercase">
{props.kind === "ChannelOpen"
? i18n.t("modals.transaction_details.channel_open")
: props.kind === "ChannelClose"
@@ -176,8 +175,8 @@ function OnchainHeader(props: {
export const KeyValue: ParentComponent<{ key: string }> = (props) => {
return (
<li class="flex justify-between items-center gap-4">
<span class="uppercase font-semibold whitespace-nowrap text-sm">
<li class="flex items-center justify-between gap-4">
<span class="whitespace-nowrap text-sm font-semibold uppercase">
{props.key}
</span>
<span class="font-light">{props.children}</span>
@@ -189,7 +188,7 @@ export function MiniStringShower(props: { text: string }) {
const [copy, copied] = useCopy({ copiedTimeout: 1000 });
return (
<div class="w-full grid gap-1 grid-cols-[minmax(0,_1fr)_auto]">
<div class="grid w-full grid-cols-[minmax(0,_1fr)_auto] gap-1">
<TruncateMiddle text={props.text} />
{/* <pre class="truncate text-neutral-300 font-light">{props.text}</pre> */}
<button
@@ -197,7 +196,7 @@ export function MiniStringShower(props: { text: string }) {
classList={{ "bg-m-green rounded": copied() }}
onClick={() => copy(props.text)}
>
<img src={copyIcon} alt="copy" class="w-4 h-4" />
<img src={copyIcon} alt="copy" class="h-4 w-4" />
</button>
</div>
);
@@ -224,7 +223,7 @@ function LightningDetails(props: { info: MutinyInvoice }) {
<KeyValue
key={i18n.t("modals.transaction_details.description")}
>
<span class="text-neutral-300 truncate">
<span class="truncate text-neutral-300">
{props.info.description}
</span>
</KeyValue>
@@ -268,8 +267,8 @@ function OnchainDetails(props: { info: OnChainTx; kind?: HackActivityType }) {
await (state.mutiny_wallet?.list_channels() as Promise<
MutinyChannel[]
>);
const channel = channels.find((channel) =>
channel.outpoint?.startsWith(props.info.txid)
const channel = channels.find(
(channel) => channel.outpoint?.startsWith(props.info.txid)
);
return channel;
} catch (e) {
@@ -375,7 +374,7 @@ function ChannelCloseDetails(props: { info: ChannelClosure }) {
</KeyValue>
</Show>
<KeyValue key={i18n.t("modals.transaction_details.reason")}>
<p class="text-neutral-300 text-right">
<p class="text-right text-neutral-300">
{props.info.reason ?? ""}
</p>
</KeyValue>
@@ -458,7 +457,7 @@ export function DetailsIdModal(props: {
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<Suspense>
<div class="flex justify-between mb-2">
<div class="mb-2 flex justify-between">
<div />
<Dialog.CloseButton>
<ModalCloseButton />

View File

@@ -1,5 +1,6 @@
import { Dialog } from "@kobalte/core";
import { ParentComponent } from "solid-js";
import { Button, SmallHeader } from "~/components";
import { useI18n } from "~/i18n/context";
@@ -22,7 +23,7 @@ export const ConfirmDialog: ParentComponent<{
<Dialog.Overlay class={OVERLAY} />
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<div class="flex justify-between mb-2">
<div class="mb-2 flex justify-between">
<Dialog.Title>
<SmallHeader>
{i18n.t(
@@ -33,7 +34,7 @@ export const ConfirmDialog: ParentComponent<{
</div>
<Dialog.Description class="flex flex-col gap-4">
{props.children}
<div class="flex gap-4 w-full justify-end">
<div class="flex w-full justify-end gap-4">
<Button onClick={props.onCancel}>
{i18n.t("modals.confirm_dialog.cancel")}
</Button>

View File

@@ -1,4 +1,6 @@
import { ExternalLink } from "@mutinywallet/ui";
import { A, Title } from "solid-start";
import {
Button,
DefaultMain,
@@ -7,7 +9,6 @@ import {
SafeArea,
SmallHeader
} from "~/components/layout";
import { ExternalLink } from "@mutinywallet/ui";
import { useI18n } from "~/i18n/context";
export function ErrorDisplay(props: { error: Error }) {
@@ -20,7 +21,7 @@ export function ErrorDisplay(props: { error: Error }) {
<SmallHeader>
{i18n.t("error.general.never_should_happen")}
</SmallHeader>
<p class="bg-white/10 rounded-xl p-4 font-mono">
<p class="rounded-xl bg-white/10 p-4 font-mono">
<span class="font-bold">{props.error.name}</span>:{" "}
{props.error.message}
</p>

View File

@@ -1,12 +1,12 @@
import { useI18n } from "~/i18n/context";
import { AmountFiat, AmountSats, FeesModal } from "~/components";
import { useI18n } from "~/i18n/context";
export function Fee(props: { amountSats?: bigint | number }) {
const i18n = useI18n();
return (
<div class="flex gap-3">
<p class="text-m-grey-400 text-sm">{i18n.t("common.fee")}</p>
<p class="text-sm text-m-grey-400">{i18n.t("common.fee")}</p>
<div class="flex gap-1">
<div class="flex flex-col gap-1">
<div class="text-right text-sm">

View File

@@ -1,7 +1,8 @@
import { ParentComponent, Show, createResource } from "solid-js";
import { I18nContext } from "~/i18n/context";
import i18next from "i18next";
import { createResource, ParentComponent, Show } from "solid-js";
import i18nConfig from "~/i18n/config";
import { I18nContext } from "~/i18n/context";
export const I18nProvider: ParentComponent = (props) => {
const [i18nConfigured] = createResource(async () => {

View File

@@ -1,21 +1,22 @@
import { useMegaStore } from "~/state/megaStore";
import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { createFileUploader } from "@solid-primitives/upload";
import { createSignal, Show } from "solid-js";
import {
Button,
ConfirmDialog,
InfoBox,
InnerCard,
NiceP,
SimpleDialog,
VStack,
ConfirmDialog,
showToast,
InfoBox,
TextField
SimpleDialog,
TextField,
VStack
} from "~/components";
import { Show, createSignal } from "solid-js";
import eify from "~/utils/eify";
import { downloadTextFile } from "~/utils/download";
import { createFileUploader } from "@solid-primitives/upload";
import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { downloadTextFile } from "~/utils/download";
import eify from "~/utils/eify";
export function ImportExport(props: { emergency?: boolean }) {
const i18n = useI18n();

View File

@@ -1,4 +1,5 @@
import { ParentComponent } from "solid-js";
import info from "~/assets/icons/info.svg";
export const InfoBox: ParentComponent<{
@@ -6,7 +7,7 @@ export const InfoBox: ParentComponent<{
}> = (props) => {
return (
<div
class="grid grid-cols-[auto_minmax(0,_1fr)] rounded-xl px-4 py-2 md:p-4 gap-4 bg-neutral-950/50 border"
class="grid grid-cols-[auto_minmax(0,_1fr)] gap-4 rounded-xl border bg-neutral-950/50 px-4 py-2 md:p-4"
classList={{
"border-m-red": props.accent === "red",
"border-m-blue bg-m-blue/10": props.accent === "blue",
@@ -15,7 +16,7 @@ export const InfoBox: ParentComponent<{
}}
>
<div class="self-center">
<img src={info} alt="info" class="w-8 h-8" />
<img src={info} alt="info" class="h-8 w-8" />
</div>
<div class="flex items-center">
<p class="text-sm font-light">{props.children}</p>

View File

@@ -1,18 +1,19 @@
import { Match, Show, Switch } from "solid-js";
import { QRCodeSVG } from "solid-qr-code";
import { ReceiveFlavor } from "~/routes/Receive";
import { useCopy } from "~/utils/useCopy";
import { AmountSats, AmountFiat, TruncateMiddle } from "~/components";
import boltBlack from "~/assets/icons/bolt-black.svg";
import chainBlack from "~/assets/icons/chain-black.svg";
import copyBlack from "~/assets/icons/copy-black.svg";
import shareBlack from "~/assets/icons/share-black.svg";
import chainBlack from "~/assets/icons/chain-black.svg";
import boltBlack from "~/assets/icons/bolt-black.svg";
import { AmountFiat, AmountSats, TruncateMiddle } from "~/components";
import { useI18n } from "~/i18n/context";
import { ReceiveFlavor } from "~/routes/Receive";
import { useCopy } from "~/utils/useCopy";
function KindIndicator(props: { kind: ReceiveFlavor }) {
const i18n = useI18n();
return (
<div class="text-black flex flex-col items-end">
<div class="flex flex-col items-end text-black">
<Switch>
<Match when={props.kind === "onchain"}>
<h3 class="font-semibold">
@@ -68,16 +69,16 @@ export function IntegratedQr(props: {
return (
<div
id="qr"
class="w-full bg-white rounded-xl relative flex flex-col items-center px-4"
class="relative flex w-full flex-col items-center rounded-xl bg-white px-4"
onClick={() => copy(props.value)}
>
<Show when={copied()}>
<div class="absolute w-full h-full bg-neutral-900/60 z-50 rounded-xl flex flex-col items-center justify-center transition-all">
<div class="absolute z-50 flex h-full w-full flex-col items-center justify-center rounded-xl bg-neutral-900/60 transition-all">
<p class="text-xl font-bold">{i18n.t("common.copied")}</p>
</div>
</Show>
<div
class="w-full flex items-center py-4 max-w-[256px]"
class="flex w-full max-w-[256px] items-center py-4"
classList={{
"justify-between": props.kind !== "onchain",
"justify-end": props.kind === "onchain"
@@ -88,7 +89,7 @@ export function IntegratedQr(props: {
<div class="text-black">
<AmountSats amountSats={Number(props.amountSats)} />
</div>
<div class="text-black text-sm">
<div class="text-sm text-black">
<AmountFiat amountSats={Number(props.amountSats)} />
</div>
</div>
@@ -98,10 +99,10 @@ export function IntegratedQr(props: {
<QRCodeSVG
value={props.value}
class="w-full h-full max-h-[256px]"
class="h-full max-h-[256px] w-full"
/>
<div
class="w-full grid gap-1 py-4 max-w-[256px] "
class="grid w-full max-w-[256px] gap-1 py-4 "
classList={{
"grid-cols-[2rem_minmax(0,1fr)_2rem]": !!navigator.share,
"grid-cols-[minmax(0,1fr)_2rem]": !navigator.share

View File

@@ -1,12 +1,13 @@
import { Dialog } from "@kobalte/core";
import { JSX, createMemo } from "solid-js";
import { createMemo, JSX } from "solid-js";
import {
ModalCloseButton,
SmallHeader,
CopyButton,
DIALOG_CONTENT,
DIALOG_POSITIONER,
ModalCloseButton,
OVERLAY,
CopyButton
SmallHeader
} from "~/components";
import { useI18n } from "~/i18n/context";
@@ -29,7 +30,7 @@ export function JsonModal(props: {
<Dialog.Overlay class={OVERLAY} />
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<div class="flex justify-between mb-2 items-center">
<div class="mb-2 flex items-center justify-between">
<Dialog.Title>
<SmallHeader>{props.title}</SmallHeader>
</Dialog.Title>
@@ -37,8 +38,8 @@ export function JsonModal(props: {
<ModalCloseButton />
</Dialog.CloseButton>
</div>
<Dialog.Description class="flex flex-col gap-4 items-center">
<div class="bg-white/5 rounded-xl max-h-[50vh] overflow-y-scroll disable-scrollbars p-4">
<Dialog.Description class="flex flex-col items-center gap-4">
<div class="max-h-[50vh] overflow-y-scroll rounded-xl bg-white/5 p-4 disable-scrollbars">
<pre class="whitespace-pre-wrap break-all">
{json()}
</pre>

View File

@@ -1,32 +1,33 @@
import { useMegaStore } from "~/state/megaStore";
import { Collapsible, TextField } from "@kobalte/core";
import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm";
import { ExternalLink } from "@mutinywallet/ui";
import {
createResource,
createSignal,
For,
Match,
Show,
Suspense,
Switch,
createResource,
createSignal
Switch
} from "solid-js";
import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm";
import { Collapsible, TextField } from "@kobalte/core";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import eify from "~/utils/eify";
import {
Button,
ConfirmDialog,
Hr,
Button,
InnerCard,
VStack,
showToast,
MiniStringShower,
ResetRouter,
Restart,
ResyncOnchain,
ResetRouter,
MiniStringShower
showToast,
VStack
} from "~/components";
import { Network } from "~/logic/mutinyWalletSetup";
import { ExternalLink } from "@mutinywallet/ui";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
// TODO: hopefully I don't have to maintain this type forever but I don't know how to pass it around otherwise
type RefetchPeersType = (
@@ -57,7 +58,7 @@ function PeerItem(props: { peer: MutinyPeer }) {
return (
<Collapsible.Root>
<Collapsible.Trigger class="w-full">
<h2 class="truncate text-start text-lg font-mono bg-neutral-200 text-black rounded px-4 py-2">
<h2 class="truncate rounded bg-neutral-200 px-4 py-2 text-start font-mono text-lg text-black">
{">"}{" "}
{props.peer.alias ? props.peer.alias : props.peer.pubkey}
</h2>
@@ -157,7 +158,7 @@ function ConnectPeer(props: { refetchPeers: RefetchPeersType }) {
{i18n.t("settings.admin.kitchen_sink.connect_peer")}
</TextField.Label>
<TextField.Input
class="w-full p-2 rounded-lg text-black"
class="w-full rounded-lg p-2 text-black"
placeholder="028241..."
/>
<TextField.ErrorMessage class="text-red-500">
@@ -207,7 +208,7 @@ function ChannelItem(props: { channel: MutinyChannel; network?: Network }) {
return (
<Collapsible.Root>
<Collapsible.Trigger class="w-full">
<h2 class="truncate text-start text-lg font-mono bg-neutral-200 text-black rounded px-4 py-2">
<h2 class="truncate rounded bg-neutral-200 px-4 py-2 text-start font-mono text-lg text-black">
{">"} {props.channel.peer}
</h2>
</Collapsible.Trigger>
@@ -386,7 +387,7 @@ function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) {
<TextField.Label class="text-sm font-semibold uppercase">
{i18n.t("settings.admin.kitchen_sink.pubkey")}
</TextField.Label>
<TextField.Input class="w-full p-2 rounded-lg text-black" />
<TextField.Input class="w-full rounded-lg p-2 text-black" />
</TextField.Root>
<TextField.Root
value={amount()}
@@ -398,7 +399,7 @@ function OpenChannel(props: { refetchChannels: RefetchChannelsListType }) {
</TextField.Label>
<TextField.Input
type="number"
class="w-full p-2 rounded-lg text-black"
class="w-full rounded-lg p-2 text-black"
/>
</TextField.Root>
<Button layout="small" type="submit">

View File

@@ -1,5 +1,6 @@
import { Progress } from "@kobalte/core";
import { Show } from "solid-js";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
@@ -29,11 +30,11 @@ export function LoadingBar(props: { value: number; max: number }) {
getValueLabel={({ value }) =>
i18n.t("modals.loading.loading", { stage: valueToStage(value) })
}
class="w-full flex flex-col gap-2"
class="flex w-full flex-col gap-2"
>
<Progress.ValueLabel class="text-sm text-m-grey-400" />
<Progress.Track class="h-6 bg-white/10 rounded">
<Progress.Fill class="bg-m-blue rounded h-full w-[var(--kb-progress-fill-width)] transition-[width]" />
<Progress.Track class="h-6 rounded bg-white/10">
<Progress.Fill class="h-full w-[var(--kb-progress-fill-width)] rounded bg-m-blue transition-[width]" />
</Progress.Track>
</Progress.Root>
);

View File

@@ -1,4 +1,5 @@
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { Button, InnerCard, NiceP, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { downloadTextFile } from "~/utils/download";

View File

@@ -1,14 +1,15 @@
import { Dialog } from "@kobalte/core";
import { ParentComponent, createSignal, JSXElement } from "solid-js";
import { ExternalLink } from "@mutinywallet/ui";
import { createSignal, JSXElement, ParentComponent } from "solid-js";
import help from "~/assets/icons/help.svg";
import {
DIALOG_CONTENT,
DIALOG_POSITIONER,
OVERLAY,
ModalCloseButton,
OVERLAY,
SmallHeader
} from "~/components";
import { ExternalLink } from "@mutinywallet/ui";
import help from "~/assets/icons/help.svg";
import { useI18n } from "~/i18n/context";
export function FeesModal(props: { icon?: boolean }) {
@@ -18,7 +19,7 @@ export function FeesModal(props: { icon?: boolean }) {
title={i18n.t("modals.more_info.whats_with_the_fees")}
linkText={
props.icon ? (
<img src={help} alt="help" class="w-4 h-4 cursor-pointer" />
<img src={help} alt="help" class="h-4 w-4 cursor-pointer" />
) : (
i18n.t("common.why")
)
@@ -44,7 +45,7 @@ export const MoreInfoModal: ParentComponent<{
return (
<Dialog.Root open={open()} onOpenChange={setOpen}>
<Dialog.Trigger>
<button class="underline decoration-light-text hover:decoration-white font-semibold">
<button class="font-semibold underline decoration-light-text hover:decoration-white">
{props.linkText}
</button>
</Dialog.Trigger>
@@ -52,7 +53,7 @@ export const MoreInfoModal: ParentComponent<{
<Dialog.Overlay class={OVERLAY} />
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<Dialog.Title class="flex justify-between mb-2 items-center">
<Dialog.Title class="mb-2 flex items-center justify-between">
<SmallHeader>{props.title}</SmallHeader>
<Dialog.CloseButton>
<ModalCloseButton />

View File

@@ -1,12 +1,12 @@
import mutiny_m from "~/assets/icons/m.svg";
import airplane from "~/assets/icons/airplane.svg";
import settings from "~/assets/icons/settings.svg";
import receive from "~/assets/icons/big-receive.svg";
import redshift from "~/assets/icons/rs.svg";
import userClock from "~/assets/icons/user-clock.svg";
import { A } from "solid-start";
import airplane from "~/assets/icons/airplane.svg";
import receive from "~/assets/icons/big-receive.svg";
import mutiny_m from "~/assets/icons/m.svg";
import redshift from "~/assets/icons/rs.svg";
import settings from "~/assets/icons/settings.svg";
import userClock from "~/assets/icons/user-clock.svg";
type ActiveTab =
| "home"
| "scan"
@@ -41,8 +41,8 @@ function NavBarItem(props: {
export function NavBar(props: { activeTab: ActiveTab }) {
return (
<nav class="hidden md:block fixed shadow-none z-40 safe-bottom top-0 bottom-auto left-0 h-full">
<ul class="flex flex-col justify-start gap-4 px-4 mt-4">
<nav class="fixed bottom-auto left-0 top-0 z-40 hidden h-full shadow-none safe-bottom md:block">
<ul class="mt-4 flex flex-col justify-start gap-4 px-4">
<NavBarItem
href="/"
icon={mutiny_m}

View File

@@ -1,8 +1,9 @@
import { Show } from "solid-js";
import { ButtonLink, SmallHeader } from "~/components";
import { useMegaStore } from "~/state/megaStore";
import save from "~/assets/icons/save.svg";
import { ButtonLink, SmallHeader } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
export function OnboardWarning() {
const i18n = useI18n();
@@ -11,9 +12,9 @@ export function OnboardWarning() {
return (
<>
<Show when={!state.has_backed_up}>
<div class="grid grid-cols-[auto_minmax(0,_1fr)_auto] rounded-xl p-4 gap-4 bg-neutral-950/50">
<div class="grid grid-cols-[auto_minmax(0,_1fr)_auto] gap-4 rounded-xl bg-neutral-950/50 p-4">
<div class="self-center">
<img src={save} alt="backup" class="w-8 h-8" />
<img src={save} alt="backup" class="h-8 w-8" />
</div>
<div class="flex flex-col justify-center">
<SmallHeader>

View File

@@ -1,25 +1,25 @@
import { NwcProfile } from "@mutinywallet/mutiny-wasm";
import { formatExpiration } from "~/utils/prettyPrintTime";
import { Card, VStack, ActivityAmount, InfoBox } from "~/components";
import { LoadingSpinner } from "@mutinywallet/ui";
import bolt from "~/assets/icons/bolt.svg";
import {
createEffect,
createResource,
createSignal,
For,
Match,
Show,
Switch,
createEffect,
createResource,
createSignal
Switch
} from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { A } from "solid-start";
import bolt from "~/assets/icons/bolt.svg";
import greenCheck from "~/assets/icons/green-check.svg";
import redClose from "~/assets/icons/red-close.svg";
import eify from "~/utils/eify";
import { A } from "solid-start";
import { createDeepSignal } from "~/utils/deepSignal";
import { ActivityAmount, Card, InfoBox, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { createDeepSignal } from "~/utils/deepSignal";
import eify from "~/utils/eify";
import { formatExpiration } from "~/utils/prettyPrintTime";
type PendingItem = {
id: string;
@@ -118,14 +118,14 @@ export function PendingNwc() {
</Show>
<For each={pendingRequests()}>
{(pendingItem) => (
<div class="grid grid-cols-[auto_minmax(0,_1fr)_minmax(0,_max-content)_auto] items-center pb-4 gap-4 border-b border-neutral-800 last:border-b-0">
<div class="grid grid-cols-[auto_minmax(0,_1fr)_minmax(0,_max-content)_auto] items-center gap-4 border-b border-neutral-800 pb-4 last:border-b-0">
<img
class="w-[1rem]"
src={bolt}
alt="onchain"
/>
<div class="flex flex-col">
<span class="text-base font-semibold truncate">
<span class="truncate text-base font-semibold">
{pendingItem.name_of_connection}
</span>
<time class="text-sm text-neutral-500">
@@ -141,7 +141,7 @@ export function PendingNwc() {
price={state.price}
/>
</div>
<div class="flex gap-2 w-[5rem]">
<div class="flex w-[5rem] gap-2">
<Switch>
<Match
when={paying() !== pendingItem.id}
@@ -182,7 +182,7 @@ export function PendingNwc() {
</VStack>
<A
href="/settings/connections"
class="text-m-red active:text-m-red/80 font-semibold no-underline self-center"
class="self-center font-semibold text-m-red no-underline active:text-m-red/80"
>
{i18n.t("settings.connections.pending_nwc.configure_link")}
</A>

View File

@@ -1,12 +1,12 @@
import { onCleanup, onMount } from "solid-js";
import { Capacitor } from "@capacitor/core";
import {
BarcodeScanner,
BarcodeFormat,
BarcodeScanner,
PermissionStates,
ScanResult
} from "@mutinywallet/barcode-scanner";
import QrScanner from "qr-scanner";
import { Capacitor } from "@capacitor/core";
import { onCleanup, onMount } from "solid-js";
export function Scanner(props: { onResult: (result: string) => void }) {
let container: HTMLVideoElement | undefined;
@@ -80,7 +80,7 @@ export function Scanner(props: { onResult: (result: string) => void }) {
<div id="video-container">
<video
ref={container}
class="w-full h-full fixed object-cover bg-transparent"
class="fixed h-full w-full bg-transparent object-cover"
/>
</div>
</>

View File

@@ -1,6 +1,6 @@
import { Button, InnerCard, NiceP, VStack } from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
export function ResetRouter() {
const i18n = useI18n();

View File

@@ -1,4 +1,5 @@
import { createSignal } from "solid-js";
import { Button, InnerCard, NiceP, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";

View File

@@ -1,7 +1,8 @@
import { For, Match, Switch, createMemo, createSignal } from "solid-js";
import { useCopy } from "~/utils/useCopy";
import { createMemo, createSignal, For, Match, Switch } from "solid-js";
import copyIcon from "~/assets/icons/copy.svg";
import { useI18n } from "~/i18n/context";
import { useCopy } from "~/utils/useCopy";
export function SeedWords(props: {
words: string;
@@ -25,11 +26,11 @@ export function SeedWords(props: {
}
return (
<div class="flex flex-col gap-4 bg-m-red p-4 rounded-xl overflow-hidden">
<div class="flex flex-col gap-4 overflow-hidden rounded-xl bg-m-red p-4">
<Switch>
<Match when={!shouldShow()}>
<div
class="cursor-pointer flex w-full justify-center"
class="flex w-full cursor-pointer justify-center"
onClick={toggleShow}
>
<code class="text-red">
@@ -41,17 +42,17 @@ export function SeedWords(props: {
<Match when={shouldShow()}>
<>
<div
class="cursor-pointer flex w-full justify-center"
class="flex w-full cursor-pointer justify-center"
onClick={toggleShow}
>
<code class="text-red">
{i18n.t("settings.backup.seed_words.hide")}
</code>
</div>
<ol class="overflow-hidden columns-2 w-full list-decimal list-inside">
<ol class="w-full list-inside list-decimal columns-2 overflow-hidden">
<For each={splitWords()}>
{(word) => (
<li class="font-mono text-left min-w-fit bg">
<li class="bg min-w-fit text-left font-mono">
{word}
</li>
)}
@@ -60,7 +61,7 @@ export function SeedWords(props: {
<div class="flex w-full justify-center">
<button
onClick={dangerouslyCopy}
class="bg-white/10 hover:bg-white/20 p-2 rounded-lg"
class="rounded-lg bg-white/10 p-2 hover:bg-white/20"
>
<div class="flex items-center gap-2">
<span>
@@ -75,7 +76,7 @@ export function SeedWords(props: {
<img
src={copyIcon}
alt="copy"
class="w-4 h-4"
class="h-4 w-4"
/>
</div>
</button>

View File

@@ -1,24 +1,25 @@
import { Title } from "solid-start";
import {
DefaultMain,
LargeHeader,
NiceP,
SafeArea,
SmallHeader,
ImportExport,
Logs,
DeleteEverything
} from "~/components";
import { ExternalLink } from "@mutinywallet/ui";
import { Match, Switch } from "solid-js";
import { FeedbackLink } from "~/routes/Feedback";
import { Title } from "solid-start";
import {
DefaultMain,
DeleteEverything,
ImportExport,
LargeHeader,
Logs,
NiceP,
SafeArea,
SmallHeader
} from "~/components";
import { useI18n } from "~/i18n/context";
import { FeedbackLink } from "~/routes/Feedback";
function ErrorFooter() {
return (
<>
<div class="h-full" />
<div class="self-center mt-4">
<div class="mt-4 self-center">
<FeedbackLink setupError={true} />
</div>
</>
@@ -40,7 +41,7 @@ export function SetupErrorDisplay(props: { initialError: Error }) {
<LargeHeader>
{i18n.t("error.on_boot.loading_failed.header")}
</LargeHeader>
<p class="bg-white/10 rounded-xl p-4 font-mono">
<p class="rounded-xl bg-white/10 p-4 font-mono">
<span class="font-bold">{error.name}</span>:{" "}
{error.message}
</p>
@@ -82,7 +83,7 @@ export function SetupErrorDisplay(props: { initialError: Error }) {
<LargeHeader>
{i18n.t("error.on_boot.existing_tab.title")}
</LargeHeader>
<p class="bg-white/10 rounded-xl p-4 font-mono">
<p class="rounded-xl bg-white/10 p-4 font-mono">
<span class="font-bold">{error.name}</span>:{" "}
{error.message}
</p>
@@ -102,7 +103,7 @@ export function SetupErrorDisplay(props: { initialError: Error }) {
"error.on_boot.incompatible_browser.header"
)}
</LargeHeader>
<p class="bg-white/10 rounded-xl p-4 font-mono">
<p class="rounded-xl bg-white/10 p-4 font-mono">
<span class="font-bold">{error.name}</span>:{" "}
{error.message}
</p>
@@ -138,7 +139,7 @@ export function SetupErrorDisplay(props: { initialError: Error }) {
<LargeHeader>
{i18n.t("error.on_boot.loading_failed.header")}
</LargeHeader>
<p class="bg-white/10 rounded-xl p-4 font-mono">
<p class="rounded-xl bg-white/10 p-4 font-mono">
<span class="font-bold">{error.name}</span>:{" "}
{error.message}
</p>
@@ -160,7 +161,7 @@ export function SetupErrorDisplay(props: { initialError: Error }) {
</NiceP>
<ImportExport emergency />
<Logs />
<div class="rounded-xl p-4 flex flex-col gap-2 bg-m-red">
<div class="flex flex-col gap-2 rounded-xl bg-m-red p-4">
<SmallHeader>
{i18n.t("settings.danger_zone")}
</SmallHeader>

View File

@@ -1,12 +1,13 @@
import { Card, VStack, JsonModal } from "~/components";
import { useCopy } from "~/utils/useCopy";
import copyIcon from "~/assets/icons/copy.svg";
import { createSignal, Show } from "solid-js";
import copyBlack from "~/assets/icons/copy-black.svg";
import shareIcon from "~/assets/icons/share.svg";
import shareBlack from "~/assets/icons/share-black.svg";
import copyIcon from "~/assets/icons/copy.svg";
import eyeIcon from "~/assets/icons/eye.svg";
import { Show, createSignal } from "solid-js";
import shareBlack from "~/assets/icons/share-black.svg";
import shareIcon from "~/assets/icons/share.svg";
import { Card, JsonModal, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useCopy } from "~/utils/useCopy";
const STYLE =
"px-4 py-2 rounded-xl border-2 border-white flex gap-2 items-center font-semibold hover:text-m-blue transition-colors";
@@ -68,7 +69,7 @@ export function StringShower(props: { text: string }) {
title={i18n.t("modals.details")}
setOpen={setOpen}
/>
<div class="w-full grid grid-cols-[minmax(0,_1fr)_auto]">
<div class="grid w-full grid-cols-[minmax(0,_1fr)_auto]">
<TruncateMiddle text={props.text} />
<button class="w-[2rem]" onClick={() => setOpen(true)}>
<img src={eyeIcon} alt="eye" />
@@ -105,7 +106,7 @@ export function ShareCard(props: { text?: string }) {
<Card>
<StringShower text={props.text ?? ""} />
<VStack>
<div class="flex gap-4 justify-center">
<div class="flex justify-center gap-4">
<CopyButton text={props.text ?? ""} />
<Show when={navigator.share}>
<ShareButton receiveString={props.text ?? ""} />

View File

@@ -1,9 +1,12 @@
import { Select, createOptions } from "@thisbeyond/solid-select";
import { createOptions, Select } from "@thisbeyond/solid-select";
import "~/styles/solid-select.css";
import { For, Show, createMemo, createSignal, onMount } from "solid-js";
import { createMemo, createSignal, For, onMount, Show } from "solid-js";
import { TinyButton } from "~/components";
import { MutinyTagItem, sortByLastUsed } from "~/utils/tags";
import { useMegaStore } from "~/state/megaStore";
import { MutinyTagItem, sortByLastUsed } from "~/utils/tags";
const createLabelValue = (label: string): Partial<MutinyTagItem> => {
return { name: label, kind: "Contact" };
@@ -57,7 +60,7 @@ export function TagEditor(props: {
};
return (
<div class="flex flex-col gap-2 flex-shrink flex-1">
<div class="flex flex-1 flex-shrink flex-col gap-2">
<Select
multiple
initialValue={props.selectedValues}
@@ -65,7 +68,7 @@ export function TagEditor(props: {
onChange={onChange}
{...selectProps()}
/>
<div class="flex gap-2 flex-wrap">
<div class="flex flex-wrap gap-2">
<Show when={availableTags() && availableTags()!.length > 0}>
<For each={availableTags()!.slice(0, 3)}>
{(tag) => (

View File

@@ -1,13 +1,14 @@
import { Toast, toaster } from "@kobalte/core";
import { Portal } from "solid-js/web";
import close from "~/assets/icons/close.svg";
import { SmallHeader } from "~/components";
export function Toaster() {
return (
<Portal>
<Toast.Region class="z-[9999] top-0 fixed flex gap-4 w-full justify-center safe-top safe-left safe-right safe-bottom">
<Toast.List class="max-w-[100vw] w-[400px] mt-8 flex flex-col gap-4" />
<Toast.Region class="fixed top-0 z-[9999] flex w-full justify-center gap-4 safe-top safe-left safe-right safe-bottom">
<Toast.List class="mt-8 flex w-[400px] max-w-[100vw] flex-col gap-4" />
</Toast.Region>
</Portal>
);
@@ -45,11 +46,11 @@ export function ToastItem(props: {
return (
<Toast.Root
toastId={props.toastId}
class={`w-[80vw] max-w-[400px] mx-auto p-4 bg-neutral-900/80 backdrop-blur-md shadow-xl rounded-xl border ${
class={`mx-auto w-[80vw] max-w-[400px] rounded-xl border bg-neutral-900/80 p-4 shadow-xl backdrop-blur-md ${
props.isError ? "border-m-red/50" : "border-white/10"
} `}
>
<div class="flex gap-4 w-full justify-between items-start">
<div class="flex w-full items-start justify-between gap-4">
<div class="flex-1">
<Toast.Title>
<SmallHeader>{props.title}</SmallHeader>
@@ -58,7 +59,7 @@ export function ToastItem(props: {
<p>{props.description}</p>
</Toast.Description>
</div>
<Toast.CloseButton class="hover:bg-white/10 rounded-lg active:bg-m-blue flex-0 w-8 h-8">
<Toast.CloseButton class="flex-0 h-8 w-8 rounded-lg hover:bg-white/10 active:bg-m-blue">
<img src={close} alt="Close" />
</Toast.CloseButton>
</div>

View File

@@ -10,7 +10,7 @@ export function BackButton(props: {
return (
<button
onClick={() => props.onClick()}
class="text-m-red active:text-m-red/80 text-xl font-semibold no-underline md:hidden flex items-center"
class="flex items-center text-xl font-semibold text-m-red no-underline active:text-m-red/80 md:hidden"
classList={{ "md:!flex": props.showOnDesktop }}
>
<Back />

View File

@@ -1,4 +1,5 @@
import { A } from "solid-start";
import { Back } from "~/assets/svg/Back";
import { useI18n } from "~/i18n/context";
@@ -7,7 +8,7 @@ export function BackLink(props: { href?: string; title?: string }) {
return (
<A
href={props.href ? props.href : "/"}
class="text-m-red active:text-m-red/80 text-xl font-semibold no-underline md:hidden flex items-center"
class="flex items-center text-xl font-semibold text-m-red no-underline active:text-m-red/80 md:hidden"
>
<Back />
{props.title ? props.title : i18n.t("common.home")}

View File

@@ -1,4 +1,5 @@
import { useLocation, useNavigate } from "solid-start";
import { BackButton } from "~/components";
import { useI18n } from "~/i18n/context";

View File

@@ -1,8 +1,8 @@
import { LoadingSpinner } from "@mutinywallet/ui";
import { cva, VariantProps } from "class-variance-authority";
import { children, JSX, ParentComponent, Show, splitProps } from "solid-js";
import { Dynamic } from "solid-js/web";
import { A } from "solid-start";
import { LoadingSpinner } from "@mutinywallet/ui";
const button = cva(
"p-3 rounded-xl font-semibold transition disabled:bg-neutral-400/10 disabled:text-white/20 disabled:shadow-inner-button-disabled",

View File

@@ -1,29 +1,30 @@
import {
Collapsible,
Dialog,
Checkbox as KCheckbox,
Separator
} from "@kobalte/core";
import { LoadingSpinner } from "@mutinywallet/ui";
import {
createResource,
createSignal,
JSX,
Match,
ParentComponent,
Show,
Suspense,
Switch,
createResource,
createSignal
Switch
} from "solid-js";
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 check from "~/assets/icons/check.svg";
import close from "~/assets/icons/close.svg";
import down from "~/assets/icons/down.svg";
import { LoadingIndicator, DecryptDialog } from "~/components";
import { LoadingSpinner } from "@mutinywallet/ui";
import { DecryptDialog, LoadingIndicator } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { generateGradient } from "~/utils/gradientHash";
import { MutinyTagItem } from "~/utils/tags";
export const SmallHeader: ParentComponent<{ class?: string }> = (props) => {
return (
@@ -38,7 +39,7 @@ export const Card: ParentComponent<{
titleElement?: JSX.Element;
}> = (props) => {
return (
<div class="rounded-xl p-4 flex flex-col gap-2 bg-neutral-950/50 w-full">
<div class="flex w-full flex-col gap-2 rounded-xl bg-neutral-950/50 p-4">
{props.title && <SmallHeader>{props.title}</SmallHeader>}
{props.titleElement && props.titleElement}
{props.children}
@@ -48,7 +49,7 @@ export const Card: ParentComponent<{
export const InnerCard: ParentComponent<{ title?: string }> = (props) => {
return (
<div class="rounded-xl p-4 flex flex-col gap-2 border border-white/10 bg-[rgba(255,255,255,0.05)]">
<div class="flex flex-col gap-2 rounded-xl border border-white/10 bg-[rgba(255,255,255,0.05)] p-4">
{props.title && <SmallHeader>{props.title}</SmallHeader>}
{props.children}
</div>
@@ -61,7 +62,7 @@ export const FancyCard: ParentComponent<{
tag?: JSX.Element;
}> = (props) => {
return (
<div class="border border-black/50 rounded-xl border-b-4 p-4 flex flex-col gap-2 bg-m-grey-800 shadow-fancy-card">
<div class="flex flex-col gap-2 rounded-xl border border-b-4 border-black/50 bg-m-grey-800 p-4 shadow-fancy-card">
{props.children}
</div>
);
@@ -75,7 +76,7 @@ export const SettingsCard: ParentComponent<{
<div class="mt-2 pl-4">
<SmallHeader>{props.title}</SmallHeader>
</div>
<div class="rounded-xl py-4 flex flex-col gap-2 bg-m-grey-800 w-full">
<div class="flex w-full flex-col gap-2 rounded-xl bg-m-grey-800 py-4">
{props.children}
</div>
</VStack>
@@ -89,14 +90,14 @@ export const Collapser: ParentComponent<{
}> = (props) => {
return (
<Collapsible.Root class="collapsible">
<Collapsible.Trigger class="flex w-full justify-between py-2 hover:bg-m-grey-750 active:bg-m-grey-900 px-4">
<Collapsible.Trigger class="flex w-full justify-between px-4 py-2 hover:bg-m-grey-750 active:bg-m-grey-900">
<div class="flex items-center gap-2">
<Switch>
<Match when={props.activityLight === "on"}>
<div class="w-2 h-2 rounded-full bg-m-green" />
<div class="h-2 w-2 rounded-full bg-m-green" />
</Match>
<Match when={props.activityLight === "off"}>
<div class="w-2 h-2 rounded-full bg-m-red" />
<div class="h-2 w-2 rounded-full bg-m-red" />
</Match>
</Switch>
<span>{props.title}</span>
@@ -107,7 +108,7 @@ export const Collapser: ParentComponent<{
class="collapsible__trigger-icon"
/>
</Collapsible.Trigger>
<Collapsible.Content class="p-4 bg-m-grey-900 shadow-inner">
<Collapsible.Content class="bg-m-grey-900 p-4 shadow-inner">
{props.children}
</Collapsible.Content>
</Collapsible.Root>
@@ -126,7 +127,7 @@ export const SafeArea: ParentComponent = (props) => {
export const DefaultMain: ParentComponent = (props) => {
return (
<main class="w-full max-w-[600px] flex flex-col gap-4 mx-auto p-4 h-full">
<main class="mx-auto flex h-full w-full max-w-[600px] flex-col gap-4 p-4">
{props.children}
{/* CSS is hard sometimes */}
<div class="py-4" />
@@ -143,7 +144,7 @@ export const FullscreenLoader = () => {
}, 10000);
return (
<div class="w-full h-[100dvh] flex flex-col gap-4 justify-center items-center">
<div class="flex h-[100dvh] w-full flex-col items-center justify-center gap-4">
<LoadingSpinner wide />
<Show when={waitedTooLong()}>
<p class="max-w-[20rem] text-neutral-400">
@@ -186,7 +187,7 @@ export const LargeHeader: ParentComponent<{
}> = (props) => {
return (
<header
class="w-full flex justify-between items-center mt-4 mb-2"
class="mb-2 mt-4 flex w-full items-center justify-between"
classList={{
"justify-between": !props.centered,
"justify-center": props.centered
@@ -236,7 +237,7 @@ export const SmallAmount: ParentComponent<{
sign?: string;
}> = (props) => {
return (
<h2 class="font-light text-lg">
<h2 class="text-lg font-light">
{props.sign ? `${props.sign} ` : ""}
{props.amount.toLocaleString()} <span class="text-sm">SATS</span>
</h2>
@@ -248,7 +249,7 @@ export const NiceP: ParentComponent = (props) => {
};
export const TinyText: ParentComponent = (props) => {
return <p class="text-neutral-400 text-sm">{props.children}</p>;
return <p class="text-sm text-neutral-400">{props.children}</p>;
};
export const TinyButton: ParentComponent<{
@@ -267,7 +268,7 @@ export const TinyButton: ParentComponent<{
return (
<button
class="py-1 px-2 rounded-lg bg-white/10"
class="rounded-lg bg-white/10 px-2 py-1"
onClick={() => props.onClick()}
style={{ background: bg() }}
>
@@ -278,7 +279,7 @@ export const TinyButton: ParentComponent<{
export const Indicator: ParentComponent = (props) => {
return (
<div class="box-border animate-pulse px-2 py-1 -my-1 bg-white/70 rounded text-xs uppercase text-black">
<div class="-my-1 box-border animate-pulse rounded bg-white/70 px-2 py-1 text-xs uppercase text-black">
{props.children}
</div>
);
@@ -301,12 +302,12 @@ export function Checkbox(props: {
onChange={props.onChange}
>
<KCheckbox.Input class="" />
<KCheckbox.Control class="flex-0 w-8 h-8 rounded-lg border-2 border-white bg-neutral-800 ui-checked:bg-m-red">
<KCheckbox.Control class="flex-0 h-8 w-8 rounded-lg border-2 border-white bg-neutral-800 ui-checked:bg-m-red">
<KCheckbox.Indicator>
<img src={check} class="w-8 h-8" alt="check" />
<img src={check} class="h-8 w-8" alt="check" />
</KCheckbox.Indicator>
</KCheckbox.Control>
<KCheckbox.Label class="flex-1 text-xl font-light flex flex-col gap-1">
<KCheckbox.Label class="flex flex-1 flex-col gap-1 text-xl font-light">
{props.label}
<Show when={props.caption}>
<TinyText>{props.caption}</TinyText>
@@ -318,8 +319,8 @@ export function Checkbox(props: {
export function ModalCloseButton() {
return (
<button class="self-center justify-self-center hover:bg-white/10 rounded-lg active:bg-m-blue">
<img src={close} alt="Close" class="w-8 h-8" />
<button class="self-center justify-self-center rounded-lg hover:bg-white/10 active:bg-m-blue">
<img src={close} alt="Close" class="h-8 w-8" />
</button>
);
}
@@ -344,7 +345,7 @@ export const SimpleDialog: ParentComponent<{
<Dialog.Overlay class={SIMPLE_OVERLAY} />
<div class={SIMPLE_DIALOG_POSITIONER}>
<Dialog.Content class={SIMPLE_DIALOG_CONTENT}>
<div class="flex justify-between mb-2 items-center">
<div class="mb-2 flex items-center justify-between">
<Dialog.Title>
<SmallHeader>{props.title}</SmallHeader>
</Dialog.Title>

View File

@@ -1,4 +1,5 @@
import { Progress } from "@kobalte/core";
import { SmallHeader } from "~/components";
import { useI18n } from "~/i18n/context";
@@ -35,7 +36,7 @@ export function ProgressBar(props: { value: number; max: number }) {
"send.progress_bar.sats_sent"
)}`
}
class="w-full flex flex-col gap-2"
class="flex w-full flex-col gap-2"
>
<div class="flex justify-between">
<Progress.Label>
@@ -43,8 +44,8 @@ export function ProgressBar(props: { value: number; max: number }) {
</Progress.Label>
<Progress.ValueLabel class="text-sm font-semibold uppercase" />
</div>
<Progress.Track class="h-6 bg-white/10 rounded">
<Progress.Fill class="bg-m-red rounded h-full w-[var(--kb-progress-fill-width)] transition-[width]" />
<Progress.Track class="h-6 rounded bg-white/10">
<Progress.Fill class="h-full w-[var(--kb-progress-fill-width)] rounded bg-m-red transition-[width]" />
</Progress.Track>
</Progress.Root>
);

View File

@@ -36,7 +36,7 @@ export function StyledRadioGroup(props: {
{(choice) => (
<RadioGroup.Item
value={choice.value}
class={`ui-checked:bg-neutral-950 bg-white/10 rounded outline outline-black/50 ui-checked:outline-m-blue ui-checked:outline-2`}
class={`rounded bg-white/10 outline outline-black/50 ui-checked:bg-neutral-950 ui-checked:outline-2 ui-checked:outline-m-blue`}
classList={{
"ui-checked:outline-m-red": props.accent === "red",
"ui-checked:outline-white":
@@ -45,12 +45,12 @@ export function StyledRadioGroup(props: {
}}
disabled={choice.disabled}
>
<div class={props.small ? "py-2 px-2" : "py-3 px-4"}>
<div class={props.small ? "px-2 py-2" : "px-4 py-3"}>
<RadioGroup.ItemInput />
<RadioGroup.ItemControl>
<RadioGroup.ItemIndicator />
</RadioGroup.ItemControl>
<RadioGroup.ItemLabel class="ui-checked:text-white text-neutral-400">
<RadioGroup.ItemLabel class="text-neutral-400 ui-checked:text-white">
<div class="block">
<div
classList={{

View File

@@ -1,5 +1,6 @@
import { TextField as KTextField } from "@kobalte/core";
import { type JSX, Show, splitProps } from "solid-js";
import { Show, splitProps, type JSX } from "solid-js";
import { TinyText } from "~/components";
export type TextFieldProps = {
@@ -41,7 +42,7 @@ export function TextField(props: TextFieldProps) {
required={props.required}
>
<Show when={props.label}>
<KTextField.Label class="text-sm uppercase font-semibold">
<KTextField.Label class="text-sm font-semibold uppercase">
{props.label}
</KTextField.Label>
</Show>
@@ -51,14 +52,14 @@ export function TextField(props: TextFieldProps) {
<KTextField.Input
{...fieldProps}
type={props.type}
class="w-full p-2 rounded-lg bg-white/10 placeholder-neutral-400"
class="w-full rounded-lg bg-white/10 p-2 placeholder-neutral-400"
/>
}
>
<KTextField.TextArea
{...fieldProps}
autoResize
class="w-full p-2 rounded-lg bg-white/10 placeholder-neutral-400"
class="w-full rounded-lg bg-white/10 p-2 placeholder-neutral-400"
/>
</Show>
<KTextField.ErrorMessage class="text-m-red">

View File

@@ -5,7 +5,7 @@ export function MegaCheck() {
<img
src={megacheck}
alt="success"
class="w-1/2 mx-auto max-w-[50vh] flex-shrink"
class="mx-auto w-1/2 max-w-[50vh] flex-shrink"
/>
);
}

View File

@@ -5,7 +5,7 @@ export function MegaEx() {
<img
src={megaex}
alt="fail"
class="w-1/2 mx-auto max-w-[30vh] flex-shrink"
class="mx-auto w-1/2 max-w-[30vh] flex-shrink"
/>
);
}

View File

@@ -1,8 +1,9 @@
import { Dialog } from "@kobalte/core";
import { JSX } from "solid-js";
import { Button } from "~/components";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
import { useI18n } from "~/i18n/context";
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
type SuccessModalProps = {
open: boolean;
@@ -24,10 +25,10 @@ export function SuccessModal(props: SuccessModalProps) {
<Dialog.Portal>
<div class={DIALOG_POSITIONER}>
<Dialog.Content class={DIALOG_CONTENT}>
<Dialog.Description class="flex flex-col items-center justify-center gap-6 h-full w-full max-w-[400px] mx-auto">
<Dialog.Description class="mx-auto flex h-full w-full max-w-[400px] flex-col items-center justify-center gap-6">
{props.children}
</Dialog.Description>
<div class="w-full flex max-w-[300px] mx-auto">
<div class="mx-auto flex w-full max-w-[300px]">
<Button onClick={onNice} intent="inactive">
{props.confirmText ??
`${i18n.t("common.nice")}`}

View File

@@ -2,9 +2,10 @@ import { use } from "i18next";
// FIXME: this doesn't work when deployed
// import HttpApi from 'i18next-http-backend';
import LanguageDetector from "i18next-browser-languagedetector";
import en from "~/i18n/en/translations";
import pt from "~/i18n/pt/translations";
import ko from "~/i18n/ko/translations";
import pt from "~/i18n/pt/translations";
export const resources = {
en: {

View File

@@ -1,5 +1,5 @@
import { createContext, useContext } from "solid-js";
import { i18n } from "i18next";
import { createContext, useContext } from "solid-js";
export const I18nContext = createContext<i18n>();

View File

@@ -1,4 +1,4 @@
import { resources, defaultNS } from "~/i18n/config";
import { defaultNS, resources } from "~/i18n/config";
declare module "i18next" {
interface CustomTypeOptions {

View File

@@ -1,4 +1,5 @@
import initWaila, { PaymentParams } from "@mutinywallet/waila-wasm";
import { Result } from "~/utils/typescript";
// Make sure we've initialzied waila before we try to use it

View File

@@ -12,10 +12,12 @@ import {
Scripts,
Title
} from "solid-start";
// eslint-disable-next-line
import "@mutinywallet/ui/style.css";
import { ErrorDisplay, I18nProvider, Toaster } from "~/components";
import { Provider as MegaStoreProvider } from "~/state/megaStore";
import { Toaster, ErrorDisplay, I18nProvider } from "~/components";
export default function Root() {
return (

View File

@@ -1,27 +1,28 @@
import { For, Show, Suspense, createResource } from "solid-js";
import { Tabs } from "@kobalte/core";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { createResource, For, Show, Suspense } from "solid-js";
import {
BackLink,
Button,
Card,
DefaultMain,
LargeHeader,
NiceP,
MutinyWalletGuard,
SafeArea,
VStack,
NavBar,
BackLink,
CombinedActivity,
ContactEditor,
ContactFormValues,
ContactViewer,
DefaultMain,
LargeHeader,
LoadingShimmer,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
showToast,
LoadingShimmer
VStack
} from "~/components";
import { Tabs } from "@kobalte/core";
import { gradientsPerContact } from "~/utils/gradientHash";
import { useMegaStore } from "~/state/megaStore";
import { Contact } from "@mutinywallet/mutiny-wasm";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { gradientsPerContact } from "~/utils/gradientHash";
function ContactRow() {
const i18n = useI18n();
@@ -67,7 +68,7 @@ function ContactRow() {
<div class="flex gap-4">
<ContactEditor list createContact={createContact} />
<Show when={contacts()}>
<div class="flex gap-4 flex-1 overflow-x-scroll disable-scrollbars">
<div class="flex flex-1 gap-4 overflow-x-scroll disable-scrollbars">
<For each={contacts()}>
{(contact) => (
<ContactViewer
@@ -97,7 +98,7 @@ export default function Activity() {
<LargeHeader>{i18n.t("activity.title")}</LargeHeader>
<ContactRow />
<Tabs.Root defaultValue="mutiny">
<Tabs.List class="relative flex justify-around mt-4 mb-8 gap-1 bg-neutral-950 p-1 rounded-xl">
<Tabs.List class="relative mb-8 mt-4 flex justify-around gap-1 rounded-xl bg-neutral-950 p-1">
<Tabs.Trigger value="mutiny" class={TAB}>
{i18n.t("activity.mutiny")}
</Tabs.Trigger>
@@ -124,7 +125,7 @@ export default function Activity() {
</Tabs.Content>
<Tabs.Content value="nostr">
<VStack>
<div class="my-8 flex flex-col items-center gap-4 text-center max-w-[20rem] mx-auto">
<div class="mx-auto my-8 flex max-w-[20rem] flex-col items-center gap-4 text-center">
<NiceP>
{i18n.t("activity.import_contacts")}
</NiceP>

View File

@@ -1,14 +1,19 @@
import {
SubmitHandler,
createForm,
email,
getValue,
required,
setValue
setValue,
SubmitHandler
} from "@modular-forms/solid";
import { Match, Show, Switch, createSignal } from "solid-js";
import { ExternalLink } from "@mutinywallet/ui";
import { createSignal, Match, Show, Switch } from "solid-js";
import { A, useLocation } from "solid-start";
import feedback from "~/assets/icons/feedback.svg";
import { InfoBox, MegaCheck, NavBar } from "~/components";
import {
BackPop,
Button,
ButtonLink,
Checkbox,
@@ -16,16 +21,12 @@ import {
LargeHeader,
NiceP,
SafeArea,
VStack,
BackPop,
StyledRadioGroup,
TextField
TextField,
VStack
} from "~/components/layout";
import { ExternalLink } from "@mutinywallet/ui";
import feedback from "~/assets/icons/feedback.svg";
import eify from "~/utils/eify";
import { useI18n } from "~/i18n/context";
import { InfoBox, MegaCheck, NavBar } from "~/components";
import eify from "~/utils/eify";
const FEEDBACK_API = import.meta.env.VITE_FEEDBACK;
@@ -34,7 +35,7 @@ export function FeedbackLink(props: { setupError?: boolean }) {
const location = useLocation();
return (
<A
class="font-semibold no-underline text-m-grey-350 flex gap-2 items-center"
class="flex items-center gap-2 font-semibold text-m-grey-350 no-underline"
state={{
previous: location.pathname,
// If we're coming from an error page we want to know that so we can hide the navbar
@@ -303,7 +304,7 @@ export default function Feedback() {
<Switch>
<Match when={submitted()}>
<div class="flex flex-col gap-4 items-center h-full">
<div class="flex h-full flex-col items-center gap-4">
<MegaCheck />
<LargeHeader centered>
{i18n.t("feedback.received")}

View File

@@ -3,6 +3,7 @@ import {
MutinyBip21RawMaterials,
MutinyInvoice
} from "@mutinywallet/mutiny-wasm";
import { ExternalLink } from "@mutinywallet/ui";
import {
createEffect,
createMemo,
@@ -13,42 +14,42 @@ import {
Show,
Switch
} from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { objectToSearchParams } from "~/utils/objectToSearchParams";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { useNavigate } from "solid-start";
import side2side from "~/assets/icons/side-to-side.svg";
import {
Fee,
AmountCard,
AmountFiat,
AmountSats,
BackButton,
BackLink,
Button,
Card,
DefaultMain,
Indicator,
LargeHeader,
MutinyWalletGuard,
SafeArea,
SimpleDialog,
NavBar,
AmountSats,
AmountFiat,
BackLink,
TagEditor,
StyledRadioGroup,
showToast,
AmountCard,
BackButton,
SuccessModal,
MegaCheck,
InfoBox,
Fee,
FeesModal,
IntegratedQr
Indicator,
InfoBox,
IntegratedQr,
LargeHeader,
MegaCheck,
MutinyWalletGuard,
NavBar,
SafeArea,
showToast,
SimpleDialog,
StyledRadioGroup,
SuccessModal,
TagEditor
} from "~/components";
import { ExternalLink } from "@mutinywallet/ui";
import { MutinyTagItem } from "~/utils/tags";
import { Network } from "~/logic/mutinyWalletSetup";
import side2side from "~/assets/icons/side-to-side.svg";
import eify from "~/utils/eify";
import { matchError } from "~/logic/errorDispatch";
import { useI18n } from "~/i18n/context";
import { matchError } from "~/logic/errorDispatch";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { objectToSearchParams } from "~/utils/objectToSearchParams";
import { MutinyTagItem } from "~/utils/tags";
type OnChainTx = {
transaction: {
@@ -290,9 +291,8 @@ export default function Receive() {
try {
// Lightning invoice might be blank
if (lightning) {
const invoice = await state.mutiny_wallet?.get_invoice(
lightning
);
const invoice =
await state.mutiny_wallet?.get_invoice(lightning);
// If the invoice has a fees amount that's probably the LSP fee
if (invoice?.fees_paid) {
@@ -368,7 +368,7 @@ export default function Receive() {
</LargeHeader>
<Switch>
<Match when={!unified() || receiveState() === "edit"}>
<div class="flex flex-col flex-1 gap-8">
<div class="flex flex-1 flex-col gap-8">
<AmountCard
initialOpen={shouldShowAmountEditor()}
amountSats={amount() || "0"}
@@ -406,19 +406,19 @@ export default function Receive() {
amountSats={amount() || "0"}
kind={flavor()}
/>
<p class="text-neutral-400 text-center">
<p class="text-center text-neutral-400">
{i18n.t("receive.keep_mutiny_open")}
</p>
{/* Only show method chooser when we have an invoice */}
<Show when={bip21Raw()?.invoice}>
<button
class="font-bold text-m-grey-400 flex gap-2 p-2 items-center mx-auto"
class="mx-auto flex items-center gap-2 p-2 font-bold text-m-grey-400"
onClick={() => setMethodChooserOpen(true)}
>
<span>
{i18n.t("receive.choose_format")}
</span>
<img class="w-4 h-4" src={side2side} />
<img class="h-4 w-4" src={side2side} />
</button>
<SimpleDialog
title={i18n.t(
@@ -451,13 +451,13 @@ export default function Receive() {
}}
>
<MegaCheck />
<h1 class="w-full mt-4 mb-2 text-2xl font-semibold text-center md:text-3xl">
<h1 class="mb-2 mt-4 w-full text-center text-2xl font-semibold md:text-3xl">
{receiveState() === "paid" &&
paidState() === "lightning_paid"
? i18n.t("receive.payment_received")
: i18n.t("receive.payment_initiated")}
</h1>
<div class="flex flex-col gap-1 items-center">
<div class="flex flex-col items-center gap-1">
<div class="text-xl">
<AmountSats
amountSats={

View File

@@ -1,3 +1,5 @@
import { MutinyChannel } from "@mutinywallet/mutiny-wasm";
import { LoadingSpinner } from "@mutinywallet/ui";
import {
createEffect,
createMemo,
@@ -11,37 +13,36 @@ import {
Suspense,
Switch
} from "solid-js";
import utxoIcon from "~/assets/icons/coin.svg";
import wave from "~/assets/wave.gif";
import {
CENTER_COLUMN,
MISSING_LABEL,
REDSHIFT_LABEL,
RIGHT_COLUMN,
THREE_COLUMNS,
AmountSats,
BackLink,
Button,
Card,
CENTER_COLUMN,
DefaultMain,
LargeHeader,
NiceP,
MISSING_LABEL,
MutinyWalletGuard,
NavBar,
NiceP,
ProgressBar,
REDSHIFT_LABEL,
RIGHT_COLUMN,
SafeArea,
SmallAmount,
SmallHeader,
VStack,
BackLink,
StyledRadioGroup,
NavBar,
Button,
ProgressBar,
AmountSats
THREE_COLUMNS,
VStack
} from "~/components";
import { LoadingSpinner } from "@mutinywallet/ui";
import { useMegaStore } from "~/state/megaStore";
import wave from "~/assets/wave.gif";
import utxoIcon from "~/assets/icons/coin.svg";
import { MutinyChannel } from "@mutinywallet/mutiny-wasm";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { Network } from "~/logic/mutinyWalletSetup";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { useMegaStore } from "~/state/megaStore";
import { getRedshifted, setRedshifted } from "~/utils/fakeLabels";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
type ShiftOption = "utxo" | "lightning";
@@ -462,7 +463,7 @@ export default function Redshift() {
{i18n.t("redshift.title")}{" "}
{i18n.t("common.coming_soon")}
</LargeHeader>
<div class="relative filter grayscale pointer-events-none opacity-75">
<div class="pointer-events-none relative opacity-75 grayscale filter">
<VStack biggap>
{/* <pre>{JSON.stringify(redshiftResource(), null, 2)}</pre> */}
<Switch>

View File

@@ -1,11 +1,12 @@
import { createEffect, createSignal } from "solid-js";
import { useNavigate } from "solid-start";
import { Button, Scanner as Reader, showToast } from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { toParsedParams } from "~/logic/waila";
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import { createEffect, createSignal } from "solid-js";
import { useNavigate } from "solid-start";
import { Button, Scanner as Reader, showToast } from "~/components";
import { useI18n } from "~/i18n/context";
import { toParsedParams } from "~/logic/waila";
import { useMegaStore } from "~/state/megaStore";
export default function Scanner() {
const i18n = useI18n();
@@ -63,10 +64,10 @@ export default function Scanner() {
});
return (
<div class="safe-top safe-left safe-right safe-bottom h-full">
<div class="h-full safe-top safe-left safe-right safe-bottom">
<Reader onResult={onResult} />
<div class="w-full flex flex-col items-center fixed bottom-[2rem] gap-8 px-8">
<div class="w-full max-w-[800px] flex flex-col gap-2">
<div class="fixed bottom-[2rem] flex w-full flex-col items-center gap-8 px-8">
<div class="flex w-full max-w-[800px] flex-col gap-2">
<Button intent="blue" onClick={handlePaste}>
{i18n.t("scanner.paste")}
</Button>

View File

@@ -1,53 +1,55 @@
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import { Contact, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import { ExternalLink } from "@mutinywallet/ui";
import {
Match,
Show,
Switch,
createEffect,
createMemo,
createSignal,
onMount
Match,
onMount,
Show,
Switch
} from "solid-js";
import { useNavigate } from "solid-start";
import { Paste } from "~/assets/svg/Paste";
import { Scan } from "~/assets/svg/Scan";
import {
NavBar,
AmountSats,
AmountCard,
AmountFiat,
AmountSats,
BackButton,
BackLink,
Button,
ButtonLink,
Card,
DefaultMain,
Fee,
HStack,
InfoBox,
LargeHeader,
MutinyWalletGuard,
SafeArea,
SmallHeader,
VStack,
StyledRadioGroup,
showToast,
MegaCheck,
MegaEx,
BackLink,
TagEditor,
MutinyWalletGuard,
NavBar,
SafeArea,
showToast,
SmallHeader,
StringShower,
AmountCard,
BackButton,
StyledRadioGroup,
SuccessModal,
InfoBox,
Fee
TagEditor,
VStack
} from "~/components";
import { ExternalLink } from "@mutinywallet/ui";
import { Paste } from "~/assets/svg/Paste";
import { Scan } from "~/assets/svg/Scan";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { ParsedParams, toParsedParams } from "~/logic/waila";
import { useMegaStore } from "~/state/megaStore";
import { Contact, MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import eify from "~/utils/eify";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { useNavigate } from "solid-start";
import { MutinyTagItem } from "~/utils/tags";
import { Network } from "~/logic/mutinyWalletSetup";
import { useI18n } from "~/i18n/context";
import { ParsedParams, toParsedParams } from "~/logic/waila";
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import { FeedbackLink } from "./Feedback";
export type SendSource = "lightning" | "onchain";
@@ -144,7 +146,7 @@ function DestinationInput(props: {
props.setFieldDestination(trim);
}}
placeholder="bitcoin:..."
class="p-2 rounded-lg bg-white/10 placeholder-neutral-400"
class="rounded-lg bg-white/10 p-2 placeholder-neutral-400"
/>
<Button
disabled={!props.fieldDestination}
@@ -155,13 +157,13 @@ function DestinationInput(props: {
</Button>
<HStack>
<Button onClick={props.handlePaste}>
<div class="flex flex-col gap-2 items-center">
<div class="flex flex-col items-center gap-2">
<Paste />
<span>{i18n.t("send.paste")}</span>
</div>
</Button>
<ButtonLink href="/scanner">
<div class="flex flex-col gap-2 items-center">
<div class="flex flex-col items-center gap-2">
<Scan />
<span>{i18n.t("send.scan_qr")}</span>
</div>
@@ -604,7 +606,7 @@ export default function Send() {
<Switch>
<Match when={sentDetails()?.failure_reason}>
<MegaEx />
<h1 class="w-full mt-4 mb-2 text-2xl font-semibold text-center md:text-3xl">
<h1 class="mb-2 mt-4 w-full text-center text-2xl font-semibold md:text-3xl">
{sentDetails()?.amount
? source() === "onchain"
? i18n.t("send.payment_initiated")
@@ -615,14 +617,14 @@ export default function Send() {
</Match>
<Match when={true}>
<MegaCheck />
<h1 class="w-full mt-4 mb-2 text-2xl font-semibold text-center md:text-3xl">
<h1 class="mb-2 mt-4 w-full text-center text-2xl font-semibold md:text-3xl">
{sentDetails()?.amount
? source() === "onchain"
? i18n.t("send.payment_initiated")
: i18n.t("send.payment_sent")
: sentDetails()?.failure_reason}
</h1>
<div class="flex flex-col gap-1 items-center">
<div class="flex flex-col items-center gap-1">
<div class="text-xl">
<AmountSats
amountSats={sentDetails()?.amount}

View File

@@ -1,13 +1,13 @@
import {
AmountCard,
Fee,
NavBar,
OnboardWarning,
Button,
DefaultMain,
ShareCard,
Fee,
LargeHeader,
NavBar,
OnboardWarning,
SafeArea,
ShareCard,
VStack
} from "~/components";

View File

@@ -1,41 +1,42 @@
import { createForm, required } from "@modular-forms/solid";
import { MutinyChannel, MutinyPeer } from "@mutinywallet/mutiny-wasm";
import { ExternalLink } from "@mutinywallet/ui";
import {
createMemo,
createResource,
createSignal,
For,
Match,
Show,
Switch,
createMemo,
createResource,
createSignal
Switch
} from "solid-js";
import { useNavigate } from "solid-start";
import {
AmountCard,
NavBar,
showToast,
AmountFiat,
BackLink,
Button,
Card,
DefaultMain,
InfoBox,
LargeHeader,
MutinyWalletGuard,
SafeArea,
BackLink,
TextField,
VStack,
MegaCheck,
MegaEx,
InfoBox,
MutinyWalletGuard,
NavBar,
SafeArea,
showToast,
SuccessModal,
AmountFiat
TextField,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { Network } from "~/logic/mutinyWalletSetup";
import { MethodChooser, SendSource } from "~/routes/Send";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import { useNavigate } from "solid-start";
import mempoolTxUrl from "~/utils/mempoolTxUrl";
import { ExternalLink } from "@mutinywallet/ui";
import { Network } from "~/logic/mutinyWalletSetup";
import { useI18n } from "~/i18n/context";
const CHANNEL_FEE_ESTIMATE_ADDRESS =
"bc1qf7546vg73ddsjznzq57z3e8jdn6gtw6au576j07kt6d9j7nz8mzsyn6lgf";
@@ -282,7 +283,7 @@ export default function Swap() {
<Switch>
<Match when={channelOpenResult()?.failure_reason}>
<MegaEx />
<h1 class="w-full mt-4 mb-2 text-2xl font-semibold text-center md:text-3xl">
<h1 class="mb-2 mt-4 w-full text-center text-2xl font-semibold md:text-3xl">
{channelOpenResult()?.failure_reason
? channelOpenResult()?.failure_reason
?.message
@@ -293,10 +294,10 @@ export default function Swap() {
<Match when={channelOpenResult()?.channel}>
<MegaCheck />
<div class="flex flex-col justify-center">
<h1 class="w-full mt-4 mb-2 justify-center text-2xl font-semibold text-center md:text-3xl">
<h1 class="mb-2 mt-4 w-full justify-center text-center text-2xl font-semibold md:text-3xl">
{i18n.t("swap.initiated")}
</h1>
<p class="text-xl text-center">
<p class="text-center text-xl">
{i18n.t("swap.sats_added", {
amount: (
Number(
@@ -310,7 +311,7 @@ export default function Swap() {
).toLocaleString()
})}
</p>
<div class="text-sm text-center text-white/70">
<div class="text-center text-sm text-white/70">
<AmountFiat
amountSats={
Number(
@@ -356,16 +357,16 @@ export default function Swap() {
<Show when={!hasLsp()}>
<Card>
<VStack>
<div class="w-full flex flex-col gap-2">
<div class="flex w-full flex-col gap-2">
<label
for="peerselect"
class="uppercase font-semibold text-sm"
class="text-sm font-semibold uppercase"
>
{i18n.t("swap.use_existing")}
</label>
<select
name="peerselect"
class="bg-black px-4 py-2 rounded truncate w-full"
class="w-full truncate rounded bg-black px-4 py-2"
onChange={handlePeerSelect}
value={selectedPeer()}
>

View File

@@ -1,5 +1,6 @@
import { Title } from "solid-start";
import { HttpStatusCode } from "solid-start/server";
import { ButtonLink, DefaultMain, LargeHeader, SafeArea } from "~/components";
import { useI18n } from "~/i18n/context";

View File

@@ -1,6 +1,7 @@
import { Switch, Match } from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { Match, Switch } from "solid-js";
import { App, FullscreenLoader, SetupErrorDisplay } from "~/components";
import { useMegaStore } from "~/state/megaStore";
export default function Home() {
const [state, _] = useMegaStore();

View File

@@ -1,15 +1,15 @@
import {
BackLink,
DefaultMain,
DeleteEverything,
KitchenSink,
NavBar,
DefaultMain,
LargeHeader,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
SmallHeader,
VStack,
BackLink
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
@@ -28,7 +28,7 @@ export default function Admin() {
<NiceP>{i18n.t("settings.admin.warning_one")}</NiceP>
<NiceP>{i18n.t("settings.admin.warning_two")}</NiceP>
<KitchenSink />
<div class="rounded-xl p-4 flex flex-col gap-2 bg-m-red overflow-x-hidden">
<div class="flex flex-col gap-2 overflow-x-hidden rounded-xl bg-m-red p-4">
<SmallHeader>
{i18n.t("settings.danger_zone")}
</SmallHeader>

View File

@@ -1,20 +1,21 @@
import { createEffect, createSignal, Show } from "solid-js";
import { useNavigate } from "solid-start";
import {
BackLink,
Button,
Checkbox,
DefaultMain,
LargeHeader,
NiceP,
MutinyWalletGuard,
SafeArea,
VStack,
Checkbox,
NavBar,
NiceP,
SafeArea,
SeedWords,
BackLink
VStack
} from "~/components";
import { useNavigate } from "solid-start";
import { useMegaStore } from "~/state/megaStore";
import { Show, createEffect, createSignal } from "solid-js";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
function Quiz(props: { setHasCheckedAll: (hasChecked: boolean) => void }) {
const i18n = useI18n();

View File

@@ -1,20 +1,21 @@
import { Match, Switch, createResource } from "solid-js";
import { useMegaStore } from "~/state/megaStore";
import { createResource, Match, Switch } from "solid-js";
import {
AmountSmall,
BackLink,
Card,
DefaultMain,
LargeHeader,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
SmallHeader,
TinyText,
VStack,
AmountSmall,
BackLink,
NavBar
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
function BalanceBar(props: { inbound: number; outbound: number }) {
const i18n = useI18n();
@@ -26,9 +27,9 @@ function BalanceBar(props: { inbound: number; outbound: number }) {
</SmallHeader>
<SmallHeader>{i18n.t("settings.channels.inbound")}</SmallHeader>
</div>
<div class="flex gap-1 w-full">
<div class="flex w-full gap-1">
<div
class="bg-m-green p-2 rounded-l-xl min-w-fit"
class="min-w-fit rounded-l-xl bg-m-green p-2"
style={{
"flex-grow": props.outbound || 1
}}
@@ -36,7 +37,7 @@ function BalanceBar(props: { inbound: number; outbound: number }) {
<AmountSmall amountSats={props.outbound} />
</div>
<div
class="bg-m-blue p-2 rounded-r-xl min-w-fit"
class="min-w-fit rounded-r-xl bg-m-blue p-2"
style={{
"flex-grow": props.inbound || 1
}}

View File

@@ -1,28 +1,29 @@
import { NwcProfile } from "@mutinywallet/mutiny-wasm";
import { For, Show, createResource, createSignal } from "solid-js";
import { createResource, createSignal, For, Show } from "solid-js";
import { QRCodeSVG } from "solid-qr-code";
import {
KeyValue,
MiniStringShower,
InfoBox,
NavBar,
ShareCard,
BackLink,
Button,
Collapser,
DefaultMain,
InfoBox,
KeyValue,
LargeHeader,
MiniStringShower,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
SettingsCard,
ShareCard,
SimpleDialog,
VStack,
BackLink,
TextField
TextField,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import { useI18n } from "~/i18n/context";
function Nwc() {
const i18n = useI18n();
@@ -118,10 +119,10 @@ function Nwc() {
/>
</KeyValue>
<div class="w-full bg-white rounded-xl">
<div class="w-full rounded-xl bg-white">
<QRCodeSVG
value={profile.nwc_uri}
class="w-full h-full p-8 max-h-[320px]"
class="h-full max-h-[320px] w-full p-8"
/>
</div>
<ShareCard text={profile.nwc_uri || ""} />

View File

@@ -1,18 +1,19 @@
import { ExternalLink } from "@mutinywallet/ui";
import {
BackLink,
DefaultMain,
DeleteEverything,
ImportExport,
LargeHeader,
LoadingIndicator,
Logs,
NavBar,
DefaultMain,
LargeHeader,
NiceP,
SafeArea,
SmallHeader,
VStack,
BackLink
VStack
} from "~/components";
import { ExternalLink } from "@mutinywallet/ui";
import { useI18n } from "~/i18n/context";
function EmergencyStack() {
@@ -21,7 +22,7 @@ function EmergencyStack() {
<VStack>
<ImportExport emergency />
<Logs />
<div class="rounded-xl p-4 flex flex-col gap-2 bg-m-red overflow-x-hidden">
<div class="flex flex-col gap-2 overflow-x-hidden rounded-xl bg-m-red p-4">
<SmallHeader>{i18n.t("settings.danger_zone")}</SmallHeader>
<DeleteEverything emergency />
</div>

View File

@@ -1,23 +1,24 @@
import { createForm } from "@modular-forms/solid";
import { createSignal, Show } from "solid-js";
import {
BackLink,
Button,
ButtonLink,
DefaultMain,
InfoBox,
LargeHeader,
NiceP,
MutinyWalletGuard,
SafeArea,
VStack,
NavBar,
BackLink,
NiceP,
SafeArea,
TextField,
InfoBox
VStack
} from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { Show, createSignal } from "solid-js";
import { createForm } from "@modular-forms/solid";
import { timeout } from "~/utils/timeout";
import eify from "~/utils/eify";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import { timeout } from "~/utils/timeout";
type EncryptPasswordForm = {
existingPassword: string;

View File

@@ -1,17 +1,18 @@
import { TextField } from "@kobalte/core";
import { createSignal } from "solid-js";
import {
BackLink,
Button,
NavBar,
DefaultMain,
InnerCard,
LargeHeader,
MutinyWalletGuard,
SafeArea,
BackLink
NavBar,
SafeArea
} from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
export default function LnUrlAuth() {
const i18n = useI18n();
@@ -56,7 +57,7 @@ export default function LnUrlAuth() {
{i18n.t("settings.lnurl_auth.title")}
</TextField.Label>
<TextField.Input
class="w-full p-2 rounded-lg text-black"
class="w-full rounded-lg p-2 text-black"
placeholder="LNURL..."
/>
<TextField.ErrorMessage class="text-red-500">

View File

@@ -1,38 +1,39 @@
import {
createResource,
createSignal,
Match,
Show,
Suspense,
Switch,
createResource,
createSignal
Switch
} from "solid-js";
import { A } from "solid-start";
import party from "~/assets/party.gif";
import {
ConfirmDialog,
InfoBox,
NavBar,
BackLink,
Button,
ConfirmDialog,
DefaultMain,
FancyCard,
InfoBox,
LargeHeader,
LoadingShimmer,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
TinyText,
VStack,
BackLink,
LoadingShimmer
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import party from "~/assets/party.gif";
import { useI18n } from "~/i18n/context";
import { subscriptionValid } from "~/utils/subscriptions";
function Perks(props: { alreadySubbed?: boolean }) {
const i18n = useI18n();
return (
<ul class="list-disc ml-8 font-light text-lg">
<ul class="ml-8 list-disc text-lg font-light">
<Show when={props.alreadySubbed}>
<li>{i18n.t("settings.plus.satisfaction")}</li>
</Show>
@@ -214,7 +215,7 @@ export default function Plus() {
<VStack>
<Switch>
<Match when={state.mutiny_plus}>
<img src={party} class="w-1/2 mx-auto" />
<img src={party} class="mx-auto w-1/2" />
<NiceP>{i18n.t("settings.plus.thanks")}</NiceP>
<Perks alreadySubbed />
<NiceP>

View File

@@ -1,35 +1,36 @@
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import { TextField as KTextField } from "@kobalte/core";
import {
Button,
DefaultMain,
LargeHeader,
NiceP,
SafeArea,
VStack,
BackLink,
NavBar,
TextFieldProps,
showToast,
ConfirmDialog,
InfoBox
} from "~/components";
import { useMegaStore } from "~/state/megaStore";
import { For, Show, createSignal, splitProps } from "solid-js";
import pasteIcon from "~/assets/icons/paste.svg";
import {
SubmitHandler,
createForm,
custom,
required,
setValues,
SubmitHandler,
validate
} from "@modular-forms/solid";
import { TextField as KTextField } from "@kobalte/core";
import eify from "~/utils/eify";
import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { WORDS_EN } from "~/utils/words";
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import { createSignal, For, Show, splitProps } from "solid-js";
import pasteIcon from "~/assets/icons/paste.svg";
import {
BackLink,
Button,
ConfirmDialog,
DefaultMain,
InfoBox,
LargeHeader,
NavBar,
NiceP,
SafeArea,
showToast,
TextFieldProps,
VStack
} from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
import { WORDS_EN } from "~/utils/words";
type SeedWordsForm = {
words: string[];
@@ -67,7 +68,7 @@ export function SeedTextField(props: TextFieldProps) {
autocorrect="off"
autocomplete="off"
type={props.type}
class="w-full p-2 rounded-lg border bg-m-grey-750 placeholder-neutral-400"
class="w-full rounded-lg border bg-m-grey-750 p-2 placeholder-neutral-400"
classList={{
"border-m-grey-750": !props.error && !props.value,
"border-m-red": !!props.error,
@@ -170,16 +171,16 @@ function TwelveWordsEntry() {
return (
<>
<Form onSubmit={onSubmit} class="flex flex-col gap-4">
<div class="flex flex-col gap-4 bg-m-grey-800 p-4 rounded-xl overflow-hidden">
<div class="flex flex-col gap-4 overflow-hidden rounded-xl bg-m-grey-800 p-4">
<Show when={error()}>
<InfoBox accent="red">{error()?.message}</InfoBox>
</Show>
<ul class="overflow-hidden columns-2 w-full list-none pt-2 pr-2">
<ul class="w-full list-none columns-2 overflow-hidden pr-2 pt-2">
<FieldArray name="words">
{(fieldArray) => (
<For each={fieldArray.items}>
{(_, index) => (
<div class="flex items-center gap-1 mb-2">
<div class="mb-2 flex items-center gap-1">
<pre class="w-[2rem] text-right">
{index() + 1}
{"."}
@@ -217,7 +218,7 @@ function TwelveWordsEntry() {
<div class="flex w-full justify-center">
<button
onClick={handlePaste}
class="bg-white/10 hover:bg-white/20 py-2 px-4 rounded-lg"
class="rounded-lg bg-white/10 px-4 py-2 hover:bg-white/20"
type="button"
>
<div class="flex items-center gap-2">
@@ -225,7 +226,7 @@ function TwelveWordsEntry() {
<img
src={pasteIcon}
alt="paste"
class="w-4 h-4"
class="h-4 w-4"
/>
</div>
</button>

View File

@@ -1,25 +1,26 @@
import { createForm, url } from "@modular-forms/solid";
import { ExternalLink } from "@mutinywallet/ui";
import {
BackLink,
Button,
Card,
DefaultMain,
LargeHeader,
MutinyWalletGuard,
NavBar,
NiceP,
SafeArea,
showToast,
TextField
} from "~/components";
import { useI18n } from "~/i18n/context";
import {
MutinyWalletSettingStrings,
setSettings
} from "~/logic/mutinyWalletSetup";
import {
Button,
Card,
DefaultMain,
TextField,
LargeHeader,
MutinyWalletGuard,
NiceP,
SafeArea,
showToast,
BackLink,
NavBar
} from "~/components";
import eify from "~/utils/eify";
import { ExternalLink } from "@mutinywallet/ui";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
export function SettingsStringsEditor() {
const i18n = useI18n();

View File

@@ -1,15 +1,16 @@
import { For, Show } from "solid-js";
import { A } from "solid-start";
import forward from "~/assets/icons/forward.svg";
import {
BackLink,
DefaultMain,
LargeHeader,
NavBar,
SafeArea,
SettingsCard,
VStack,
BackLink,
NavBar
VStack
} from "~/components";
import { A } from "solid-start";
import { For, Show } from "solid-js";
import forward from "~/assets/icons/forward.svg";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
@@ -29,7 +30,7 @@ function SettingsLinkList(props: {
{(link) => (
<A
href={link.href}
class="no-underline flex w-full flex-col gap-1 py-2 hover:bg-m-grey-750 active:bg-m-grey-900 px-4"
class="flex w-full flex-col gap-1 px-4 py-2 no-underline hover:bg-m-grey-750 active:bg-m-grey-900"
classList={{
"opacity-50 cursor pointer-events-none grayscale":
link.disabled

View File

@@ -1,28 +1,29 @@
/* @refresh reload */
// Inspired by https://github.com/solidjs/solid-realworld/blob/main/src/store/index.js
import { MutinyBalance, MutinyWallet } from "@mutinywallet/mutiny-wasm";
import {
ParentComponent,
createContext,
onCleanup,
onMount,
ParentComponent,
useContext
} from "solid-js";
import { createStore } from "solid-js/store";
import { useSearchParams } from "solid-start";
import { checkBrowserCompatibility } from "~/logic/browserCompatibility";
import {
MutinyWalletSettingStrings,
doubleInitDefense,
getSettings,
initializeWasm,
MutinyWalletSettingStrings,
setupMutinyWallet
} from "~/logic/mutinyWalletSetup";
import { MutinyBalance, MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { MutinyTagItem } from "~/utils/tags";
import { checkBrowserCompatibility } from "~/logic/browserCompatibility";
import eify from "~/utils/eify";
import { ParsedParams } from "~/logic/waila";
import eify from "~/utils/eify";
import { subscriptionValid } from "~/utils/subscriptions";
import { useSearchParams } from "solid-start";
import { MutinyTagItem } from "~/utils/tags";
const MegaStoreContext = createContext<MegaStore>();

View File

@@ -7,12 +7,12 @@
.solid-select-control[data-disabled="true"] {
}
.solid-select-control {
@apply w-full p-2 rounded-lg bg-white/10 placeholder-neutral-400;
@apply w-full rounded-lg bg-white/10 p-2 placeholder-neutral-400;
@apply grid leading-6;
grid-template-columns: repeat(1, minmax(0, 1fr));
}
.solid-select-control[data-multiple="true"][data-has-value="true"] {
@apply flex items-stretch gap-1 flex-wrap;
@apply flex flex-wrap items-stretch gap-1;
}
.solid-select-placeholder {
@@ -23,16 +23,16 @@
@apply col-start-1 row-start-1;
}
.solid-select-multi-value {
@apply flex bg-white/20 rounded items-center px-1;
@apply flex items-center rounded bg-white/20 px-1;
}
.solid-select-multi-value-remove {
/* TODO: there's gotta be a better way to vertically center this */
@apply pl-2 pr-1 leading-3 -mt-2 text-2xl;
@apply -mt-2 pl-2 pr-1 text-2xl leading-3;
}
.solid-select-input {
@apply bg-transparent caret-transparent flex-grow flex-shrink;
@apply flex-shrink flex-grow bg-transparent caret-transparent;
outline: 2px solid transparent;
@apply col-start-1 row-start-1;
}
@@ -47,17 +47,17 @@
}
.solid-select-list {
@apply max-h-[50vh] min-w-full overflow-y-auto absolute whitespace-nowrap z-10 bg-neutral-950 p-2 rounded-lg;
@apply absolute z-10 max-h-[50vh] min-w-full overflow-y-auto whitespace-nowrap rounded-lg bg-neutral-950 p-2;
}
.solid-select-option[data-focused="true"] {
}
.solid-select-option > mark {
@apply underline bg-white/10 text-white;
@apply bg-white/10 text-white underline;
}
.solid-select-option {
@apply cursor-default select-none p-1 hover:bg-neutral-800 rounded;
@apply cursor-default select-none rounded p-1 hover:bg-neutral-800;
}
.solid-select-option[data-disabled="true"] {
@apply pointer-events-none opacity-50;

View File

@@ -1,8 +1,9 @@
// Thanks you https://soorria.com/snippets/use-copy-solidjs
import type { Accessor } from "solid-js";
import { createSignal } from "solid-js";
import { Clipboard } from "@capacitor/clipboard";
import { Capacitor } from "@capacitor/core";
import type { Accessor } from "solid-js";
import { createSignal } from "solid-js";
export type UseCopyProps = {
copiedTimeout?: number;
};