mirror of
https://git.v0l.io/Kieran/dtan.git
synced 2025-01-18 04:41:32 +00:00
fix: Used Text component and snort transform instead of custom code
This commit is contained in:
parent
e973f31111
commit
2c751a813e
@ -1,73 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
interface RichTextContentProps {
|
||||
text: string;
|
||||
}
|
||||
|
||||
// Helper function to check if a string is an image URL
|
||||
const isImageUrl = (string: string): boolean => /\.(jpeg|jpg|gif|png)$/.test(string);
|
||||
|
||||
// Helper function to check if a string is a web URL
|
||||
const isWebUrl = (string: string): boolean => {
|
||||
const urlPattern = new RegExp('^(https?:\\/\\/)' + // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
||||
return !!urlPattern.test(string);
|
||||
};
|
||||
|
||||
// Function to split the text into segments
|
||||
const getSegments = (text: string): { type: 'text' | 'image' | 'link', content: string }[] => {
|
||||
const words = text.match(/(\S+|\s+)/g) || [];
|
||||
const segments: { type: 'text' | 'image' | 'link', content: string }[] = [];
|
||||
let currentTextSegment = '';
|
||||
|
||||
words.forEach(word => {
|
||||
const trimmedWord = word.trim();
|
||||
if (isImageUrl(trimmedWord)) {
|
||||
if (currentTextSegment) {
|
||||
segments.push({ type: 'text', content: currentTextSegment });
|
||||
currentTextSegment = '';
|
||||
}
|
||||
segments.push({ type: 'image', content: trimmedWord });
|
||||
} else if (isWebUrl(trimmedWord)) {
|
||||
if (currentTextSegment) {
|
||||
segments.push({ type: 'text', content: currentTextSegment });
|
||||
currentTextSegment = '';
|
||||
}
|
||||
segments.push({ type: 'link', content: trimmedWord });
|
||||
} else {
|
||||
currentTextSegment += word;
|
||||
}
|
||||
});
|
||||
|
||||
if (currentTextSegment) {
|
||||
segments.push({ type: 'text', content: currentTextSegment });
|
||||
}
|
||||
|
||||
return segments;
|
||||
};
|
||||
|
||||
const RichTextContent: React.FC<RichTextContentProps> = ({ text }) => {
|
||||
const segments = getSegments(text);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{segments.map((segment, index) => {
|
||||
switch(segment.type) {
|
||||
case 'image':
|
||||
return <img key={index} src={segment.content} style={{maxHeight:'50vh'}} />;
|
||||
case 'link':
|
||||
return <a key={index} href={segment.content} className="text-indigo-300" target="_blank" rel="noopener noreferrer">{segment.content}</a>;
|
||||
default:
|
||||
return <span key={index}>{segment.content}</span>;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RichTextContent;
|
||||
|
@ -6,23 +6,25 @@ import { Link } from "react-router-dom";
|
||||
export function Text({ content, tags }: { content: string; tags: Array<Array<string>> }) {
|
||||
const frags = useMemo(() => transformText(content, tags), [content, tags]);
|
||||
|
||||
function renderFrag(f: ParsedFragment) {
|
||||
function renderFrag(f: ParsedFragment, index: number) {
|
||||
switch (f.type) {
|
||||
case "media":
|
||||
return <img key={index} src={f.content} style={{ maxHeight: "50vh" }} />;
|
||||
case "mention":
|
||||
case "link": {
|
||||
const link = tryParseNostrLink(f.content);
|
||||
if (link) {
|
||||
return <Mention link={link} />;
|
||||
const nostrLink = tryParseNostrLink(f.content);
|
||||
if (nostrLink) {
|
||||
return <Mention key={index} link={nostrLink} />;
|
||||
} else {
|
||||
return (
|
||||
<Link to={f.content} target="_blank">
|
||||
<Link key={index} to={f.content} target="_blank" className="text-indigo-300" rel="noopener noreferrer">
|
||||
{f.content}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return <span>{f.content}</span>;
|
||||
return <span key={index}>{f.content}</span>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ export function TorrentList({ items }: { items: Array<TaggedNostrEvent> }) {
|
||||
return (
|
||||
<table className="torrent-list mb-8">
|
||||
<thead>
|
||||
<tr className="bg-neutral-800 h-8">
|
||||
<tr className="h-8">
|
||||
<th className="rounded-tl-lg">Category</th>
|
||||
<th>Name</th>
|
||||
<th>Uploaded</th>
|
||||
|
@ -9,7 +9,7 @@ import { useLogin } from "../login";
|
||||
import { Button } from "../element/button";
|
||||
import { Comments } from "../element/comments";
|
||||
import { useMemo } from "react";
|
||||
import RichTextContent from "../element/rich-text-content";
|
||||
import { Text } from "../element/text";
|
||||
|
||||
export function TorrentPage() {
|
||||
const location = useLocation();
|
||||
@ -62,8 +62,8 @@ export function TorrentDetail({ item }: { item: TaggedNostrEvent }) {
|
||||
<div className="flex items-center gap-2">
|
||||
Tags:{" "}
|
||||
<div className="flex gap-2">
|
||||
{tags.map((a) => (
|
||||
<div className="rounded-2xl py-1 px-4 bg-indigo-800 hover:bg-indigo-700">
|
||||
{tags.map((a, i) => (
|
||||
<div key={i} className="rounded-2xl py-1 px-4 bg-indigo-800 hover:bg-indigo-700">
|
||||
<Link to={`/search/?tags=${a}`}>#{a}</Link>
|
||||
</div>
|
||||
))}
|
||||
@ -89,7 +89,7 @@ export function TorrentDetail({ item }: { item: TaggedNostrEvent }) {
|
||||
<>
|
||||
<h3 className="mt-2">Description</h3>
|
||||
<pre className="font-mono text-sm bg-neutral-900 p-4 rounded-lg overflow-y-auto">
|
||||
<RichTextContent text={item.content}></RichTextContent>
|
||||
<Text content={item.content} tags={item.tags}></Text>
|
||||
</pre>
|
||||
</>
|
||||
)}
|
||||
@ -97,19 +97,23 @@ export function TorrentDetail({ item }: { item: TaggedNostrEvent }) {
|
||||
<div className="file-list flex flex-col gap-1 bg-neutral-900 p-4 rounded-lg">
|
||||
<table className="w-max">
|
||||
<thead>
|
||||
<th>
|
||||
<b>Filename</b>
|
||||
</th>
|
||||
<th>
|
||||
<b>Size</b>
|
||||
</th>
|
||||
</thead>
|
||||
{sortedFiles.map((a) => (
|
||||
<tr>
|
||||
<th>
|
||||
<b>Filename</b>
|
||||
</th>
|
||||
<th>
|
||||
<b>Size</b>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sortedFiles.map((a, i) => (
|
||||
<tr key={i}>
|
||||
<td className="pr-4">{a[1]}</td>
|
||||
<td className="text-neutral-500 font-semibold text-right text-sm">{FormatBytes(Number(a[2]))}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3 className="mt-2">Comments</h3>
|
||||
|
Loading…
Reference in New Issue
Block a user