From db56a801d06af98399616badd5d84a472a01fa37 Mon Sep 17 00:00:00 2001 From: verbiricha Date: Mon, 31 Jul 2023 18:24:39 +0200 Subject: [PATCH] refactor: use regular text for chat --- src/element/chat-message.tsx | 9 +- src/element/live-chat.css | 9 -- src/element/markdown.tsx | 195 +---------------------------------- src/element/text.tsx | 175 ++++++++++++++++++++++++++----- 4 files changed, 156 insertions(+), 232 deletions(-) diff --git a/src/element/chat-message.tsx b/src/element/chat-message.tsx index 365e7ec..3ce52db 100644 --- a/src/element/chat-message.tsx +++ b/src/element/chat-message.tsx @@ -14,7 +14,7 @@ import { EmojiPicker } from "./emoji-picker"; import { Icon } from "./icon"; import { Emoji } from "./emoji"; import { Profile } from "./profile"; -import { Markdown } from "./markdown"; +import { Text } from "element/text"; import { SendZapsDialog } from "./send-zap"; import { findTag } from "../utils"; import type { EmojiPack } from "../hooks/emoji"; @@ -152,12 +152,7 @@ export function ChatMessage({ pubkey={ev.pubkey} profile={profile} /> - + {(hasReactions || hasZaps) && (
{hasZaps && ( diff --git a/src/element/live-chat.css b/src/element/live-chat.css index c789a60..02924fc 100644 --- a/src/element/live-chat.css +++ b/src/element/live-chat.css @@ -357,12 +357,3 @@ height: 18px; border-radius: unset; } - -.message .markdown { - font-size: 14px; - line-height: normal; -} - -.message .markdown .emoji { - width: unset; -} diff --git a/src/element/markdown.tsx b/src/element/markdown.tsx index 3511b33..c867686 100644 --- a/src/element/markdown.tsx +++ b/src/element/markdown.tsx @@ -1,204 +1,20 @@ import "./markdown.css"; import { createElement } from "react"; -import { parseNostrLink } from "@snort/system"; import { useMemo } from "react"; import ReactMarkdown from "react-markdown"; -import { Address } from "element/Address"; -import { Event } from "element/Event"; -import { Mention } from "element/mention"; -import { Emoji } from "element/emoji"; import { HyperText } from "element/hypertext"; - -const MentionRegex = /(#\[\d+\])/gi; -const NostrPrefixRegex = /^nostr:/; -const EmojiRegex = /:([\w-]+):/g; - -function extractEmoji(fragments: Fragment[], tags: string[][]) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(EmojiRegex).map((i) => { - const t = tags.find((a) => a[0] === "emoji" && a[1] === i); - if (t) { - return ; - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function extractMentions(fragments, tags) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(MentionRegex).map((match) => { - const matchTag = match.match(/#\[(\d+)\]/); - if (matchTag && matchTag.length === 2) { - const idx = parseInt(matchTag[1]); - const ref = tags?.find((a, i) => i === idx); - if (ref) { - switch (ref[0]) { - case "p": { - return ; - } - case "a": { - return
; - } - default: - // todo: e and t mentions - return ref[1]; - } - } - return null; - } else { - return match; - } - }); - } - return f; - }) - .flat(); -} - -function extractNprofiles(fragments) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/(nostr:nprofile1[a-z0-9]+)/g).map((i) => { - if (i.startsWith("nostr:nprofile1")) { - try { - const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); - return ; - } catch (error) { - return i; - } - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function extractNpubs(fragments) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/(nostr:npub1[a-z0-9]+)/g).map((i) => { - if (i.startsWith("nostr:npub1")) { - try { - const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); - return ; - } catch (error) { - return i; - } - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function extractNevents(fragments) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/(nostr:nevent1[a-z0-9]+)/g).map((i) => { - if (i.startsWith("nostr:nevent1")) { - try { - const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); - return ; - } catch (error) { - return i; - } - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function extractNaddrs(fragments) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/(nostr:naddr1[a-z0-9]+)/g).map((i) => { - if (i.startsWith("nostr:naddr1")) { - try { - const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); - return
; - } catch (error) { - console.error(error); - return i; - } - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function extractNoteIds(fragments) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/(nostr:note1[a-z0-9]+)/g).map((i) => { - if (i.startsWith("nostr:note1")) { - try { - const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); - return ; - } catch (error) { - return i; - } - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} - -function transformText(ps, tags) { - let fragments = extractMentions(ps, tags); - fragments = extractNprofiles(fragments); - fragments = extractNevents(fragments); - fragments = extractNaddrs(fragments); - fragments = extractNoteIds(fragments); - fragments = extractNpubs(fragments); - fragments = extractEmoji(fragments, tags); - - return fragments; -} +import { transformText } from "element/text"; interface MarkdownProps { content: string; tags?: string[]; - enableParagraphs?: booleam; } export function Markdown({ content, tags = [], - enableParagraphs = true, element = "div", }: MarkdownProps) { const components = useMemo(() => { @@ -208,17 +24,12 @@ export function Markdown({ }, td: ({ children }) => children && {transformText(children, tags)}, - p: ({ children }) => - enableParagraphs ? ( -

{transformText(children, tags)}

- ) : ( - transformText(children, tags) - ), + p: ({ children }) =>

{transformText(children, tags)}

, a: (props) => { return {props.children}; }, }; - }, [tags, enableParagraphs]); + }, [tags]); return createElement( element, { className: "markdown" }, diff --git a/src/element/text.tsx b/src/element/text.tsx index 56070f3..e419156 100644 --- a/src/element/text.tsx +++ b/src/element/text.tsx @@ -1,32 +1,18 @@ import { useMemo, type ReactNode } from "react"; -import { validateNostrLink } from "@snort/system"; + +import { parseNostrLink, validateNostrLink } from "@snort/system"; + +import { Address } from "element/Address"; +import { Event } from "element/Event"; +import { Mention } from "element/mention"; +import { Emoji } from "element/emoji"; +import { HyperText } from "element/hypertext"; import { splitByUrl } from "utils"; -import { Emoji } from "./emoji"; -import { HyperText } from "./hypertext"; type Fragment = string | ReactNode; -function transformText(fragments: Fragment[], tags: string[][]) { - return extractLinks(extractEmoji(fragments, tags)); -} - -function extractEmoji(fragments: Fragment[], tags: string[][]) { - return fragments - .map((f) => { - if (typeof f === "string") { - return f.split(/:([\w-]+):/g).map((i) => { - const t = tags.find((a) => a[0] === "emoji" && a[1] === i); - if (t) { - return ; - } else { - return i; - } - }); - } - return f; - }) - .flat(); -} +const NostrPrefixRegex = /^nostr:/; +const EmojiRegex = /:([\w-]+):/g; function extractLinks(fragments: Fragment[]) { return fragments @@ -74,6 +60,147 @@ function extractLinks(fragments: Fragment[]) { .flat(); } +function extractEmoji(fragments: Fragment[], tags: string[][]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(EmojiRegex).map((i) => { + const t = tags.find((a) => a[0] === "emoji" && a[1] === i); + if (t) { + return ; + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +function extractNprofiles(fragments: Fragment[]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(/(nostr:nprofile1[a-z0-9]+)/g).map((i) => { + if (i.startsWith("nostr:nprofile1")) { + try { + const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); + return ; + } catch (error) { + return i; + } + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +function extractNpubs(fragments: Fragment[]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(/(nostr:npub1[a-z0-9]+)/g).map((i) => { + if (i.startsWith("nostr:npub1")) { + try { + const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); + return ; + } catch (error) { + return i; + } + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +function extractNevents(fragments: Fragment[]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(/(nostr:nevent1[a-z0-9]+)/g).map((i) => { + if (i.startsWith("nostr:nevent1")) { + try { + const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); + return ; + } catch (error) { + return i; + } + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +function extractNaddrs(fragments: Fragment[]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(/(nostr:naddr1[a-z0-9]+)/g).map((i) => { + if (i.startsWith("nostr:naddr1")) { + try { + const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); + return
; + } catch (error) { + console.error(error); + return i; + } + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +function extractNoteIds(fragments: Fragment[]) { + return fragments + .map((f) => { + if (typeof f === "string") { + return f.split(/(nostr:note1[a-z0-9]+)/g).map((i) => { + if (i.startsWith("nostr:note1")) { + try { + const link = parseNostrLink(i.replace(NostrPrefixRegex, "")); + return ; + } catch (error) { + return i; + } + } else { + return i; + } + }); + } + return f; + }) + .flat(); +} + +export function transformText(ps: Fragment[], tags: Array) { + let fragments = extractEmoji(ps, tags); + fragments = extractNprofiles(fragments); + fragments = extractNevents(fragments); + fragments = extractNaddrs(fragments); + fragments = extractNoteIds(fragments); + fragments = extractNpubs(fragments); + fragments = extractLinks(fragments); + + return fragments; +} + export function Text({ content, tags }: { content: string; tags: string[][] }) { // todo: RTL langugage support const element = useMemo(() => {