diff --git a/package.json b/package.json
index 1d815f60..2f66ea30 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
"@tiptap/react": "^2.1.11",
"@tiptap/starter-kit": "^2.1.11",
"@tiptap/suggestion": "^2.1.11",
+ "@vidstack/react": "^1.0.2",
"dayjs": "^1.11.10",
"destr": "^2.0.1",
"html-to-text": "^9.0.5",
@@ -55,7 +56,6 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.46.2",
"react-markdown": "^8.0.7",
- "react-player": "^2.13.0",
"react-router-dom": "^6.16.0",
"react-textarea-autosize": "^8.5.3",
"reactflow": "^11.9.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 81bd9dd9..4428170f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -71,6 +71,9 @@ dependencies:
'@tiptap/suggestion':
specifier: ^2.1.11
version: 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.11)
+ '@vidstack/react':
+ specifier: ^1.0.2
+ version: 1.0.2(@types/react@18.2.23)(react@18.2.0)
dayjs:
specifier: ^1.11.10
version: 1.11.10
@@ -116,9 +119,6 @@ dependencies:
react-markdown:
specifier: ^8.0.7
version: 8.0.7(@types/react@18.2.23)(react@18.2.0)
- react-player:
- specifier: ^2.13.0
- version: 2.13.0(react@18.2.0)
react-router-dom:
specifier: ^6.16.0
version: 6.16.0(react-dom@18.2.0)(react@18.2.0)
@@ -133,16 +133,16 @@ dependencies:
version: 3.0.1
tauri-plugin-sql-api:
specifier: github:tauri-apps/tauri-plugin-sql#v1
- version: github.com/tauri-apps/tauri-plugin-sql/533198dd3b6cfca36d876918d22efcdaac43065a
+ version: github.com/tauri-apps/tauri-plugin-sql/1c79471feb06366fe1c11cb1cb6c67bcdb80c215
tauri-plugin-store-api:
specifier: github:tauri-apps/tauri-plugin-store#v1
- version: github.com/tauri-apps/tauri-plugin-store/66e06b7830037fdae0b42b5499e23334eaf4e017
+ version: github.com/tauri-apps/tauri-plugin-store/1a741b721ed1eae0de0d811ecfe86fc6ad54fb73
tauri-plugin-stronghold-api:
specifier: github:tauri-apps/tauri-plugin-stronghold#v1
- version: github.com/tauri-apps/tauri-plugin-stronghold/4684fed1f5e7eb01885e40114accdcecb61962ed
+ version: github.com/tauri-apps/tauri-plugin-stronghold/d87b778f48ee12435efcf3f82d2e5efbb9541759
tauri-plugin-upload-api:
specifier: github:tauri-apps/tauri-plugin-upload#v1
- version: github.com/tauri-apps/tauri-plugin-upload/40c0bc302a9dd8304762951e450ee84d53c2037b
+ version: github.com/tauri-apps/tauri-plugin-upload/5348082f7436b01f0b5c08d6ddfc4f760abbac7e
tippy.js:
specifier: ^6.3.7
version: 6.3.7
@@ -1892,11 +1892,6 @@ packages:
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false
- /@tauri-apps/api@1.4.0:
- resolution: {integrity: sha512-Jd6HPoTM1PZSFIzq7FB8VmMu3qSSyo/3lSwLpoapW+lQ41CL5Dow2KryLg+gyazA/58DRWI9vu/XpEeHK4uMdw==}
- engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
- dev: false
-
/@tauri-apps/api@1.5.0:
resolution: {integrity: sha512-yQY9wpVNuiYhLLuyDlu1nBpqJELT1fGp7OctN4rW9I2W1T2p7A3tqPxsEzQprEwneQRBAlPM9vC8NsnMbct+pg==}
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
@@ -2708,6 +2703,18 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
+ /@vidstack/react@1.0.2(@types/react@18.2.23)(react@18.2.0):
+ resolution: {integrity: sha512-ZBTaEFtxmaFX/oB5I9o8qvoQ39jmwTySFxsFfBN7tkcWxKdTOUhwlIgIlFM5H/alJ/qxw13AZvxK2MW6q+le3g==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/react': ^18.0.0
+ react: ^18.0.0
+ dependencies:
+ '@types/react': 18.2.23
+ media-captions: 1.0.0
+ react: 18.2.0
+ dev: false
+
/@vitejs/plugin-react-swc@3.4.0(vite@4.4.9):
resolution: {integrity: sha512-m7UaA4Uvz82N/0EOVpZL4XsFIakRqrFKeSNxa1FBLSXGvWrWRBwmZb4qxk+ZIVAZcW3c3dn5YosomDgx62XWcQ==}
peerDependencies:
@@ -4460,10 +4467,6 @@ packages:
wrap-ansi: 8.1.0
dev: true
- /load-script@1.0.0:
- resolution: {integrity: sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==}
- dev: false
-
/locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -4674,8 +4677,9 @@ packages:
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
dev: false
- /memoize-one@5.2.1:
- resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
+ /media-captions@1.0.0:
+ resolution: {integrity: sha512-605d9sXW+DtJBNzzfL4N6NpOIjigN+kpzS+V1QaCiNNPB7G015/peyw6wfv9iCp8GAP6R5NPyAICZKeuqWPAQQ==}
+ engines: {node: '>=16'}
dev: false
/merge-stream@2.0.0:
@@ -5612,10 +5616,6 @@ packages:
scheduler: 0.23.0
dev: false
- /react-fast-compare@3.2.2:
- resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
- dev: false
-
/react-hook-form@7.46.2(react@18.2.0):
resolution: {integrity: sha512-x1DWmHQchV7x2Rq9l99M/cQHC8JGchAnw9Z0uTz5KrPa0bTl/Inm1NR7ceOARfIrkNuQNAhuSuZPYa6k7QYn3Q==}
engines: {node: '>=12.22.0'}
@@ -5659,19 +5659,6 @@ packages:
- supports-color
dev: false
- /react-player@2.13.0(react@18.2.0):
- resolution: {integrity: sha512-gkY7ZdbVFztlKFFhCPcnDrFQm+L399b8fhWsKatZ+b2wpKJwfUHBXQFMRxqYQGT0ic1/wQ7D7EZEWy7ZBqk2pw==}
- peerDependencies:
- react: '>=16.6.0'
- dependencies:
- deepmerge: 4.3.1
- load-script: 1.0.0
- memoize-one: 5.2.1
- prop-types: 15.8.1
- react: 18.2.0
- react-fast-compare: 3.2.2
- dev: false
-
/react-remove-scroll-bar@2.3.4(@types/react@18.2.23)(react@18.2.0):
resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==}
engines: {node: '>=10'}
@@ -6758,34 +6745,34 @@ packages:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: false
- github.com/tauri-apps/tauri-plugin-sql/533198dd3b6cfca36d876918d22efcdaac43065a:
- resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-sql/tar.gz/533198dd3b6cfca36d876918d22efcdaac43065a}
+ github.com/tauri-apps/tauri-plugin-sql/1c79471feb06366fe1c11cb1cb6c67bcdb80c215:
+ resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-sql/tar.gz/1c79471feb06366fe1c11cb1cb6c67bcdb80c215}
name: tauri-plugin-sql-api
version: 0.0.0
dependencies:
- '@tauri-apps/api': 1.4.0
+ '@tauri-apps/api': 1.5.0
dev: false
- github.com/tauri-apps/tauri-plugin-store/66e06b7830037fdae0b42b5499e23334eaf4e017:
- resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-store/tar.gz/66e06b7830037fdae0b42b5499e23334eaf4e017}
+ github.com/tauri-apps/tauri-plugin-store/1a741b721ed1eae0de0d811ecfe86fc6ad54fb73:
+ resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-store/tar.gz/1a741b721ed1eae0de0d811ecfe86fc6ad54fb73}
name: tauri-plugin-store-api
version: 0.0.0
dependencies:
- '@tauri-apps/api': 1.4.0
+ '@tauri-apps/api': 1.5.0
dev: false
- github.com/tauri-apps/tauri-plugin-stronghold/4684fed1f5e7eb01885e40114accdcecb61962ed:
- resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-stronghold/tar.gz/4684fed1f5e7eb01885e40114accdcecb61962ed}
+ github.com/tauri-apps/tauri-plugin-stronghold/d87b778f48ee12435efcf3f82d2e5efbb9541759:
+ resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-stronghold/tar.gz/d87b778f48ee12435efcf3f82d2e5efbb9541759}
name: tauri-plugin-stronghold-api
version: 0.0.0
dependencies:
- '@tauri-apps/api': 1.4.0
+ '@tauri-apps/api': 1.5.0
dev: false
- github.com/tauri-apps/tauri-plugin-upload/40c0bc302a9dd8304762951e450ee84d53c2037b:
- resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-upload/tar.gz/40c0bc302a9dd8304762951e450ee84d53c2037b}
+ github.com/tauri-apps/tauri-plugin-upload/5348082f7436b01f0b5c08d6ddfc4f760abbac7e:
+ resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-upload/tar.gz/5348082f7436b01f0b5c08d6ddfc4f760abbac7e}
name: tauri-plugin-upload-api
version: 0.0.0
dependencies:
- '@tauri-apps/api': 1.4.0
+ '@tauri-apps/api': 1.5.0
dev: false
diff --git a/src/app.tsx b/src/app.tsx
index d3197cb7..b99127cf 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -1,11 +1,12 @@
import { message } from '@tauri-apps/api/dialog';
-import { RouterProvider, createBrowserRouter, redirect } from 'react-router-dom';
+import { fetch } from '@tauri-apps/api/http';
+import '@vidstack/react/player/styles/default/theme.css';
+import { RouterProvider, createBrowserRouter, defer, redirect } from 'react-router-dom';
import 'reactflow/dist/style.css';
import { AuthCreateScreen } from '@app/auth/create';
import { AuthImportScreen } from '@app/auth/import';
import { OnboardingScreen } from '@app/auth/onboarding';
-import { BrowseScreen } from '@app/browse';
import { ErrorScreen } from '@app/error';
import { useStorage } from '@libs/storage/provider';
@@ -50,6 +51,17 @@ export default function App() {
}
};
+ const relayLoader = async ({ params }) => {
+ return defer({
+ relay: fetch(`https://${params.url}`, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/nostr+json',
+ },
+ }).then((res) => res.data),
+ });
+ };
+
const router = createBrowserRouter([
{
path: '/',
@@ -64,27 +76,6 @@ export default function App() {
return { Component: SpaceScreen };
},
},
- {
- path: 'browse',
- element: ,
- errorElement: ,
- children: [
- {
- path: '',
- async lazy() {
- const { BrowseUsersScreen } = await import('@app/browse/users');
- return { Component: BrowseUsersScreen };
- },
- },
- {
- path: 'relays',
- async lazy() {
- const { BrowseRelaysScreen } = await import('@app/browse/relays');
- return { Component: BrowseRelaysScreen };
- },
- },
- ],
- },
{
path: 'users/:pubkey',
async lazy() {
@@ -113,6 +104,30 @@ export default function App() {
return { Component: NWCScreen };
},
},
+ {
+ path: 'explore',
+ async lazy() {
+ const { ExploreScreen } = await import('@app/explore');
+ return { Component: ExploreScreen };
+ },
+ },
+ {
+ path: 'relays',
+ async lazy() {
+ const { RelaysScreen } = await import('@app/relays');
+ return { Component: RelaysScreen };
+ },
+ children: [
+ {
+ path: ':url',
+ loader: relayLoader,
+ async lazy() {
+ const { RelayScreen } = await import('@app/relays/relay');
+ return { Component: RelayScreen };
+ },
+ },
+ ],
+ },
],
},
{
diff --git a/src/app/browse/index.tsx b/src/app/browse/index.tsx
deleted file mode 100644
index cb538e5e..00000000
--- a/src/app/browse/index.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { NavLink, Outlet } from 'react-router-dom';
-import { ReactFlowProvider } from 'reactflow';
-import { twMerge } from 'tailwind-merge';
-
-export function BrowseScreen() {
- return (
-
-
-
-
-
-
- twMerge(
- 'inline-flex h-7 w-20 items-center justify-center rounded-full text-sm font-semibold',
- isActive ? 'bg-white/10 hover:bg-white/20' : ' hover:bg-white/5'
- )
- }
- >
- Users
-
-
- twMerge(
- 'inline-flex h-7 w-20 items-center justify-center rounded-full text-sm font-semibold',
- isActive ? 'bg-white/10 hover:bg-white/20' : ' hover:bg-white/5'
- )
- }
- >
- Relays
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/app/browse/relays.tsx b/src/app/browse/relays.tsx
deleted file mode 100644
index 6047990b..00000000
--- a/src/app/browse/relays.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-export function BrowseRelaysScreen() {
- return (
-
- );
-}
diff --git a/src/app/browse/components/edge.tsx b/src/app/explore/components/edge.tsx
similarity index 100%
rename from src/app/browse/components/edge.tsx
rename to src/app/explore/components/edge.tsx
diff --git a/src/app/browse/components/groupTitle.tsx b/src/app/explore/components/groupTitle.tsx
similarity index 100%
rename from src/app/browse/components/groupTitle.tsx
rename to src/app/explore/components/groupTitle.tsx
diff --git a/src/app/browse/components/line.tsx b/src/app/explore/components/line.tsx
similarity index 100%
rename from src/app/browse/components/line.tsx
rename to src/app/explore/components/line.tsx
diff --git a/src/app/browse/components/userGroupNode.tsx b/src/app/explore/components/userGroupNode.tsx
similarity index 92%
rename from src/app/browse/components/userGroupNode.tsx
rename to src/app/explore/components/userGroupNode.tsx
index 7fe58277..0d06c297 100644
--- a/src/app/browse/components/userGroupNode.tsx
+++ b/src/app/explore/components/userGroupNode.tsx
@@ -1,6 +1,6 @@
import { Handle, Position } from 'reactflow';
-import { UserWithDrawer } from '@app/browse/components/userWithDrawer';
+import { UserWithDrawer } from '@app/explore/components/userWithDrawer';
import { GroupTitle } from './groupTitle';
diff --git a/src/app/browse/components/userLatestPosts.tsx b/src/app/explore/components/userLatestPosts.tsx
similarity index 100%
rename from src/app/browse/components/userLatestPosts.tsx
rename to src/app/explore/components/userLatestPosts.tsx
diff --git a/src/app/browse/components/userNode.tsx b/src/app/explore/components/userNode.tsx
similarity index 100%
rename from src/app/browse/components/userNode.tsx
rename to src/app/explore/components/userNode.tsx
diff --git a/src/app/browse/components/userWithDrawer.tsx b/src/app/explore/components/userWithDrawer.tsx
similarity index 100%
rename from src/app/browse/components/userWithDrawer.tsx
rename to src/app/explore/components/userWithDrawer.tsx
diff --git a/src/app/browse/users.tsx b/src/app/explore/index.tsx
similarity index 71%
rename from src/app/browse/users.tsx
rename to src/app/explore/index.tsx
index c638c546..fac38ae2 100644
--- a/src/app/browse/users.tsx
+++ b/src/app/explore/index.tsx
@@ -2,16 +2,17 @@ import { useCallback, useMemo, useRef } from 'react';
import ReactFlow, {
Background,
ConnectionMode,
+ ReactFlowProvider,
addEdge,
useEdgesState,
useNodesState,
useReactFlow,
} from 'reactflow';
-import { Edge } from '@app/browse//components/edge';
-import { UserGroupNode } from '@app/browse//components/userGroupNode';
-import { Line } from '@app/browse/components/line';
-import { UserNode } from '@app/browse/components/userNode';
+import { Edge } from '@app/explore/components/edge';
+import { Line } from '@app/explore/components/line';
+import { UserGroupNode } from '@app/explore/components/userGroupNode';
+import { UserNode } from '@app/explore/components/userNode';
import { useStorage } from '@libs/storage/provider';
@@ -23,7 +24,7 @@ const getId = () => `${id++}`;
const nodeTypes = { user: UserNode, userGroup: UserGroupNode };
const edgeTypes = { buttonedge: Edge };
-export function BrowseUsersScreen() {
+export function ExploreScreen() {
const { db } = useStorage();
const { getContactsByPubkey } = useNostr();
const { project } = useReactFlow();
@@ -91,26 +92,28 @@ export function BrowseUsersScreen() {
);
return (
-
-
-
-
-
+
+
+
+
+
+
+
);
}
diff --git a/src/app/relays/components/relayList.tsx b/src/app/relays/components/relayList.tsx
new file mode 100644
index 00000000..08084521
--- /dev/null
+++ b/src/app/relays/components/relayList.tsx
@@ -0,0 +1,89 @@
+import { useQuery } from '@tanstack/react-query';
+import { useNavigate } from 'react-router-dom';
+import { VList } from 'virtua';
+
+import { LoaderIcon, PlusIcon, ShareIcon } from '@shared/icons';
+import { User } from '@shared/user';
+
+import { useNostr } from '@utils/hooks/useNostr';
+
+export function RelayList() {
+ const navigate = useNavigate();
+
+ const { getAllRelaysByUsers } = useNostr();
+ const { status, data } = useQuery(
+ ['relays'],
+ async () => {
+ return await getAllRelaysByUsers();
+ },
+ { refetchOnMount: false }
+ );
+
+ const openRelay = (relayUrl: string) => {
+ const url = new URL(relayUrl);
+ navigate(`/relays/${url.hostname}`);
+ };
+
+ return (
+
+ {status === 'loading' ? (
+
+ ) : (
+
+
+
+ All relays used by your follows
+
+
+ {[...data].map(([key, value]) => (
+
+
+
+
+
+
+
+ Relay:
+
+ {key}
+
+
+
+
+ {value.slice(0, 4).map((item) => (
+
+ ))}
+ {value.length > 4 ? (
+
+ +{value.length}
+
+ ) : null}
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/app/relays/components/userRelay.tsx b/src/app/relays/components/userRelay.tsx
new file mode 100644
index 00000000..95b3cd4b
--- /dev/null
+++ b/src/app/relays/components/userRelay.tsx
@@ -0,0 +1,46 @@
+import { useQuery } from '@tanstack/react-query';
+
+import { useNDK } from '@libs/ndk/provider';
+import { useStorage } from '@libs/storage/provider';
+
+export function UserRelay() {
+ const { relayUrls } = useNDK();
+ const { db } = useStorage();
+ const { status, data } = useQuery(
+ ['user-relay'],
+ async () => {
+ return await db.getExplicitRelayUrls();
+ },
+ { refetchOnWindowFocus: false }
+ );
+
+ return (
+
+ {status === 'loading' ? (
+
Loading...
+ ) : (
+
+ {data.map((item) => (
+
+ {relayUrls.includes(item) ? (
+
+
+
+
+ ) : (
+
+
+
+
+ )}
+
{item}
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/src/app/relays/index.tsx b/src/app/relays/index.tsx
new file mode 100644
index 00000000..41cfe7da
--- /dev/null
+++ b/src/app/relays/index.tsx
@@ -0,0 +1,16 @@
+import { RelayList } from '@app/relays/components/relayList';
+import { UserRelay } from '@app/relays/components/userRelay';
+
+export function RelaysScreen() {
+ return (
+
+
+
+
+
Connected relays
+
+
+
+
+ );
+}
diff --git a/src/app/relays/relay.tsx b/src/app/relays/relay.tsx
new file mode 100644
index 00000000..210423b3
--- /dev/null
+++ b/src/app/relays/relay.tsx
@@ -0,0 +1,19 @@
+import { Suspense } from 'react';
+import { Await, useLoaderData } from 'react-router-dom';
+
+export function RelayScreen() {
+ const data: { relay?: { [key: string]: string } } = useLoaderData();
+
+ return (
+
+
Loading...}>
+ Could not load relay information 😬 }
+ >
+ {(resolvedRelay) => {JSON.stringify(resolvedRelay)}
}
+
+
+
+ );
+}
diff --git a/src/app/space/components/toggle.tsx b/src/app/space/components/toggle.tsx
index 07e32c49..1b4eebc3 100644
--- a/src/app/space/components/toggle.tsx
+++ b/src/app/space/components/toggle.tsx
@@ -1,6 +1,6 @@
import { useStorage } from '@libs/storage/provider';
-import { PlusIcon } from '@shared/icons';
+import { HandArrowDownIcon, PlusIcon } from '@shared/icons';
import { WidgetKinds, useWidgets } from '@stores/widgets';
@@ -9,17 +9,22 @@ export function ToggleWidgetList() {
const setWidget = useWidgets((state) => state.setWidget);
return (
-
-
+
+
+
+
+
+
+
);
}
diff --git a/src/shared/icons/handArrowDown.tsx b/src/shared/icons/handArrowDown.tsx
new file mode 100644
index 00000000..3eeeb8de
--- /dev/null
+++ b/src/shared/icons/handArrowDown.tsx
@@ -0,0 +1,29 @@
+import { SVGProps } from 'react';
+
+export function HandArrowDownIcon(
+ props: JSX.IntrinsicAttributes & SVGProps
+) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/index.ts b/src/shared/icons/index.ts
index 24e62684..eb6bf2ca 100644
--- a/src/shared/icons/index.ts
+++ b/src/shared/icons/index.ts
@@ -66,3 +66,4 @@ export * from './stars';
export * from './nwc';
export * from './timeline';
export * from './dots';
+export * from './handArrowDown';
diff --git a/src/shared/navigation.tsx b/src/shared/navigation.tsx
index d3b2530a..14fe54cf 100644
--- a/src/shared/navigation.tsx
+++ b/src/shared/navigation.tsx
@@ -90,7 +90,7 @@ export function Navigation() {
Home
twMerge(
@@ -104,7 +104,24 @@ export function Navigation() {
- Browse
+ Relays
+
+
+ twMerge(
+ 'flex h-10 items-center gap-2.5 rounded-r-lg border-l-2 pl-4 pr-3',
+ isActive
+ ? 'border-fuchsia-500 bg-white/5 text-white'
+ : 'border-transparent text-white/70'
+ )
+ }
+ >
+
+
+
+ Explore
-
+ src={url}
+ poster={`https://thumbnail.video/api/get?url=${url}&seconds=1`}
+ load="visible"
+ aspectRatio="16/9"
+ crossorigin=""
+ >
+
+
);
}
diff --git a/src/shared/notes/preview/image.tsx b/src/shared/notes/preview/image.tsx
index 3d2964e6..31c1be25 100644
--- a/src/shared/notes/preview/image.tsx
+++ b/src/shared/notes/preview/image.tsx
@@ -2,7 +2,6 @@ import { downloadDir } from '@tauri-apps/api/path';
import { download } from 'tauri-plugin-upload-api';
import { DownloadIcon } from '@shared/icons';
-import { Image } from '@shared/image';
export function ImagePreview({ urls, truncate }: { urls: string[]; truncate?: boolean }) {
const downloadImage = async (url: string) => {
@@ -16,12 +15,15 @@ export function ImagePreview({ urls, truncate }: { urls: string[]; truncate?: bo
{urls.map((url) => (
-
);
diff --git a/src/shared/user.tsx b/src/shared/user.tsx
index 13c1a519..7c467bd9 100644
--- a/src/shared/user.tsx
+++ b/src/shared/user.tsx
@@ -29,7 +29,8 @@ export const User = memo(function User({
| 'chat'
| 'large'
| 'thread'
- | 'avatar';
+ | 'avatar'
+ | 'stacked';
embedProfile?: string;
}) {
const { status, user } = useProfile(pubkey, embedProfile);
@@ -186,6 +187,28 @@ export const User = memo(function User({
);
}
+ if (variant === 'stacked') {
+ return (
+
+
+
+
+
+
+ );
+ }
+
if (variant === 'repost') {
return (
diff --git a/src/shared/widgets/eventLoader.tsx b/src/shared/widgets/eventLoader.tsx
index 72492253..0f15b7aa 100644
--- a/src/shared/widgets/eventLoader.tsx
+++ b/src/shared/widgets/eventLoader.tsx
@@ -19,7 +19,7 @@ export function EventLoader({ firstTime }: { firstTime: boolean }) {
useEffect(() => {
async function getEvents() {
const events = await getAllEventsSinceLastLogin();
- console.log('total event found: ', events.data.length);
+ console.log('total new events has found: ', events.data.length);
const promises = await Promise.all(
events.data.map(async (event) => await db.createEvent(event))
diff --git a/src/utils/hooks/useNostr.ts b/src/utils/hooks/useNostr.ts
index dbd4e82c..9aae02ac 100644
--- a/src/utils/hooks/useNostr.ts
+++ b/src/utils/hooks/useNostr.ts
@@ -305,6 +305,31 @@ export function useNostr() {
return events as unknown as NDKEvent[];
};
+ const getAllRelaysByUsers = async () => {
+ const relayMap = new Map();
+ const relayEvents = fetcher.fetchLatestEventsPerAuthor(
+ {
+ authors: db.account.follows,
+ relayUrls: relayUrls,
+ },
+ { kinds: [NDKKind.RelayList] },
+ 5
+ );
+
+ for await (const { author, events } of relayEvents) {
+ if (events[0]) {
+ events[0].tags.forEach((tag) => {
+ const users = relayMap.get(tag[1]);
+
+ if (!users) return relayMap.set(tag[1], [author]);
+ return users.push(author);
+ });
+ }
+ }
+
+ return relayMap;
+ };
+
const publish = async ({
content,
kind,
@@ -450,5 +475,6 @@ export function useNostr() {
upload,
getContactsByPubkey,
getEventsByPubkey,
+ getAllRelaysByUsers,
};
}