diff --git a/packages/ark/package.json b/packages/ark/package.json index 40038843..eb71789c 100644 --- a/packages/ark/package.json +++ b/packages/ark/package.json @@ -32,6 +32,7 @@ "@tiptap/extension-mention": "^2.1.13", "@tiptap/react": "^2.1.13", "@vidstack/react": "^1.9.8", + "get-urls": "^12.1.0", "markdown-to-jsx": "^7.3.2", "minidenticons": "^4.2.0", "nanoid": "^5.0.4", diff --git a/packages/ark/src/hooks/useRichContent.tsx b/packages/ark/src/hooks/useRichContent.tsx index 058117d2..7b67901b 100644 --- a/packages/ark/src/hooks/useRichContent.tsx +++ b/packages/ark/src/hooks/useRichContent.tsx @@ -1,3 +1,4 @@ +import getUrls from "get-urls"; import { nanoid } from "nanoid"; import { nip19 } from "nostr-tools"; import { ReactNode } from "react"; @@ -27,6 +28,10 @@ const NOSTR_MENTIONS = [ ]; const NOSTR_EVENTS = [ + "@nevent1", + "@note1", + "@nostr:note1", + "@nostr:nevent1", "nostr:note1", "note1", "nostr:nevent1", @@ -37,44 +42,68 @@ const NOSTR_EVENTS = [ // const BITCOINS = ['lnbc', 'bc1p', 'bc1q']; -const IMAGES = [".jpg", ".jpeg", ".gif", ".png", ".webp", ".avif", ".tiff"]; +const IMAGES = ["jpg", "jpeg", "gif", "png", "webp", "avif", "tiff"]; const VIDEOS = [ - ".mp4", - ".mov", - ".webm", - ".wmv", - ".flv", - ".mts", - ".avi", - ".ogv", - ".mkv", - ".mp3", - ".m3u8", + "mp4", + "mov", + "webm", + "wmv", + "flv", + "mts", + "avi", + "ogv", + "mkv", + "m3u8", ]; -export function useRichContent(content: string, textmode = false) { +const AUDIOS = ["mp3", "ogg", "wav"]; + +export function useRichContent(content: string) { const storage = useStorage(); let parsedContent: string | ReactNode[] = content.replace(/\n+/g, "\n"); let linkPreview: string; let images: string[] = []; let videos: string[] = []; + let audios: string[] = []; let events: string[] = []; const text = parsedContent; const words = text.split(/( |\n)/); + const urls = [...getUrls(text)]; - if (!textmode) { - if (storage.settings.media) { - images = words.filter((word) => IMAGES.some((el) => word.endsWith(el))); - videos = words.filter((word) => VIDEOS.some((el) => word.endsWith(el))); - } - events = words.filter((word) => - NOSTR_EVENTS.some((el) => word.startsWith(el)), + if (storage.settings.media && !storage.settings.lowPowerMode) { + images = urls.filter((word) => + IMAGES.some((el) => { + const url = new URL(word); + const extension = url.pathname.split(".")[1]; + if (extension === el) return true; + return false; + }), + ); + videos = urls.filter((word) => + VIDEOS.some((el) => { + const url = new URL(word); + const extension = url.pathname.split(".")[1]; + if (extension === el) return true; + return false; + }), + ); + audios = urls.filter((word) => + AUDIOS.some((el) => { + const url = new URL(word); + const extension = url.pathname.split(".")[1]; + if (extension === el) return true; + return false; + }), ); } + events = words.filter((word) => + NOSTR_EVENTS.some((el) => word.startsWith(el)), + ); + const hashtags = words.filter((word) => word.startsWith("#")); const mentions = words.filter((word) => NOSTR_MENTIONS.some((el) => word.startsWith(el)), @@ -97,6 +126,14 @@ export function useRichContent(content: string, textmode = false) { } } + if (audios.length) { + for (const audio of audios) { + parsedContent = reactStringReplace(parsedContent, audio, (match, i) => ( + + )); + } + } + if (hashtags.length) { for (const hashtag of hashtags) { parsedContent = reactStringReplace( @@ -174,7 +211,7 @@ export function useRichContent(content: string, textmode = false) { (match, i) => { const url = new URL(match); - if (!linkPreview && !textmode) { + if (!linkPreview) { linkPreview = match; return ; } diff --git a/packages/ark/src/provider.tsx b/packages/ark/src/provider.tsx index df939e4b..21f47852 100644 --- a/packages/ark/src/provider.tsx +++ b/packages/ark/src/provider.tsx @@ -2,7 +2,12 @@ import { LoaderIcon } from "@lume/icons"; import { NDKCacheAdapterTauri } from "@lume/ndk-cache-tauri"; import { LumeStorage } from "@lume/storage"; import { QUOTES, delay } from "@lume/utils"; -import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk"; +import NDK, { + NDKNip46Signer, + NDKPrivateKeySigner, + NDKRelay, + NDKRelayAuthPolicies, +} from "@nostr-dev-kit/ndk"; import { ndkAdapter } from "@nostr-fetch/adapter-ndk"; import { platform } from "@tauri-apps/plugin-os"; import { relaunch } from "@tauri-apps/plugin-process"; @@ -150,6 +155,12 @@ const LumeProvider = ({ children }: PropsWithChildren) => { // connect await ndk.connect(3000); + // auth + ndk.relayAuthDefaultPolicy = (relay: NDKRelay, challenge: string) => { + const signIn = NDKRelayAuthPolicies.signIn({ ndk, signer }); + return signIn(relay, challenge); + }; + // update account's metadata if (storage.account) { const user = ndk.getUser({ pubkey: storage.account.pubkey }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fe29e9b..d2413c3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -498,6 +498,9 @@ importers: '@vidstack/react': specifier: ^1.9.8 version: 1.9.8(@types/react@18.2.45)(react@18.2.0) + get-urls: + specifier: ^12.1.0 + version: 12.1.0 markdown-to-jsx: specifier: ^7.3.2 version: 7.3.2(react@18.2.0) @@ -3184,6 +3187,13 @@ packages: fsevents: 2.3.3 dev: true + /clone-regexp@3.0.0: + resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==} + engines: {node: '>=12'} + dependencies: + is-regexp: 3.1.0 + dev: false + /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -3252,6 +3262,11 @@ packages: engines: {node: '>= 0.6'} dev: true + /convert-hrtime@5.0.0: + resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} + engines: {node: '>=12'} + dev: false + /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: true @@ -3825,6 +3840,11 @@ packages: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} dev: true + /function-timeout@0.1.1: + resolution: {integrity: sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==} + engines: {node: '>=14.16'} + dev: false + /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} @@ -3865,6 +3885,17 @@ packages: get-intrinsic: 1.2.2 dev: true + /get-urls@12.1.0: + resolution: {integrity: sha512-qHO+QmPiI1bEw0Y/m+WMAAx/UoEEXLZwEx0DVaKMtlHNrKbMeV960LryIpd+E2Ykb9XkVHmVtpbCsmul3GhR0g==} + engines: {node: '>=16'} + dependencies: + normalize-url: 8.0.0 + super-regex: 0.2.0 + url-regex-safe: 4.0.0 + transitivePeerDependencies: + - re2 + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4027,6 +4058,11 @@ packages: loose-envify: 1.4.0 dev: false + /ip-regex@4.3.0: + resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} + engines: {node: '>=8'} + dev: false + /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -4140,6 +4176,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-regexp@3.1.0: + resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} + engines: {node: '>=12'} + dev: false + /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: @@ -4563,6 +4604,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + dev: false + /nostr-fetch@0.14.1: resolution: {integrity: sha512-0r9loOVutJalz8OFK4vMWWcxGlpGdhcR+/xCro/k6V75uRrYchMYNrgJWP3fT7Sn89JtUkUqRYi4P9hh5qdruA==} dependencies: @@ -5450,6 +5496,15 @@ packages: ts-interface-checker: 0.1.13 dev: true + /super-regex@0.2.0: + resolution: {integrity: sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==} + engines: {node: '>=14.16'} + dependencies: + clone-regexp: 3.0.0 + function-timeout: 0.1.1 + time-span: 5.1.0 + dev: false + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -5559,6 +5614,13 @@ packages: engines: {node: '>=10'} dev: false + /time-span@5.1.0: + resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} + engines: {node: '>=12'} + dependencies: + convert-hrtime: 5.0.0 + dev: false + /timer2@1.0.0: resolution: {integrity: sha512-UOZql+P2ET0da+B7V3/RImN3IhC5ghb+9cpecfUhmYGIm0z73dDr3A781nBLnFYmRzeT1AmoT4w9Lgr8n7n7xg==} dev: true @@ -5581,6 +5643,11 @@ packages: prosemirror-markdown: 1.12.0 dev: false + /tlds@1.248.0: + resolution: {integrity: sha512-noj0KdpWTBhwsKxMOXk0rN9otg4kTgLm4WohERRHbJ9IY+kSDKr3RmjitaQ3JFzny+DyvBOQKlFZhp0G0qNSfg==} + hasBin: true + dev: false + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -5804,6 +5871,19 @@ packages: punycode: 2.3.1 dev: true + /url-regex-safe@4.0.0: + resolution: {integrity: sha512-BrnFCWKNFrFnRzKD66NtJqQepfJrUHNPvPxE5y5NSAhXBb4OlobQjt7907Jm4ItPiXaeX+dDWMkcnOd4jR9N8A==} + engines: {node: '>= 14'} + peerDependencies: + re2: ^1.20.1 + peerDependenciesMeta: + re2: + optional: true + dependencies: + ip-regex: 4.3.0 + tlds: 1.248.0 + dev: false + /use-callback-ref@1.3.0(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'}