Add IPFS CID display with public gateway links

- Cache detail page shows IPFS section with CID and links to
  ipfs.io, dweb.link, Cloudflare, and Pinata gateways
- Media list cards show purple "IPFS" badge for items with CID
- JSON API response includes ipfs_cid field

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-08 17:56:29 +00:00
parent 591c0aad4c
commit 808e754e7f

View File

@@ -1714,6 +1714,10 @@ async def cache_detail(content_hash: str, request: Request):
elif file_size > 1024:
size_str = f"{file_size/1024:.1f} KB"
# Get IPFS CID from database
cache_item = await database.get_cache_item(content_hash)
ipfs_cid = cache_item.get("ipfs_cid") if cache_item else None
# Build media display HTML
if media_type == "video":
video_src = video_src_for_request(content_hash, request)
@@ -1770,7 +1774,47 @@ async def cache_detail(content_hash: str, request: Request):
</div>
</div>
</div>
'''
# Add IPFS section if we have a CID
if ipfs_cid:
content += f'''
<div class="border-t border-dark-500 pt-6 mt-6">
<h2 class="text-lg font-semibold text-white mb-4">IPFS</h2>
<div class="bg-dark-600 rounded-lg p-4 mb-4">
<div class="text-sm text-gray-400 mb-1">Content Identifier (CID)</div>
<div class="font-mono text-xs text-gray-200 break-all">{ipfs_cid}</div>
</div>
<div class="text-sm text-gray-400 mb-2">Public Gateways:</div>
<div class="flex flex-wrap gap-2">
<a href="https://ipfs.io/ipfs/{ipfs_cid}" target="_blank" rel="noopener"
class="px-3 py-1 bg-purple-600 hover:bg-purple-700 text-white text-sm rounded-lg transition-colors">
ipfs.io
</a>
<a href="https://dweb.link/ipfs/{ipfs_cid}" target="_blank" rel="noopener"
class="px-3 py-1 bg-purple-600 hover:bg-purple-700 text-white text-sm rounded-lg transition-colors">
dweb.link
</a>
<a href="https://cloudflare-ipfs.com/ipfs/{ipfs_cid}" target="_blank" rel="noopener"
class="px-3 py-1 bg-purple-600 hover:bg-purple-700 text-white text-sm rounded-lg transition-colors">
Cloudflare
</a>
<a href="https://gateway.pinata.cloud/ipfs/{ipfs_cid}" target="_blank" rel="noopener"
class="px-3 py-1 bg-purple-600 hover:bg-purple-700 text-white text-sm rounded-lg transition-colors">
Pinata
</a>
</div>
</div>
'''
else:
content += '''
<div class="border-t border-dark-500 pt-6 mt-6">
<h2 class="text-lg font-semibold text-white mb-4">IPFS</h2>
<div class="text-gray-400 text-sm">Not yet uploaded to IPFS</div>
</div>
'''
content += f'''
<!-- Metadata Section -->
<div class="border-t border-dark-500 pt-6 mt-6" id="metadata-section"
hx-get="/cache/{content_hash}/meta-form" hx-trigger="load" hx-swap="innerHTML">
@@ -1783,12 +1827,15 @@ async def cache_detail(content_hash: str, request: Request):
# JSON response - return metadata
meta = await database.load_item_metadata(content_hash, ctx.actor_id if ctx else None)
cache_item = await database.get_cache_item(content_hash)
ipfs_cid = cache_item.get("ipfs_cid") if cache_item else None
file_size = cache_path.stat().st_size
media_type = detect_media_type(cache_path)
return {
"content_hash": content_hash,
"size": file_size,
"media_type": media_type,
"ipfs_cid": ipfs_cid,
"meta": meta
}
@@ -3510,6 +3557,11 @@ async def ui_media_list(
cache_path = get_cache_path(content_hash)
media_type = detect_media_type(cache_path) if cache_path else "unknown"
# Check IPFS status
cache_item = await database.get_cache_item(content_hash)
ipfs_cid = cache_item.get("ipfs_cid") if cache_item else None
ipfs_badge = '<span class="px-2 py-1 bg-purple-600 text-white text-xs font-medium rounded-full" title="On IPFS">IPFS</span>' if ipfs_cid else ''
# Format size
size = item["size"]
if size > 1024*1024:
@@ -3523,7 +3575,10 @@ async def ui_media_list(
<a href="/ui/cache/{content_hash}" class="block">
<div class="bg-dark-700 rounded-lg p-4 hover:bg-dark-600 transition-colors">
<div class="flex items-center justify-between gap-2 mb-3">
<span class="px-2 py-1 bg-blue-600 text-white text-xs font-medium rounded-full">{media_type}</span>
<div class="flex items-center gap-2">
<span class="px-2 py-1 bg-blue-600 text-white text-xs font-medium rounded-full">{media_type}</span>
{ipfs_badge}
</div>
<span class="text-xs text-gray-400">{size_str}</span>
</div>
<div class="text-xs text-gray-400 font-mono mb-3 truncate">{content_hash[:24]}...</div>