diff --git a/components/bookmark-card.tsx b/components/bookmark-card.tsx index be48a7a..e536889 100644 --- a/components/bookmark-card.tsx +++ b/components/bookmark-card.tsx @@ -1,7 +1,7 @@ 'use client' import React, { useRef, useEffect, useState } from 'react' -import { ExternalLink, Download, Play, Pencil, X, Check, ImageOff, Bookmark, Globe } from 'lucide-react' +import { ExternalLink, Download, FileText, Play, Pencil, X, Check, ImageOff, Bookmark, Globe } from 'lucide-react' import type { BookmarkWithMedia, Category } from '@/lib/types' // ── URL helpers ──────────────────────────────────────────────────────────────── @@ -625,6 +625,60 @@ export default function BookmarkCard({ bookmark }: BookmarkCardProps) { document.body.removeChild(a) } + function handleDownloadMarkdown() { + const lines: string[] = [] + + // Header + if (isKnownAuthor) { + lines.push(`# Tweet by @${bookmark.authorHandle}`) + lines.push('') + lines.push(`**Author:** ${bookmark.authorName} (@${bookmark.authorHandle})`) + } else { + lines.push(`# Bookmarked Tweet`) + } + if (dateStr) lines.push(`**Date:** ${dateStr}`) + lines.push(`**URL:** ${tweetUrl}`) + if (categories.length > 0) { + lines.push(`**Categories:** ${categories.map((c) => c.name).join(', ')}`) + } + lines.push('') + lines.push('---') + lines.push('') + + // Full stored text — keep URLs so truncated threads show the continuation link + if (bookmark.text) lines.push(bookmark.text) + + // If text ends with a t.co link the tweet may be part of a longer thread + if (TCO_REGEX.test(bookmark.text)) { + lines.push('') + lines.push(`> *This tweet may be part of a longer thread. [Read on X ↗](${tweetUrl})*`) + } + + // Media + if (bookmark.mediaItems.length > 0) { + lines.push('') + lines.push('---') + lines.push('') + for (const m of bookmark.mediaItems) { + if (m.type === 'photo') { + lines.push(``) + } else { + lines.push(`[${m.type === 'video' ? 'Video' : 'GIF'} — view on X](${tweetUrl})`) + } + } + } + + const blob = new Blob([lines.join('\n')], { type: 'text/markdown' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `tweet-${bookmark.tweetId}.md` + document.body.appendChild(a) + a.click() + document.body.removeChild(a) + URL.revokeObjectURL(url) + } + // Only show download if media is a photo or a real video (not a thumbnail JPEG stored as video) const isDownloadable = firstMedia !== null && (firstMedia.type === 'photo' || isVideoUrl(firstMedia.url)) @@ -662,6 +716,13 @@ export default function BookmarkCard({ bookmark }: BookmarkCardProps) { {/* Actions — visible on hover */}