`feat: add support for viewing WebSocket links
This commit is contained in:
parent
5aefd7dbde
commit
e1d3d97f9a
16 changed files with 98 additions and 78 deletions
|
|
@ -1,15 +1,16 @@
|
|||
import { isNsfwEvent } from '@renderer/lib/event'
|
||||
import { cn } from '@renderer/lib/utils'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { memo } from 'react'
|
||||
import {
|
||||
embedded,
|
||||
embeddedHashtagRenderer,
|
||||
embeddedNormalUrlRenderer,
|
||||
embeddedNostrNpubRenderer,
|
||||
embeddedNostrProfileRenderer
|
||||
} from '@renderer/embedded'
|
||||
import { isNsfwEvent } from '@renderer/lib/event'
|
||||
import { cn } from '@renderer/lib/utils'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { memo } from 'react'
|
||||
import { EmbeddedNote } from '../Embedded'
|
||||
embeddedNostrProfileRenderer,
|
||||
EmbeddedNote,
|
||||
embeddedWebsocketUrlRenderer
|
||||
} from '../Embedded'
|
||||
import ImageGallery from '../ImageGallery'
|
||||
import VideoPlayer from '../VideoPlayer'
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ const Content = memo(
|
|||
const { content, images, videos, embeddedNotes } = preprocess(event.content)
|
||||
const isNsfw = isNsfwEvent(event)
|
||||
const nodes = embedded(content, [
|
||||
embeddedWebsocketUrlRenderer,
|
||||
embeddedNormalUrlRenderer,
|
||||
embeddedHashtagRenderer,
|
||||
embeddedNostrNpubRenderer,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { toHashtag } from '@renderer/lib/link'
|
||||
import { SecondaryPageLink } from '@renderer/PageManager'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export function EmbeddedHashtag({ hashtag }: { hashtag: string }) {
|
||||
return (
|
||||
|
|
@ -12,3 +13,10 @@ export function EmbeddedHashtag({ hashtag }: { hashtag: string }) {
|
|||
</SecondaryPageLink>
|
||||
)
|
||||
}
|
||||
|
||||
export const embeddedHashtagRenderer: TEmbeddedRenderer = {
|
||||
regex: /#([\p{L}\p{N}\p{M}]+)/gu,
|
||||
render: (hashtag: string, index: number) => {
|
||||
return <EmbeddedHashtag key={`hashtag-${index}-${hashtag}`} hashtag={hashtag} />
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,29 @@
|
|||
import Username from '../Username'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export function EmbeddedMention({ userId }: { userId: string }) {
|
||||
return <Username userId={userId} showAt className="text-highlight font-normal inline-block" />
|
||||
}
|
||||
|
||||
export const embeddedNostrNpubRenderer: TEmbeddedRenderer = {
|
||||
regex: /(nostr:npub1[a-z0-9]{58})/g,
|
||||
render: (id: string, index: number) => {
|
||||
const npub1 = id.split(':')[1]
|
||||
return <EmbeddedMention key={`embedded-nostr-npub-${index}-${npub1}`} userId={npub1} />
|
||||
}
|
||||
}
|
||||
|
||||
export const embeddedNostrProfileRenderer: TEmbeddedRenderer = {
|
||||
regex: /(nostr:nprofile1[a-z0-9]+)/g,
|
||||
render: (id: string, index: number) => {
|
||||
const nprofile = id.split(':')[1]
|
||||
return <EmbeddedMention key={`embedded-nostr-profile-${index}-${nprofile}`} userId={nprofile} />
|
||||
}
|
||||
}
|
||||
|
||||
export const embeddedNpubRenderer: TEmbeddedRenderer = {
|
||||
regex: /(npub1[a-z0-9]{58})/g,
|
||||
render: (npub1: string, index: number) => {
|
||||
return <EmbeddedMention key={`embedded-npub-${index}-${npub1}`} userId={npub1} />
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export function EmbeddedNormalUrl({ url }: { url: string }) {
|
||||
return (
|
||||
<a
|
||||
|
|
@ -11,3 +13,10 @@ export function EmbeddedNormalUrl({ url }: { url: string }) {
|
|||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
export const embeddedNormalUrlRenderer: TEmbeddedRenderer = {
|
||||
regex: /(https?:\/\/[^\s]+)/g,
|
||||
render: (url: string, index: number) => {
|
||||
return <EmbeddedNormalUrl key={`normal-url-${index}-${url}`} url={url} />
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { useRelaySettings } from '@renderer/providers/RelaySettingsProvider'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export function EmbeddedWebsocketUrl({ url }: { url: string }) {
|
||||
const { setTemporaryRelayUrls } = useRelaySettings()
|
||||
return (
|
||||
<span
|
||||
className="cursor-pointer px-1 rounded-md text-highlight border border-highlight/60 hover:border-highlight hover:bg-muted/60"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setTemporaryRelayUrls([url])
|
||||
}}
|
||||
>
|
||||
{url}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export const embeddedWebsocketUrlRenderer: TEmbeddedRenderer = {
|
||||
regex: /(wss?:\/\/[^\s]+)/g,
|
||||
render: (url: string, index: number) => {
|
||||
return <EmbeddedWebsocketUrl key={`websocket-url-${index}-${url}`} url={url} />
|
||||
}
|
||||
}
|
||||
|
|
@ -2,3 +2,17 @@ export * from './EmbeddedHashtag'
|
|||
export * from './EmbeddedMention'
|
||||
export * from './EmbeddedNormalUrl'
|
||||
export * from './EmbeddedNote'
|
||||
export * from './EmbeddedWebsocketUrl'
|
||||
|
||||
import reactStringReplace from 'react-string-replace'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export function embedded(content: string, renderers: TEmbeddedRenderer[]) {
|
||||
let nodes: React.ReactNode[] = [content]
|
||||
|
||||
renderers.forEach((renderer) => {
|
||||
nodes = reactStringReplace(nodes, renderer.regex, renderer.render)
|
||||
})
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
import { useMemo } from 'react'
|
||||
import {
|
||||
embedded,
|
||||
embeddedHashtagRenderer,
|
||||
embeddedNormalUrlRenderer,
|
||||
embeddedNostrNpubRenderer
|
||||
} from '@renderer/embedded'
|
||||
import { embeddedNpubRenderer } from '@renderer/embedded/EmbeddedNpub'
|
||||
import { useMemo } from 'react'
|
||||
embeddedNostrNpubRenderer,
|
||||
embeddedNpubRenderer,
|
||||
embeddedWebsocketUrlRenderer
|
||||
} from '../Embedded'
|
||||
|
||||
export default function ProfileAbout({ about, className }: { about?: string; className?: string }) {
|
||||
const nodes = useMemo(() => {
|
||||
return about
|
||||
? embedded(about, [
|
||||
embeddedWebsocketUrlRenderer,
|
||||
embeddedNormalUrlRenderer,
|
||||
embeddedHashtagRenderer,
|
||||
embeddedNostrNpubRenderer,
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
import { EmbeddedHashtag } from '../components/Embedded'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export const embeddedHashtagRenderer: TEmbeddedRenderer = {
|
||||
regex: /#([\p{L}\p{N}\p{M}]+)/gu,
|
||||
render: (hashtag: string, index: number) => {
|
||||
return <EmbeddedHashtag key={`hashtag-${index}-${hashtag}`} hashtag={hashtag} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import { EmbeddedNormalUrl } from '../components/Embedded'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export const embeddedNormalUrlRenderer: TEmbeddedRenderer = {
|
||||
regex: /(https?:\/\/[^\s]+|wss?:\/\/[^\s]+)/g,
|
||||
render: (url: string, index: number) => {
|
||||
return <EmbeddedNormalUrl key={`normal-url-${index}-${url}`} url={url} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { EmbeddedMention } from '../components/Embedded'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export const embeddedNostrNpubRenderer: TEmbeddedRenderer = {
|
||||
regex: /(nostr:npub1[a-z0-9]{58})/g,
|
||||
render: (id: string, index: number) => {
|
||||
const npub1 = id.split(':')[1]
|
||||
return <EmbeddedMention key={`embedded-nostr-npub-${index}-${npub1}`} userId={npub1} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { EmbeddedMention } from '../components/Embedded'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export const embeddedNostrProfileRenderer: TEmbeddedRenderer = {
|
||||
regex: /(nostr:nprofile1[a-z0-9]+)/g,
|
||||
render: (id: string, index: number) => {
|
||||
const nprofile = id.split(':')[1]
|
||||
return <EmbeddedMention key={`embedded-nostr-profile-${index}-${nprofile}`} userId={nprofile} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import { EmbeddedMention } from '../components/Embedded'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export const embeddedNpubRenderer: TEmbeddedRenderer = {
|
||||
regex: /(npub1[a-z0-9]{58})/g,
|
||||
render: (npub1: string, index: number) => {
|
||||
return <EmbeddedMention key={`embedded-npub-${index}-${npub1}`} userId={npub1} />
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import reactStringReplace from 'react-string-replace'
|
||||
import { TEmbeddedRenderer } from './types'
|
||||
|
||||
export * from './EmbeddedHashtag'
|
||||
export * from './EmbeddedNormalUrl'
|
||||
export * from './EmbeddedNostrNpub'
|
||||
export * from './EmbeddedNostrProfile'
|
||||
|
||||
export function embedded(content: string, renderers: TEmbeddedRenderer[]) {
|
||||
let nodes: React.ReactNode[] = [content]
|
||||
|
||||
renderers.forEach((renderer) => {
|
||||
nodes = reactStringReplace(nodes, renderer.regex, renderer.render)
|
||||
})
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@ i18n
|
|||
})
|
||||
|
||||
i18n.services.formatter?.add('date', (value, lng) => {
|
||||
console.log('lng', lng)
|
||||
if (lng?.startsWith('zh')) {
|
||||
return dayjs(value).format('YYYY-MM-DD')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { TRelayGroup } from '@common/types'
|
||||
import { isWebsocketUrl, normalizeUrl } from '@renderer/lib/url'
|
||||
import storage from '@renderer/services/storage.service'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { createContext, Dispatch, useContext, useEffect, useState } from 'react'
|
||||
|
||||
type TRelaySettingsContext = {
|
||||
relayGroups: TRelayGroup[]
|
||||
|
|
@ -12,6 +12,7 @@ type TRelaySettingsContext = {
|
|||
deleteRelayGroup: (groupName: string) => void
|
||||
addRelayGroup: (groupName: string, relayUrls?: string[]) => string | null
|
||||
updateRelayGroupRelayUrls: (groupName: string, relayUrls: string[]) => void
|
||||
setTemporaryRelayUrls: Dispatch<string[]>
|
||||
}
|
||||
|
||||
const RelaySettingsContext = createContext<TRelaySettingsContext | undefined>(undefined)
|
||||
|
|
@ -150,7 +151,8 @@ export function RelaySettingsProvider({ children }: { children: React.ReactNode
|
|||
renameRelayGroup,
|
||||
deleteRelayGroup,
|
||||
addRelayGroup,
|
||||
updateRelayGroupRelayUrls
|
||||
updateRelayGroupRelayUrls,
|
||||
setTemporaryRelayUrls
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue