diff --git a/packages/app/src/Components/Spotlight/SpotlightMedia.tsx b/packages/app/src/Components/Spotlight/SpotlightMedia.tsx index af1a3d8c..7f99f0ac 100644 --- a/packages/app/src/Components/Spotlight/SpotlightMedia.tsx +++ b/packages/app/src/Components/Spotlight/SpotlightMedia.tsx @@ -8,7 +8,7 @@ import useImgProxy from "@/Hooks/useImgProxy"; interface SpotlightMediaProps { media: Array; idx: number; - className: string; + className?: string; onClose: () => void; onNext?: () => void; onPrev?: () => void; diff --git a/packages/app/src/Components/Text/Text.tsx b/packages/app/src/Components/Text/Text.tsx index 681b2fae..a8f22acb 100644 --- a/packages/app/src/Components/Text/Text.tsx +++ b/packages/app/src/Components/Text/Text.tsx @@ -1,6 +1,6 @@ import "./Text.css"; -import { HexKey, ParsedFragment, parseIMeta } from "@snort/system"; +import { HexKey, IMeta, ParsedFragment } from "@snort/system"; import classNames from "classnames"; import { ReactNode, useState } from "react"; @@ -100,9 +100,7 @@ export default function Text({ const [imageIdx, setImageIdx] = useState(0); const elements = useTextTransformer(id, content, tags); - const images = elements.filter(a => a.type === "media" && a.mimeType?.startsWith("image")).map(a => a.content); - const iMeta = parseIMeta(tags); function renderContentWithHighlightedText(content: string, textToHighlight: string) { const textToHighlightArray = textToHighlight.trim().toLowerCase().split(" "); @@ -139,8 +137,8 @@ export default function Text({ ); - const RevealMediaInstance = ({ content }: { content: string }) => { - const imeta = iMeta?.[content]; + const RevealMediaInstance = ({ content, data }: { content: string, data?: object }) => { + const imeta = data as IMeta; return ( ); + chunks.push(); } else { // We build a grid layout to render the grouped images const imagesWithGridConfig = galleryImages.map((gi, index) => { @@ -211,6 +209,7 @@ export default function Text({ return { content: gi.content, + data: gi.data, gridColumn: config ? config[index][0] : 1, gridRow: config ? config[index][1] : 1, height, @@ -227,7 +226,7 @@ export default function Text({ gridColumn: `span ${img.gridColumn}`, gridRow: `span ${img.gridRow}`, }}> - + ))} diff --git a/packages/system/src/index.ts b/packages/system/src/index.ts index 530842cd..158b6e10 100644 --- a/packages/system/src/index.ts +++ b/packages/system/src/index.ts @@ -32,7 +32,6 @@ export * from "./pow-util"; export * from "./query-optimizer"; export * from "./encrypted"; export * from "./outbox-model"; -export { parseIMeta } from "./utils"; export * from "./impl/nip4"; export * from "./impl/nip44"; diff --git a/packages/system/src/text.ts b/packages/system/src/text.ts index 249d0380..ac3b68fb 100644 --- a/packages/system/src/text.ts +++ b/packages/system/src/text.ts @@ -11,6 +11,7 @@ import { } from "./const"; import { NostrLink, validateNostrLink } from "./nostr-link"; import { splitByUrl } from "./utils"; +import { IMeta } from "./nostr"; export interface ParsedFragment { type: @@ -27,6 +28,7 @@ export interface ParsedFragment { content: string; mimeType?: string; language?: string; + data?: object; } export type Fragment = string | ParsedFragment; @@ -81,10 +83,12 @@ function extractLinks(fragments: Fragment[]) { return "unknown"; } })(); + const data = parseInlineMetaHack(url); return { type: "media", - content: a, + content: data ? `${url.protocol}//${url.host}${url.pathname}${url.search}` : a, mimeType: `${mediaType}/${extension[1]}`, + data, } as ParsedFragment; } else { return { @@ -249,6 +253,57 @@ function extractMarkdownCode(fragments: Fragment[]): (string | ParsedFragment)[] .flat(); } +export function parseIMeta(tags: Array>) { + let ret: Record | undefined; + const imetaTags = tags.filter(a => a[0] === "imeta"); + for (const imetaTag of imetaTags) { + ret ??= {}; + let imeta: IMeta = {}; + let url = ""; + for (const t of imetaTag.slice(1)) { + const [k, v] = t.split(" "); + if (k === "url") { + url = v; + } + if (k === "dim") { + const [w, h] = v.split("x"); + imeta.height = Number(h); + imeta.width = Number(w); + } + if (k === "blurhash") { + imeta.blurHash = v; + } + if (k === "x") { + imeta.sha256 = v; + } + if (k === "alt") { + imeta.alt = v; + } + } + ret[url] = imeta; + } + return ret; +} + +export function parseInlineMetaHack(u: URL) { + if (u.hash) { + const params = new URLSearchParams(u.hash.substring(1)); + + let imeta: IMeta = {}; + const dim = params.get("dim"); + if (dim) { + const [w, h] = dim.split("x"); + imeta.height = Number(h); + imeta.width = Number(w); + } + imeta.blurHash = params.get("blurhash") ?? undefined; + imeta.sha256 = params.get("x") ?? undefined; + imeta.alt = params.get("alt") ?? undefined; + + return imeta; + } +} + export function transformText(body: string, tags: Array>) { let fragments = extractLinks([body]); fragments = extractMentions(fragments); @@ -258,7 +313,7 @@ export function transformText(body: string, tags: Array>) { fragments = extractCashuTokens(fragments); fragments = extractCustomEmoji(fragments, tags); fragments = extractMarkdownCode(fragments); - fragments = removeUndefined( + const frags = removeUndefined( fragments.map(a => { if (typeof a === "string") { if (a.length > 0) { @@ -269,5 +324,17 @@ export function transformText(body: string, tags: Array>) { } }), ); - return fragments as Array; + + const imeta = parseIMeta(tags); + if (imeta) { + for (const f of frags) { + if (f.type === "media") { + const ix = imeta[f.content]; + if (ix) { + f.data = ix; + } + } + } + } + return frags; } diff --git a/packages/system/src/utils.ts b/packages/system/src/utils.ts index ac7f7d8d..51d393e9 100644 --- a/packages/system/src/utils.ts +++ b/packages/system/src/utils.ts @@ -51,38 +51,6 @@ export function splitByUrl(str: string) { return str.split(urlRegex); } -export function parseIMeta(tags: Array>) { - let ret: Record | undefined; - const imetaTags = tags.filter(a => a[0] === "imeta"); - for (const imetaTag of imetaTags) { - ret ??= {}; - let imeta: IMeta = {}; - let url = ""; - for (const t of imetaTag.slice(1)) { - const [k, v] = t.split(" "); - if (k === "url") { - url = v; - } - if (k === "dim") { - const [w, h] = v.split("x"); - imeta.height = Number(h); - imeta.width = Number(w); - } - if (k === "blurhash") { - imeta.blurHash = v; - } - if (k === "x") { - imeta.sha256 = v; - } - if (k === "alt") { - imeta.alt = v; - } - } - ret[url] = imeta; - } - return ret; -} - export function getHex64(json: string, field: string): string { let len = field.length + 3; let idx = json.indexOf(`"${field}":`) + len;