diff --git a/package.json b/package.json index b4e6e41..bc5c4bb 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "class-variance-authority": "^0.4.0", "i18next": "^22.5.1", "i18next-browser-languagedetector": "^7.1.0", - "nostr-tools": "^1.11.1", "qr-scanner": "^1.4.2", "solid-js": "^1.7.7", "solid-qr-code": "^0.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e555485..af8523c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,9 +37,6 @@ dependencies: i18next-browser-languagedetector: specifier: ^7.1.0 version: 7.1.0 - nostr-tools: - specifier: ^1.11.1 - version: 1.12.1 qr-scanner: specifier: ^1.4.2 version: 1.4.2 @@ -1880,16 +1877,6 @@ packages: resolution: {integrity: sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==} hasBin: true - /@noble/curves@1.0.0: - resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} - dependencies: - '@noble/hashes': 1.3.0 - dev: false - - /@noble/hashes@1.3.0: - resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} - dev: false - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2050,25 +2037,6 @@ packages: picomatch: 2.3.1 rollup: 3.26.2 - /@scure/base@1.1.1: - resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} - dev: false - - /@scure/bip32@1.3.0: - resolution: {integrity: sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==} - dependencies: - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 - '@scure/base': 1.1.1 - dev: false - - /@scure/bip39@1.2.0: - resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} - dependencies: - '@noble/hashes': 1.3.0 - '@scure/base': 1.1.1 - dev: false - /@sideway/address@4.1.4: resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} dependencies: @@ -4459,16 +4427,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /nostr-tools@1.12.1: - resolution: {integrity: sha512-ZeoV7g3jBUAlb4mKa3C+6hrc84htPkbebMShfGNgV4vAiz18e/sQukUBFL6vb/+sxZy+dBQFkRwsJIaVFs8Gfw==} - dependencies: - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 - '@scure/base': 1.1.1 - '@scure/bip32': 1.3.0 - '@scure/bip39': 1.2.0 - dev: false - /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} diff --git a/src/components/LoadingIndicator.tsx b/src/components/LoadingIndicator.tsx index 90c5722..5dbf1f5 100644 --- a/src/components/LoadingIndicator.tsx +++ b/src/components/LoadingIndicator.tsx @@ -8,14 +8,12 @@ export function LoadingBar(props: { value: number; max: number }) { case 0: return "Just getting started"; case 1: - return "Checking user status"; - case 2: return "Double checking something"; - case 3: + case 2: return "Downloading"; - case 4: + case 3: return "Setup"; - case 5: + case 4: return "Done"; default: return "Just getting started"; @@ -44,16 +42,14 @@ export function LoadingIndicator() { switch (state.load_stage) { case "fresh": return 0; - case "checking_user": - return 1; case "checking_double_init": - return 2; + return 1; case "downloading": - return 3; + return 2; case "setup": - return 4; + return 3; case "done": - return 5; + return 4; default: return 0; } @@ -61,7 +57,7 @@ export function LoadingIndicator() { return ( - + ); } diff --git a/src/components/waitlist/Notes.tsx b/src/components/waitlist/Notes.tsx deleted file mode 100644 index f28cb73..0000000 --- a/src/components/waitlist/Notes.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Component, For, createEffect, createSignal } from "solid-js"; - -import { nip19 } from "nostr-tools"; -import { Linkify } from "~/components/layout"; - -type NostrEvent = { - content: string; - created_at: number; - id?: string; - tags: string; -}; - -const Note: Component<{ e: NostrEvent }> = (props) => { - const linkRoot = "https://snort.social/e/"; - - const [noteId, setNoteId] = createSignal(""); - - createEffect(() => { - if (props.e.id) { - setNoteId(nip19.noteEncode(props.e.id)); - } - }); - - return ( -
- -
-

- {/* {props.e.content} */} - -

