Skip to content

Commit

Permalink
Merge pull request 'feat: highlight search results' (#625) from ferna…
Browse files Browse the repository at this point in the history
…ndoporazzi/snort:highlight-searched-word into main

Reviewed-on: https://git.v0l.io/Kieran/snort/pulls/625
  • Loading branch information
Kieran committed Sep 29, 2023
2 parents 60326ea + a082464 commit 1d1e888
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 3 deletions.
3 changes: 3 additions & 0 deletions packages/app/src/Element/Event/Note.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface NoteProps {
ignoreModeration?: boolean;
onClick?: (e: TaggedNostrEvent) => void;
depth?: number;
searchedValue?: string;
options?: {
showHeader?: boolean;
showContextMenu?: boolean;
Expand Down Expand Up @@ -206,6 +207,7 @@ export function NoteInner(props: NoteProps) {
<Text
id={ev.id}
content={ev.content}
highlighText={props.searchedValue}
tags={ev.tags}
creator={ev.pubkey}
depth={props.depth}
Expand All @@ -222,6 +224,7 @@ export function NoteInner(props: NoteProps) {
return (
<Text
id={ev.id}
highlighText={props.searchedValue}
content={body}
tags={ev.tags}
creator={ev.pubkey}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/Element/Feed/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const Timeline = (props: TimelineProps) => {
</>
)}
{mainFeed.map(e => (
<Note key={e.id} data={e} related={relatedFeed(e.id)} ignoreModeration={props.ignoreModeration} depth={0} />
<Note key={e.id} searchedValue={props.subject.discriminator} data={e} related={relatedFeed(e.id)} ignoreModeration={props.ignoreModeration} depth={0} />
))}
{(props.loadMore === undefined || props.loadMore === true) && (
<div className="flex f-center">
Expand Down
9 changes: 9 additions & 0 deletions packages/app/src/Element/HighlightedText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const HighlightedText = ({ content }: { content: string }) => {
return (
<strong className="highlighted-text">
{content}
</strong>
);
};

export default HighlightedText;
36 changes: 35 additions & 1 deletion packages/app/src/Element/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CashuNuts from "Element/Embed/CashuNuts";
import RevealMedia from "./Event/RevealMedia";
import { ProxyImg } from "./ProxyImg";
import { SpotlightMediaModal } from "./Deck/SpotlightMedia";
import HighlightedText from "./HighlightedText";
import { useTextTransformer } from "Hooks/useTextTransformCache";

export interface TextProps {
Expand All @@ -22,6 +23,7 @@ export interface TextProps {
depth?: number;
truncate?: number;
className?: string;
highlighText?: string;
onClick?: (e: React.MouseEvent) => void;
}

Expand All @@ -36,6 +38,7 @@ export default function Text({
disableLinkPreview,
truncate,
className,
highlighText,
onClick,
}: TextProps) {
const [showSpotlight, setShowSpotlight] = useState(false);
Expand All @@ -45,6 +48,35 @@ export default function Text({

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 => {
if (typeof f === "string") {
return f;
}

return <HighlightedText content={f.content} />;
})}
</>
);
}

const renderContent = () => {
let lenCtr = 0;
function renderChunk(a: ParsedFragment) {
Expand Down Expand Up @@ -96,7 +128,9 @@ export default function Text({
case "custom_emoji":
return <ProxyImg src={a.content} size={15} className="custom-emoji" />;
default:
return <div className="text-frag">{a.content}</div>;
return <div className="text-frag">
{highlighText ? renderContentWithHighlightedText(a.content, highlighText) : a.content}
</div>;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/Pages/DonatePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const Contributors = [
bech32ToHex("npub179rec9sw2a5ngkr2wsjpjhwp2ksygjxn6uw5py9daj2ezhw3aw5swv3s6q"), // h3y6e - JA + other stuff
bech32ToHex("npub17q5n2z8naw0xl6vu9lvt560lg33pdpe29k0k09umlfxm3vc4tqrq466f2y"), // w3irdrobot
bech32ToHex("npub1ltx67888tz7lqnxlrg06x234vjnq349tcfyp52r0lstclp548mcqnuz40t"), // Vivek
bech32ToHex("npub1wh30wunfpkezx5s7edqu9g0s0raeetf5dgthzm0zw7sk8wqygmjqqfljgh"), // Fernando Porazzi
];

const Translators = [
Expand Down
2 changes: 1 addition & 1 deletion packages/system/src/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { validateNostrLink } from "./nostr-link";
import { splitByUrl } from "./utils";

export interface ParsedFragment {
type: "text" | "link" | "mention" | "invoice" | "media" | "cashu" | "hashtag" | "custom_emoji";
type: "text" | "link" | "mention" | "invoice" | "media" | "cashu" | "hashtag" | "custom_emoji" | "highlighted_text";
content: string;
mimeType?: string;
}
Expand Down

0 comments on commit 1d1e888

Please sign in to comment.