From 95dc979b8d26d55735097a42ca6ff6b146cebb00 Mon Sep 17 00:00:00 2001 From: Martti Malmi Date: Thu, 29 Feb 2024 11:14:17 +0200 Subject: [PATCH] fix highlighted text in searched notes --- .../src/Components/Event/EventComponent.tsx | 2 +- .../app/src/Components/Event/Note/Note.tsx | 2 +- .../Components/Event/Note/NoteContextMenu.tsx | 16 ++-- .../src/Components/Event/Note/NoteHeader.tsx | 2 +- .../src/Components/Event/Note/NoteText.tsx | 4 +- .../Components/Event/Note/TranslationInfo.tsx | 2 +- .../app/src/Components/Event/Note/types.tsx | 4 +- packages/app/src/Components/Feed/Timeline.tsx | 1 + .../src/Components/Feed/TimelineFragment.tsx | 2 + .../src/Components/Feed/TimelineRenderer.tsx | 2 + .../app/src/Components/HighlightedText.tsx | 5 - .../src/Components/Text/HighlightedText.tsx | 23 +++++ packages/app/src/Components/Text/Text.tsx | 96 ++----------------- packages/app/src/Components/Text/const.ts | 51 ++++++++++ 14 files changed, 104 insertions(+), 108 deletions(-) delete mode 100644 packages/app/src/Components/HighlightedText.tsx create mode 100644 packages/app/src/Components/Text/HighlightedText.tsx create mode 100644 packages/app/src/Components/Text/const.ts diff --git a/packages/app/src/Components/Event/EventComponent.tsx b/packages/app/src/Components/Event/EventComponent.tsx index ba1159b0..2e68c66b 100644 --- a/packages/app/src/Components/Event/EventComponent.tsx +++ b/packages/app/src/Components/Event/EventComponent.tsx @@ -41,7 +41,7 @@ export interface NoteProps { ignoreModeration?: boolean; onClick?: (e: TaggedNostrEvent) => void; depth?: number; - searchedValue?: string; + highlightText?: string; threadChains?: Map>; context?: ReactNode; options?: NotePropsOptions; diff --git a/packages/app/src/Components/Event/Note/Note.tsx b/packages/app/src/Components/Event/Note/Note.tsx index b30a33f8..e5f263ef 100644 --- a/packages/app/src/Components/Event/Note/Note.tsx +++ b/packages/app/src/Components/Event/Note/Note.tsx @@ -11,7 +11,7 @@ import NoteHeader from "@/Components/Event/Note/NoteHeader"; import NoteQuote from "@/Components/Event/Note/NoteQuote"; import { NoteText } from "@/Components/Event/Note/NoteText"; import { TranslationInfo } from "@/Components/Event/Note/TranslationInfo"; -import {NoteTranslation} from "@/Components/Event/Note/types"; +import { NoteTranslation } from "@/Components/Event/Note/types"; import Username from "@/Components/User/Username"; import useModeration from "@/Hooks/useModeration"; import { findTag } from "@/Utils"; diff --git a/packages/app/src/Components/Event/Note/NoteContextMenu.tsx b/packages/app/src/Components/Event/Note/NoteContextMenu.tsx index c672e9a2..50259bae 100644 --- a/packages/app/src/Components/Event/Note/NoteContextMenu.tsx +++ b/packages/app/src/Components/Event/Note/NoteContextMenu.tsx @@ -1,19 +1,19 @@ -import {HexKey, NostrLink, NostrPrefix} from "@snort/system"; -import {Menu, MenuItem} from "@szhsin/react-menu"; -import {useEffect, useState} from "react"; -import {FormattedMessage, useIntl} from "react-intl"; +import { HexKey, NostrLink, NostrPrefix } from "@snort/system"; +import { Menu, MenuItem } from "@szhsin/react-menu"; +import { useEffect, useState } from "react"; +import { FormattedMessage, useIntl } from "react-intl"; -import {NoteContextMenuProps, NoteTranslation} from "@/Components/Event/Note/types"; +import { NoteContextMenuProps, NoteTranslation } from "@/Components/Event/Note/types"; import Icon from "@/Components/Icons/Icon"; import messages from "@/Components/messages"; import SnortApi from "@/External/SnortApi"; import useEventPublisher from "@/Hooks/useEventPublisher"; import useLogin from "@/Hooks/useLogin"; import useModeration from "@/Hooks/useModeration"; -import {setBookmarked, setPinned} from "@/Utils/Login"; -import {getCurrentSubscription, SubscriptionType} from "@/Utils/Subscription"; +import { setBookmarked, setPinned } from "@/Utils/Login"; +import { getCurrentSubscription, SubscriptionType } from "@/Utils/Subscription"; -import {ReBroadcaster} from "../../ReBroadcaster"; +import { ReBroadcaster } from "../../ReBroadcaster"; export function NoteContextMenu({ ev, ...props }: NoteContextMenuProps) { const { formatMessage } = useIntl(); diff --git a/packages/app/src/Components/Event/Note/NoteHeader.tsx b/packages/app/src/Components/Event/Note/NoteHeader.tsx index 8383c183..64442de0 100644 --- a/packages/app/src/Components/Event/Note/NoteHeader.tsx +++ b/packages/app/src/Components/Event/Note/NoteHeader.tsx @@ -7,7 +7,7 @@ import { NoteContextMenu } from "@/Components/Event/Note/NoteContextMenu"; import NoteTime from "@/Components/Event/Note/NoteTime"; import ReactionsModal from "@/Components/Event/Note/ReactionsModal"; import ReplyTag from "@/Components/Event/Note/ReplyTag"; -import {NoteTranslation} from "@/Components/Event/Note/types"; +import { NoteTranslation } from "@/Components/Event/Note/types"; import Icon from "@/Components/Icons/Icon"; import messages from "@/Components/messages"; import ProfileImage from "@/Components/User/ProfileImage"; diff --git a/packages/app/src/Components/Event/Note/NoteText.tsx b/packages/app/src/Components/Event/Note/NoteText.tsx index 13fd1ac8..3827a764 100644 --- a/packages/app/src/Components/Event/Note/NoteText.tsx +++ b/packages/app/src/Components/Event/Note/NoteText.tsx @@ -3,7 +3,7 @@ import { FormattedMessage } from "react-intl"; import { Link } from "react-router-dom"; import { NoteProps } from "@/Components/Event/EventComponent"; -import {NoteTranslation} from "@/Components/Event/Note/types"; +import { NoteTranslation } from "@/Components/Event/Note/types"; import Reveal from "@/Components/Event/Reveal"; import Text from "@/Components/Text/Text"; import useLogin from "@/Hooks/useLogin"; @@ -40,7 +40,7 @@ export const NoteText = memo(function InnerContent( {shouldTruncate && showMore && } ; onTranslated?: (t: NoteTranslation) => void; -} \ No newline at end of file +} diff --git a/packages/app/src/Components/Feed/Timeline.tsx b/packages/app/src/Components/Feed/Timeline.tsx index 3b75acbd..2d377ca3 100644 --- a/packages/app/src/Components/Feed/Timeline.tsx +++ b/packages/app/src/Components/Feed/Timeline.tsx @@ -93,6 +93,7 @@ const Timeline = (props: TimelineProps) => { showLatest={t => onShowLatest(t)} displayAs={displayAs} loadMore={() => feed.loadMore()} + highlightText={props.subject.type === "post_keyword" ? props.subject.items[0] : undefined} /> ); diff --git a/packages/app/src/Components/Feed/TimelineFragment.tsx b/packages/app/src/Components/Feed/TimelineFragment.tsx index 3fd2d917..8b91c5bc 100644 --- a/packages/app/src/Components/Feed/TimelineFragment.tsx +++ b/packages/app/src/Components/Feed/TimelineFragment.tsx @@ -14,6 +14,7 @@ export interface TimelineFragProps { noteRenderer?: (ev: TaggedNostrEvent) => ReactNode; noteOnClick?: (ev: TaggedNostrEvent) => void; noteContext?: (ev: TaggedNostrEvent) => ReactNode; + highlightText?: string; } const options = { @@ -35,6 +36,7 @@ export function TimelineFragment(props: TimelineFragProps) { context={props.noteContext?.(e)} options={options} waitUntilInView={index > 5} + highlightText={props.highlightText} /> ), )} diff --git a/packages/app/src/Components/Feed/TimelineRenderer.tsx b/packages/app/src/Components/Feed/TimelineRenderer.tsx index 8e3a5cfb..f28c5bbd 100644 --- a/packages/app/src/Components/Feed/TimelineRenderer.tsx +++ b/packages/app/src/Components/Feed/TimelineRenderer.tsx @@ -25,6 +25,7 @@ export interface TimelineRendererProps { noteContext?: (ev: TaggedNostrEvent) => ReactNode; displayAs?: DisplayAs; loadMore?: () => void; + highlightText?: string; } // filter frags[0].events that have media @@ -105,6 +106,7 @@ export function TimelineRenderer(props: TimelineRendererProps) { noteRenderer={props.noteRenderer} noteOnClick={props.noteOnClick} noteContext={props.noteContext} + highlightText={props.highlightText} /> )); diff --git a/packages/app/src/Components/HighlightedText.tsx b/packages/app/src/Components/HighlightedText.tsx deleted file mode 100644 index fd301f0e..00000000 --- a/packages/app/src/Components/HighlightedText.tsx +++ /dev/null @@ -1,5 +0,0 @@ -const HighlightedText = ({ content }: { content: string }) => { - return {content}; -}; - -export default HighlightedText; diff --git a/packages/app/src/Components/Text/HighlightedText.tsx b/packages/app/src/Components/Text/HighlightedText.tsx new file mode 100644 index 00000000..0617a4a0 --- /dev/null +++ b/packages/app/src/Components/Text/HighlightedText.tsx @@ -0,0 +1,23 @@ +import React from "react"; + +const HighlightedText = ({ content, textToHighlight }: { content: string; textToHighlight: string }) => { + const textToHighlightArray = textToHighlight.trim().toLowerCase().split(" "); + const re = new RegExp(`(${textToHighlightArray.join("|")})`, "gi"); + const splittedContent = content.split(re); + + const fragments = splittedContent.map((part, index) => { + if (textToHighlightArray.includes(part.toLowerCase())) { + return ( + + {part} + + ); + } else { + return part; + } + }); + + return <>{fragments}; +}; + +export default HighlightedText; diff --git a/packages/app/src/Components/Text/Text.tsx b/packages/app/src/Components/Text/Text.tsx index 24144d3d..313d9f2c 100644 --- a/packages/app/src/Components/Text/Text.tsx +++ b/packages/app/src/Components/Text/Text.tsx @@ -8,12 +8,13 @@ import CashuNuts from "@/Components/Embed/CashuNuts"; import Hashtag from "@/Components/Embed/Hashtag"; import HyperText from "@/Components/Embed/HyperText"; import Invoice from "@/Components/Embed/Invoice"; +import { baseImageWidth, GRID_GAP, gridConfigMap, ROW_HEIGHT } from "@/Components/Text/const"; import { useTextTransformer } from "@/Hooks/useTextTransformCache"; import RevealMedia from "../Event/RevealMedia"; -import HighlightedText from "../HighlightedText"; import { ProxyImg } from "../ProxyImg"; import { SpotlightMediaModal } from "../Spotlight/SpotlightMedia"; +import HighlightedText from "./HighlightedText"; export interface TextProps { id: string; @@ -26,64 +27,10 @@ export interface TextProps { depth?: number; truncate?: number; className?: string; - highlighText?: string; + highlightText?: string; onClick?: (e: React.MouseEvent) => void; } -const baseImageWidth = 910; - -const gridConfigMap = new Map([ - [1, [[4, 3]]], - [ - 2, - [ - [2, 2], - [2, 2], - ], - ], - [ - 3, - [ - [2, 2], - [2, 1], - [2, 1], - ], - ], - [ - 4, - [ - [2, 1], - [2, 1], - [2, 1], - [2, 1], - ], - ], - [ - 5, - [ - [2, 1], - [2, 1], - [2, 1], - [1, 1], - [1, 1], - ], - ], - [ - 6, - [ - [2, 2], - [1, 1], - [1, 1], - [2, 2], - [1, 1], - [1, 1], - ], - ], -]); - -const ROW_HEIGHT = 140; -const GRID_GAP = 2; - export default function Text({ id, content, @@ -95,7 +42,7 @@ export default function Text({ disableLinkPreview, truncate, className, - highlighText, + highlightText, onClick, }: TextProps) { const [showSpotlight, setShowSpotlight] = useState(false); @@ -104,35 +51,6 @@ export default function Text({ const elements = useTextTransformer(id, content, tags); const images = elements.filter(a => a.type === "media" && a.mimeType?.startsWith("image")).map(a => a.content); - function renderContentWithHighlightedText(content: string, textToHighlight: string) { - const textToHighlightArray = textToHighlight.trim().toLowerCase().split(" "); - const re = new RegExp(`(${textToHighlightArray.join("|")})`, "gi"); - const splittedContent = content.split(re); - - const fragments = splittedContent.map(c => { - if (textToHighlightArray.includes(c.toLowerCase())) { - return { - type: "highlighted_text", - content: c, - } as ParsedFragment; - } - - return c; - }); - - return ( - <> - {fragments.map((f, index) => { - if (typeof f === "string") { - return f; - } - - return ; - })} - - ); - } - const DisableMedia = ({ content }: { content: string }) => ( e.stopPropagation()} target="_blank" rel="noreferrer" className="ext"> {content} @@ -284,7 +202,11 @@ export default function Text({ if (element.type === "text") { chunks.push(
- {highlighText ? renderContentWithHighlightedText(element.content, highlighText) : element.content} + {highlightText ? ( + + ) : ( + element.content + )}
, ); } diff --git a/packages/app/src/Components/Text/const.ts b/packages/app/src/Components/Text/const.ts new file mode 100644 index 00000000..6eb85bf0 --- /dev/null +++ b/packages/app/src/Components/Text/const.ts @@ -0,0 +1,51 @@ +export const baseImageWidth = 910; +export const gridConfigMap = new Map([ + [1, [[4, 3]]], + [ + 2, + [ + [2, 2], + [2, 2], + ], + ], + [ + 3, + [ + [2, 2], + [2, 1], + [2, 1], + ], + ], + [ + 4, + [ + [2, 1], + [2, 1], + [2, 1], + [2, 1], + ], + ], + [ + 5, + [ + [2, 1], + [2, 1], + [2, 1], + [1, 1], + [1, 1], + ], + ], + [ + 6, + [ + [2, 2], + [1, 1], + [1, 1], + [2, 2], + [1, 1], + [1, 1], + ], + ], +]); +export const ROW_HEIGHT = 140; +export const GRID_GAP = 2;