diff --git a/src/app.tsx b/src/app.tsx index 320f1250..9c09fa2f 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -80,6 +80,13 @@ const router = createBrowserRouter([ return { Component: NotificationScreen }; }, }, + { + path: 'nwc', + async lazy() { + const { NWCScreen } = await import('@app/nwc'); + return { Component: NWCScreen }; + }, + }, ], }, { diff --git a/src/shared/alby.tsx b/src/app/nwc/components/alby.tsx similarity index 80% rename from src/shared/alby.tsx rename to src/app/nwc/components/alby.tsx index 94c365ef..5dc9299b 100644 --- a/src/shared/alby.tsx +++ b/src/app/nwc/components/alby.tsx @@ -12,19 +12,19 @@ import { CancelIcon, CheckCircleIcon, LoaderIcon, - StarsIcon, } from '@shared/icons'; import { useStronghold } from '@stores/stronghold'; -export function AlbyConnectButton() { +export function NWCAlby() { const { db } = useStorage(); - const setWalletConnectURL = useStronghold((state) => state.setWalletConnectURL); const [isOpen, setIsOpen] = useState(false); const [isLoading, setIsloading] = useState(false); const [isConnected, setIsConnected] = useState(false); + const setWalletConnectURL = useStronghold((state) => state.setWalletConnectURL); + const initAlby = async () => { try { setIsloading(true); @@ -58,31 +58,24 @@ export function AlbyConnectButton() { return ( -
- -
-
- +
+
+
+
-
-
- New feature -
-

- Send bitcoin tip with Alby -

+
+
Alby
+

Require alby account

- - -
+ + +
diff --git a/src/app/nwc/components/other.tsx b/src/app/nwc/components/other.tsx new file mode 100644 index 00000000..a775940b --- /dev/null +++ b/src/app/nwc/components/other.tsx @@ -0,0 +1,166 @@ +import * as Dialog from '@radix-ui/react-dialog'; +import { useState } from 'react'; +import { Resolver, useForm } from 'react-hook-form'; + +import { useStorage } from '@libs/storage/provider'; + +import { ArrowRightCircleIcon, CancelIcon, LoaderIcon, WorldIcon } from '@shared/icons'; + +import { useStronghold } from '@stores/stronghold'; + +type FormValues = { + uri: string; +}; + +const resolver: Resolver = async (values) => { + return { + values: values.uri ? values : {}, + errors: !values.uri + ? { + uri: { + type: 'required', + message: 'This is required.', + }, + } + : {}, + }; +}; + +export function NWCOther() { + const { db } = useStorage(); + const { + register, + setError, + handleSubmit, + formState: { errors, isDirty, isValid }, + } = useForm({ resolver }); + + const [isOpen, setIsOpen] = useState(false); + const [isLoading, setIsloading] = useState(false); + + const setWalletConnectURL = useStronghold((state) => state.setWalletConnectURL); + + const onSubmit = async (data: { [x: string]: string }) => { + try { + if (!data.uri.startsWith('nostr+walletconnect:')) { + setError('uri', { + type: 'custom', + message: + 'Connect URI is required and must start with format nostr+walletconnect:, please check again', + }); + return; + } + + setIsloading(true); + + const uriObj = new URL(data.uri); + const params = new URLSearchParams(uriObj.search); + + if (params.has('relay') && params.has('secret')) { + await db.secureSave('walletConnectURL', data.uri, 'alby'); + setWalletConnectURL(data.uri); + setIsloading(false); + } + } catch (e) { + setIsloading(false); + setError('uri', { + type: 'custom', + message: + 'Connect URI is required and must start with format nostr+walletconnect:, please check again', + }); + } + }; + + return ( + +
+
+
+ +
+
+
URI String
+

+ Using format nostr+walletconnect:// +

+
+
+ + + +
+ + + +
+
+
+
+ + Nostr Wallet Connect + + + + +
+
+
+
+
+ + + + {errors.uri &&

{errors.uri.message}

} +
+
+
+ + + All information will be encrypted and stored on the local machine. + +
+
+
+
+
+
+ ); +} diff --git a/src/app/nwc/index.tsx b/src/app/nwc/index.tsx new file mode 100644 index 00000000..90955791 --- /dev/null +++ b/src/app/nwc/index.tsx @@ -0,0 +1,21 @@ +import { NWCAlby } from '@app/nwc/components/alby'; +import { NWCOther } from '@app/nwc/components/other'; + +export function NWCScreen() { + return ( +
+
+
+

Nostr Wallet Connect

+

+ Sending tips easily via Bitcoin Lightning. +

+
+
+ + +
+
+
+ ); +} diff --git a/src/shared/icons/index.ts b/src/shared/icons/index.ts index 6590a580..2c14749b 100644 --- a/src/shared/icons/index.ts +++ b/src/shared/icons/index.ts @@ -63,3 +63,4 @@ export * from './article'; export * from './follows'; export * from './alby'; export * from './stars'; +export * from './nwc'; diff --git a/src/shared/icons/nwc.tsx b/src/shared/icons/nwc.tsx new file mode 100644 index 00000000..ed4a434e --- /dev/null +++ b/src/shared/icons/nwc.tsx @@ -0,0 +1,22 @@ +import { SVGProps } from 'react'; + +export function NwcIcon(props: JSX.IntrinsicAttributes & SVGProps) { + return ( + + + + + ); +} diff --git a/src/shared/navigation.tsx b/src/shared/navigation.tsx index f14fc1f4..0dbfa3c9 100644 --- a/src/shared/navigation.tsx +++ b/src/shared/navigation.tsx @@ -7,23 +7,24 @@ import { ChatsList } from '@app/chats/components/list'; import { useStorage } from '@libs/storage/provider'; import { ActiveAccount } from '@shared/accounts/active'; -import { AlbyConnectButton } from '@shared/alby'; import { ComposerModal } from '@shared/composer'; import { Frame } from '@shared/frame'; -import { BellIcon, NavArrowDownIcon, SpaceIcon } from '@shared/icons'; +import { BellIcon, NavArrowDownIcon, NwcIcon, SpaceIcon } from '@shared/icons'; import { useActivities } from '@stores/activities'; import { useSidebar } from '@stores/sidebar'; -import { useStronghold } from '@stores/stronghold'; import { compactNumber } from '@utils/number'; export function Navigation() { const { db } = useStorage(); - const walletConnectURL = useStronghold((state) => state.walletConnectURL); const [totalNewActivities] = useActivities((state) => [state.totalNewActivities]); const [chats, toggleChats] = useSidebar((state) => [state.chats, state.toggleChats]); + const [integrations, toggleIntegrations] = useSidebar((state) => [ + state.integrations, + state.toggleIntegrations, + ]); return ( @@ -77,6 +78,44 @@ export function Navigation() { ) : null}
+ +
+ + + + + + twMerge( + 'flex h-10 items-center gap-2.5 rounded-r-lg border-l-2 pl-4 pr-2', + isActive + ? 'border-fuchsia-500 bg-white/5 text-white' + : 'border-transparent text-white/80' + ) + } + > + + + + Wallet Connect + + +
+
@@ -101,11 +140,6 @@ export function Navigation() {
- {!walletConnectURL ? ( -
- -
- ) : null}
diff --git a/src/stores/sidebar.ts b/src/stores/sidebar.ts index ba7b17aa..0bfeb0b0 100644 --- a/src/stores/sidebar.ts +++ b/src/stores/sidebar.ts @@ -4,8 +4,10 @@ import { createJSONStorage, persist } from 'zustand/middleware'; interface SidebarState { feeds: boolean; chats: boolean; + integrations: boolean; toggleFeeds: () => void; toggleChats: () => void; + toggleIntegrations: () => void; } export const useSidebar = create()( @@ -13,12 +15,14 @@ export const useSidebar = create()( (set) => ({ feeds: true, chats: true, + integrations: true, toggleFeeds: () => set((state) => ({ feeds: !state.feeds })), toggleChats: () => set((state) => ({ chats: !state.chats })), + toggleIntegrations: () => set((state) => ({ integrations: !state.integrations })), }), { name: 'sidebar', - storage: createJSONStorage(() => sessionStorage), + storage: createJSONStorage(() => localStorage), } ) );