Browse Source

`feat: add support for viewing WebSocket links

imwald
codytseng 1 year ago
parent
commit
e1d3d97f9a
  1. 16
      src/renderer/src/components/Content/index.tsx
  2. 8
      src/renderer/src/components/Embedded/EmbeddedHashtag.tsx
  3. 24
      src/renderer/src/components/Embedded/EmbeddedMention.tsx
  4. 9
      src/renderer/src/components/Embedded/EmbeddedNormalUrl.tsx
  5. 24
      src/renderer/src/components/Embedded/EmbeddedWebsocketUrl.tsx
  6. 14
      src/renderer/src/components/Embedded/index.tsx
  7. 0
      src/renderer/src/components/Embedded/types.tsx
  8. 10
      src/renderer/src/components/ProfileAbout/index.tsx
  9. 9
      src/renderer/src/embedded/EmbeddedHashtag.tsx
  10. 9
      src/renderer/src/embedded/EmbeddedNormalUrl.tsx
  11. 10
      src/renderer/src/embedded/EmbeddedNostrNpub.tsx
  12. 10
      src/renderer/src/embedded/EmbeddedNostrProfile.tsx
  13. 9
      src/renderer/src/embedded/EmbeddedNpub.tsx
  14. 17
      src/renderer/src/embedded/index.tsx
  15. 1
      src/renderer/src/i18n/index.ts
  16. 6
      src/renderer/src/providers/RelaySettingsProvider.tsx

16
src/renderer/src/components/Content/index.tsx

@ -1,15 +1,16 @@ @@ -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( @@ -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,

8
src/renderer/src/components/Embedded/EmbeddedHashtag.tsx

@ -1,5 +1,6 @@ @@ -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 }) { @@ -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} />
}
}

24
src/renderer/src/components/Embedded/EmbeddedMention.tsx

@ -1,5 +1,29 @@ @@ -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} />
}
}

9
src/renderer/src/components/Embedded/EmbeddedNormalUrl.tsx

@ -1,3 +1,5 @@ @@ -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 }) { @@ -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} />
}
}

24
src/renderer/src/components/Embedded/EmbeddedWebsocketUrl.tsx

@ -0,0 +1,24 @@ @@ -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} />
}
}

14
src/renderer/src/components/Embedded/index.tsx

@ -2,3 +2,17 @@ export * from './EmbeddedHashtag' @@ -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
}

0
src/renderer/src/embedded/types.tsx → src/renderer/src/components/Embedded/types.tsx

10
src/renderer/src/components/ProfileAbout/index.tsx

@ -1,16 +1,18 @@ @@ -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,

9
src/renderer/src/embedded/EmbeddedHashtag.tsx

@ -1,9 +0,0 @@ @@ -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} />
}
}

9
src/renderer/src/embedded/EmbeddedNormalUrl.tsx

@ -1,9 +0,0 @@ @@ -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} />
}
}

10
src/renderer/src/embedded/EmbeddedNostrNpub.tsx

@ -1,10 +0,0 @@ @@ -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} />
}
}

10
src/renderer/src/embedded/EmbeddedNostrProfile.tsx

@ -1,10 +0,0 @@ @@ -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} />
}
}

9
src/renderer/src/embedded/EmbeddedNpub.tsx

@ -1,9 +0,0 @@ @@ -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} />
}
}

17
src/renderer/src/embedded/index.tsx

@ -1,17 +0,0 @@ @@ -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
}

1
src/renderer/src/i18n/index.ts

@ -22,7 +22,6 @@ i18n @@ -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')
}

6
src/renderer/src/providers/RelaySettingsProvider.tsx

@ -1,7 +1,7 @@ @@ -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 = { @@ -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 @@ -150,7 +151,8 @@ export function RelaySettingsProvider({ children }: { children: React.ReactNode
renameRelayGroup,
deleteRelayGroup,
addRelayGroup,
updateRelayGroupRelayUrls
updateRelayGroupRelayUrls,
setTemporaryRelayUrls
}}
>
{children}

Loading…
Cancel
Save