diff --git a/package.json b/package.json index 99096bb6..b0ac8a0f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,10 @@ "@nostr-dev-kit/ndk": "0.6.0", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-tooltip": "^1.0.6", + "@tanstack/query-sync-storage-persister": "^4.29.19", "@tanstack/react-query": "^4.29.19", + "@tanstack/react-query-devtools": "^4.29.19", + "@tanstack/react-query-persist-client": "^4.29.19", "@tanstack/react-virtual": "3.0.0-beta.54", "@tauri-apps/api": "^1.4.0", "cheerio": "1.0.0-rc.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e4629599..f062af93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,9 +13,18 @@ dependencies: '@radix-ui/react-tooltip': specifier: ^1.0.6 version: 1.0.6(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + '@tanstack/query-sync-storage-persister': + specifier: ^4.29.19 + version: 4.29.19 '@tanstack/react-query': specifier: ^4.29.19 version: 4.29.19(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-query-devtools': + specifier: ^4.29.19 + version: 4.29.19(@tanstack/react-query@4.29.19)(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-query-persist-client': + specifier: ^4.29.19 + version: 4.29.19(@tanstack/react-query@4.29.19) '@tanstack/react-virtual': specifier: 3.0.0-beta.54 version: 3.0.0-beta.54(react@18.2.0) @@ -1306,10 +1315,53 @@ packages: tailwindcss: 3.3.2 dev: true + /@tanstack/match-sorter-utils@8.8.4: + resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==} + engines: {node: '>=12'} + dependencies: + remove-accents: 0.4.2 + dev: false + /@tanstack/query-core@4.29.19: resolution: {integrity: sha512-uPe1DukeIpIHpQi6UzIgBcXsjjsDaLnc7hF+zLBKnaUlh7jFE/A+P8t4cU4VzKPMFB/C970n/9SxtpO5hmIRgw==} dev: false + /@tanstack/query-persist-client-core@4.29.19: + resolution: {integrity: sha512-rr6p3xwEZCz3cEDZsj3QGePf6PG44WxRUGQVcm2JFPZOq9TkG/0i5+hQ3STiHm1Fj6qwCH8xIi62L8kG0zRj/Q==} + dependencies: + '@tanstack/query-core': 4.29.19 + dev: false + + /@tanstack/query-sync-storage-persister@4.29.19: + resolution: {integrity: sha512-B3wDl3D3YBFTlY2yeXecEh4NEG/8Hr8pqsxnWJijRwBqvOKlqD4bUgk5kl5nbn1mShD2vnQ+yvH900/11X29Zw==} + dependencies: + '@tanstack/query-persist-client-core': 4.29.19 + dev: false + + /@tanstack/react-query-devtools@4.29.19(@tanstack/react-query@4.29.19)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-rL2xqTPr+7gJvVGwyq8E8CWqqw950N4lZ6ffJeNX0qqymKHxHW1FM6nZaYt7Aufs/bXH0m1L9Sj3kDGQbp0rwg==} + peerDependencies: + '@tanstack/react-query': 4.29.19 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@tanstack/match-sorter-utils': 8.8.4 + '@tanstack/react-query': 4.29.19(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + superjson: 1.12.4 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + + /@tanstack/react-query-persist-client@4.29.19(@tanstack/react-query@4.29.19): + resolution: {integrity: sha512-LfcasTosdnI9K66HTP0Rk72Ypza3tCgrcF9bc2qFlKsBleYOYo8bz7/GiiOHj1SQH4GRQlKB+P4+/it+qlJg4g==} + peerDependencies: + '@tanstack/react-query': 4.29.19 + dependencies: + '@tanstack/query-persist-client-core': 4.29.19 + '@tanstack/react-query': 4.29.19(react-dom@18.2.0)(react@18.2.0) + dev: false + /@tanstack/react-query@4.29.19(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-XiTIOHHQ5Cw1WUlHaD4fmVUMhoWjuNJlAeJGq7eM4BraI5z7y8WkZO+NR8PSuRnQGblpuVdjClQbDFtwxTtTUw==} peerDependencies: @@ -2143,6 +2195,13 @@ packages: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: false + /copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.15 + dev: false + /create-esm-loader@0.2.3: resolution: {integrity: sha512-cllzD6IU/mzXBs5OdQVWL3+ne5Elpu3Wdm7h5OldMbGXk76yr9XzHlQXWJ4zfs0ZAibe26rkbs4KvMAJm7fIZA==} engines: {node: '>=14.x'} @@ -3451,6 +3510,11 @@ packages: dependencies: call-bind: 1.0.2 + /is-what@4.1.15: + resolution: {integrity: sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==} + engines: {node: '>=12.13'} + dev: false + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -4713,6 +4777,10 @@ packages: define-properties: 1.2.0 functions-have-names: 1.2.3 + /remove-accents@0.4.2: + resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -5116,6 +5184,13 @@ packages: ts-interface-checker: 0.1.13 dev: true + /superjson@1.12.4: + resolution: {integrity: sha512-vkpPQAxdCg9SLfPv5GPC5fnGrui/WryktoN9O5+Zif/14QIMjw+RITf/5LbBh+9QpBFb3KNvJth+puz2H8o6GQ==} + engines: {node: '>=10'} + dependencies: + copy-anything: 3.0.5 + dev: false + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} diff --git a/src/app/root.tsx b/src/app/root.tsx index 88347449..1fbd772f 100644 --- a/src/app/root.tsx +++ b/src/app/root.tsx @@ -1,14 +1,14 @@ -import { NDKFilter } from '@nostr-dev-kit/ndk'; +import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk'; +import { useQueryClient } from '@tanstack/react-query'; import { useContext, useEffect, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { prefetchEvents } from '@libs/ndk'; import { countTotalNotes, - createChannelMessage, createChat, createNote, - getChannels, + getAllPubkeys, getLastLogin, updateLastLogin, } from '@libs/storage'; @@ -21,10 +21,12 @@ import { useAccount } from '@utils/hooks/useAccount'; const totalNotes = await countTotalNotes(); const lastLogin = await getLastLogin(); +const users = await getAllPubkeys(); export function Root() { const ndk = useContext(RelayContext); const now = useRef(new Date()); + const queryClient = useQueryClient(); const navigate = useNavigate(); const { status, account } = useAccount(); @@ -99,6 +101,34 @@ export function Root() { } } + async function fetchUsersProfile() { + const authors = []; + + users.forEach((user) => { + if (user.sender_pubkey) { + authors.push(user.sender_pubkey); + } else { + authors.push(user.pubkey); + } + }); + + const filter: NDKFilter = { + authors: authors, + kinds: [0], + }; + + const events = await ndk.fetchEvents(filter); + console.log('authors', events); + + events.forEach((event: NDKEvent) => { + const profile = JSON.parse(event.content); + profile['image'] = profile.picture; + queryClient.setQueryData(['user', event.pubkey], profile); + }); + + return true; + } + /* async function fetchChannelMessages() { try { @@ -144,8 +174,9 @@ export function Root() { const notes = await fetchNotes(); if (notes) { const chats = await fetchChats(); + const users = await fetchUsersProfile(); // const channels = await fetchChannelMessages(); - if (chats) { + if (chats && users) { const now = Math.floor(Date.now() / 1000); await updateLastLogin(now); navigate('/app/space', { replace: true }); diff --git a/src/libs/storage.tsx b/src/libs/storage.tsx index b6bcfff6..b7cdd14c 100644 --- a/src/libs/storage.tsx +++ b/src/libs/storage.tsx @@ -184,6 +184,15 @@ export async function createReplyNote( ); } +// get all pubkeys in db +export async function getAllPubkeys() { + const db = await connect(); + const notes: any = await db.select('SELECT DISTINCT pubkey FROM notes'); + const replies: any = await db.select('SELECT DISTINCT pubkey FROM replies'); + const chats: any = await db.select('SELECT DISTINCT sender_pubkey FROM chats'); + return [...notes, ...replies, ...chats]; +} + // get all channels export async function getChannels() { const db = await connect(); diff --git a/src/main.tsx b/src/main.tsx index 91d7bc2b..c945adab 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,4 +1,7 @@ -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'; +import { QueryClient } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'; import { createRoot } from 'react-dom/client'; import { getSetting } from '@libs/storage'; @@ -17,13 +20,18 @@ const queryClient = new QueryClient({ }, }); +const persister = createSyncStoragePersister({ + storage: window.localStorage, +}); + const container = document.getElementById('root'); const root = createRoot(container); root.render( - + - + + ); diff --git a/src/shared/notes/preview/image.tsx b/src/shared/notes/preview/image.tsx index 0b58218e..43df8a58 100644 --- a/src/shared/notes/preview/image.tsx +++ b/src/shared/notes/preview/image.tsx @@ -5,7 +5,7 @@ export function ImagePreview({ urls, truncate }: { urls: string[]; truncate?: bo
{urls.map((url) => ( -
+
{ if (url.match(/\.(jpg|jpeg|gif|png|webp|avif)$/)) { // image url content.images.push(url); // remove url from original content - content.parsed = reactStringReplace(content.parsed, url, () => null); + content.parsed = reactStringReplace(content.parsed, url, () => ''); } else if (url.match(/\.(mp4|webm|mov|ogv|avi|mp3)$/)) { // video content.videos.push(url); // remove url from original content - content.parsed = reactStringReplace(content.parsed, url, () => null); + content.parsed = reactStringReplace(content.parsed, url, () => ''); } else { if (content.links.length < 1) { // push to store content.links.push(url); // remove url from original content - content.parsed = reactStringReplace(content.parsed, url, () => null); + content.parsed = reactStringReplace(content.parsed, url, () => ''); } else { - content.parsed = reactStringReplace(content.parsed, /#(\w+)/g, (match, i) => ( + content.parsed = reactStringReplace(content.parsed, url, (match, i) => ( {match} @@ -99,17 +90,18 @@ export function parser(event: any) { // parse hashtag content.parsed = reactStringReplace(content.parsed, /#(\w+)/g, (match, i) => ( - #{match} - + )); // clean array - content.parsed = content.parsed.filter((el) => el !== '\n'); + content.parsed = content.parsed.filter( + (el) => el !== '\n' && el !== '\n\n' && el !== '\n' + ); return content; }