- - - {new Date(props.e.created_at * 1000).toLocaleString()} - - -
-
- ); -}; - -function filterReplies(event: NostrEvent) { - // If there's a "p" tag or an "e" tag we want to return false, otherwise true - for (const tag of event.tags) { - if (tag[0] === "p" || tag[0] === "e") { - return false; - } - } - return true; -} - -const Notes: Component<{ notes: NostrEvent[] }> = (props) => { - return ( - - ); -}; - -export default Notes; diff --git a/src/components/waitlist/WaitlistAlreadyIn.tsx b/src/components/waitlist/WaitlistAlreadyIn.tsx deleted file mode 100644 index cfed4a6..0000000 --- a/src/components/waitlist/WaitlistAlreadyIn.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { createResource, Show } from "solid-js"; - -const relayUrls = [ - "wss://nostr.zebedee.cloud", - "wss://relay.snort.social", - "wss://nos.lol", - "wss://nostr.fmt.wiz.biz", - "wss://relay.damus.io", - "wss://eden.nostr.land" -]; - -import { SimplePool } from "nostr-tools"; -import { LoadingSpinner } from "~/components/layout"; -import Notes from "~/components/waitlist/Notes"; -import logo from "~/assets/icons/mutiny-logo.svg"; - -const pool = new SimplePool(); - -const postsFetcher = async () => { - const filter = { - authors: [ - "df173277182f3155d37b330211ba1de4a81500c02d195e964f91be774ec96708" - ], - since: 0, - kinds: [1] - }; - - const events = await pool.list(relayUrls, [filter]); - - return events; -}; - -export function WaitlistAlreadyIn() { - const [posts] = createResource("", postsFetcher); - - return ( -
- - logo - -

You're on a list!

-

- We'll message you when Mutiny Wallet is ready. -

-
-

Recent Updates

- - -
- } - > - - - -
- ); -} diff --git a/src/components/waitlist/WaitlistForm.tsx b/src/components/waitlist/WaitlistForm.tsx deleted file mode 100644 index 8309b49..0000000 --- a/src/components/waitlist/WaitlistForm.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { Match, Switch, createSignal } from "solid-js"; -import { Button } from "~/components/layout"; -import { StyledRadioGroup } from "../layout/Radio"; -import { TextField } from "../layout/TextField"; -import { - SubmitHandler, - createForm, - email, - getValue, - required, - setValue -} from "@modular-forms/solid"; -import { showToast } from "../Toaster"; -import eify from "~/utils/eify"; -import logo from "~/assets/icons/mutiny-logo.svg"; - -const WAITLIST_ENDPOINT = - "https://waitlist.mutiny-waitlist.workers.dev/waitlist"; - -const COMMUNICATION_METHODS = [ - { value: "nostr", label: "Nostr", caption: "Your freshest npub" }, - { value: "email", label: "Email", caption: "Burners welcome" } -]; - -type WaitlistForm = { - user_type: "nostr" | "email"; - id: string; - comment?: string; -}; - -const initialValues: WaitlistForm = { user_type: "nostr", id: "", comment: "" }; - -export default function WaitlistForm() { - const [waitlistForm, { Form, Field }] = createForm({ - initialValues - }); - - const [loading, setLoading] = createSignal(false); - - const newHandleSubmit: SubmitHandler = async ( - f: WaitlistForm - ) => { - console.log(f); - - // TODO: not sure why waitlistForm.submitting doesn't work for me - // https://modularforms.dev/solid/guides/handle-submission - setLoading(true); - try { - const res = await fetch(WAITLIST_ENDPOINT, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(f) - }); - - if (res.status !== 200) { - throw new Error("nope"); - } else { - // On success set the id in local storage and reload the page - localStorage.setItem("waitlist_id", f.id); - window.location.reload(); - } - } catch (e) { - if (f.user_type === "nostr") { - const error = new Error( - "Something went wrong. Are you sure that's a valid npub?" - ); - showToast(eify(error)); - } else { - const error = new Error("Something went wrong. Not sure what."); - showToast(eify(error)); - } - return; - } finally { - setLoading(false); - } - }; - - return ( -
- - logo - -

Join Waitlist

-

- Sign up for our waitlist and we'll send a message when Mutiny - Wallet is ready for you. -

-
- - {(field, _props) => ( - // TODO: there's probably a "real" way to do this with modular-forms - - setValue( - waitlistForm, - "user_type", - newValue as "nostr" | "email" - ) - } - choices={COMMUNICATION_METHODS} - /> - )} - - - - - {(field, props) => ( - - )} - - - - - {(field, props) => ( - - )} - - - - - {(field, props) => ( - - )} - - -
-
- ); -} diff --git a/src/root.tsx b/src/root.tsx index 568abf3..6ad4d63 100644 --- a/src/root.tsx +++ b/src/root.tsx @@ -32,14 +32,14 @@ export default function Root() { - + - - - - - - ); } diff --git a/src/state/megaStore.tsx b/src/state/megaStore.tsx index 63c4d6e..69dda81 100644 --- a/src/state/megaStore.tsx +++ b/src/state/megaStore.tsx @@ -25,11 +25,8 @@ import { ParsedParams } from "~/logic/waila"; const MegaStoreContext = createContext(); -type UserStatus = undefined | "new_here" | "waitlisted" | "approved"; - export type LoadStage = | "fresh" - | "checking_user" | "checking_double_init" | "downloading" | "setup" @@ -37,11 +34,8 @@ export type LoadStage = export type MegaStore = [ { - already_approved?: boolean; - waitlist_id?: string; mutiny_wallet?: MutinyWallet; deleting: boolean; - user_status: UserStatus; scan_result?: ParsedParams; balance?: MutinyBalance; is_syncing?: boolean; @@ -59,13 +53,11 @@ export type MegaStore = [ load_stage: LoadStage; }, { - fetchUserStatus(): Promise; setupMutinyWallet( settings?: MutinyWalletSettingStrings, password?: string ): Promise; deleteMutinyWallet(): Promise; - setWaitlistId(waitlist_id: string): void; setScanResult(scan_result: ParsedParams | undefined): void; sync(): Promise; dismissRestorePrompt(): void; @@ -78,13 +70,8 @@ export type MegaStore = [ export const Provider: ParentComponent = (props) => { const [state, setState] = createStore({ - already_approved: - import.meta.env.VITE_SELFHOSTED === "true" || - localStorage.getItem("already_approved") === "true", - waitlist_id: localStorage.getItem("waitlist_id"), mutiny_wallet: undefined as MutinyWallet | undefined, deleting: false, - user_status: undefined as UserStatus, scan_result: undefined as ParsedParams | undefined, price: 0, has_backed_up: localStorage.getItem("has_backed_up") === "true", @@ -112,47 +99,6 @@ export const Provider: ParentComponent = (props) => { }); const actions = { - async fetchUserStatus(): Promise { - if (state.already_approved) { - console.log("welcome back!"); - return "approved"; - } - - // Using a PWA - if (state.is_pwa) { - localStorage.setItem("already_approved", "true"); - return "approved"; - } - - // Got an invite link - const urlParams = new URLSearchParams(window.location.search); - const invite = urlParams.get("invite"); - if (invite === "true") { - localStorage.setItem("already_approved", "true"); - return "approved"; - } - - if (!state.waitlist_id) { - return "new_here"; - } - - try { - const res = await fetch( - `https://waitlist.mutiny-waitlist.workers.dev/waitlist/${state.waitlist_id}` - ); - const data = await res.json(); - - if (data.approval_date) { - // Remember them so we don't have to check every time - localStorage.setItem("already_approved", "true"); - return "approved"; - } else { - return "waitlisted"; - } - } catch (e) { - return "new_here"; - } - }, async checkForSubscription(justPaid?: boolean): Promise { try { const timestamp = await state.mutiny_wallet?.check_subscribed(); @@ -261,9 +207,6 @@ export const Provider: ParentComponent = (props) => { console.error(e); } }, - setWaitlistId(waitlist_id: string) { - setState({ waitlist_id }); - }, async sync(): Promise { try { if (state.mutiny_wallet && !state.is_syncing) { @@ -327,58 +270,40 @@ export const Provider: ParentComponent = (props) => { // Fetch status from remote on load onMount(() => { - setState({ load_stage: "checking_user" }); - // eslint-disable-next-line - actions.fetchUserStatus().then((status) => { - setState({ user_status: status }); + function handleExisting() { + if (state.existing_tab_detected) { + setState({ + setup_error: new Error( + "Existing tab detected, aborting setup" + ) + }); + } else { + console.log("running setup node manager..."); - function handleExisting() { - if (state.existing_tab_detected) { - setState({ - setup_error: new Error( - "Existing tab detected, aborting setup" - ) - }); - } else { - console.log("running setup node manager..."); + actions + .setupMutinyWallet() + .then(() => console.log("node manager setup done")); - actions - .setupMutinyWallet() - .then(() => console.log("node manager setup done")); - - // Setup an event listener to stop the mutiny wallet when the page unloads - window.onunload = async (_e) => { - console.log("stopping mutiny_wallet"); - await state.mutiny_wallet?.stop(); - console.log("mutiny_wallet stopped"); - sessionStorage.removeItem("MUTINY_WALLET_INITIALIZED"); - }; - } + // Setup an event listener to stop the mutiny wallet when the page unloads + window.onunload = async (_e) => { + console.log("stopping mutiny_wallet"); + await state.mutiny_wallet?.stop(); + console.log("mutiny_wallet stopped"); + sessionStorage.removeItem("MUTINY_WALLET_INITIALIZED"); + }; } + } - function handleGoodBrowser() { - console.log("checking if any other tabs are open"); - // 500ms should hopefully be enough time for any tabs to reply - timeout(500).then(handleExisting); - } + function handleGoodBrowser() { + console.log("checking if any other tabs are open"); + // 500ms should hopefully be enough time for any tabs to reply + timeout(500).then(handleExisting); + } - // Only load node manager when status is approved - if ( - state.user_status === "approved" && - !state.mutiny_wallet && - !state.deleting - ) { - console.log("checking for browser compatibility..."); - actions.checkBrowserCompat().then(handleGoodBrowser); - } - }); - }); - - // Be reactive to changes in waitlist_id - createEffect(() => { - state.waitlist_id - ? localStorage.setItem("waitlist_id", state.waitlist_id) - : localStorage.removeItem("waitlist_id"); + if (!state.mutiny_wallet && !state.deleting) { + console.log("checking for browser compatibility..."); + actions.checkBrowserCompat().then(handleGoodBrowser); + } }); createEffect(() => {