diff --git a/src/components/BlossomUploadDialog.tsx b/src/components/BlossomUploadDialog.tsx
index 3e2feb3..c28ef9e 100644
--- a/src/components/BlossomUploadDialog.tsx
+++ b/src/components/BlossomUploadDialog.tsx
@@ -109,7 +109,7 @@ export function BlossomUploadDialog({
}, [open]);
// Helper to set fallback servers
- const useFallbackServers = useCallback(() => {
+ const applyFallbackServers = useCallback(() => {
setServers(FALLBACK_SERVERS);
setSelectedServers(new Set([FALLBACK_SERVERS[0]])); // Select first by default
setUsingFallback(true);
@@ -172,7 +172,7 @@ export function BlossomUploadDialog({
const timeout = setTimeout(() => {
setLoadingServers(false);
if (!foundUserServers) {
- useFallbackServers();
+ applyFallbackServers();
}
}, 3000);
@@ -180,7 +180,7 @@ export function BlossomUploadDialog({
subscription?.unsubscribe();
clearTimeout(timeout);
};
- }, [open, pubkey, eventStore, useFallbackServers]);
+ }, [open, pubkey, eventStore, applyFallbackServers]);
// Create preview URL for selected file
useEffect(() => {
diff --git a/src/components/nostr/kinds/BlossomServerListRenderer.tsx b/src/components/nostr/kinds/BlossomServerListRenderer.tsx
new file mode 100644
index 0000000..f60eb6b
--- /dev/null
+++ b/src/components/nostr/kinds/BlossomServerListRenderer.tsx
@@ -0,0 +1,127 @@
+import { BaseEventProps, BaseEventContainer } from "./BaseEventRenderer";
+import { NostrEvent } from "@/types/nostr";
+import { getServersFromEvent } from "@/services/blossom";
+import { useGrimoire } from "@/core/state";
+import { HardDrive, ExternalLink } from "lucide-react";
+import { Button } from "@/components/ui/button";
+
+/**
+ * Kind 10063 Renderer - Blossom User Server List (Feed View)
+ * Shows the user's configured Blossom blob storage servers
+ */
+export function BlossomServerListRenderer({ event }: BaseEventProps) {
+ const { addWindow } = useGrimoire();
+ const servers = getServersFromEvent(event);
+
+ const handleServerClick = (serverUrl: string) => {
+ // Open the blossom viewer with server info
+ addWindow(
+ "blossom",
+ { subcommand: "servers", serverUrl },
+ `blossom servers`,
+ undefined,
+ );
+ };
+
+ if (servers.length === 0) {
+ return (
+
+
+ No Blossom servers configured
+
+
+ );
+ }
+
+ return (
+
+
+ {servers.map((url) => (
+
handleServerClick(url)}
+ >
+
+
+ {url}
+
+
+
+ ))}
+
+
+ );
+}
+
+/**
+ * Kind 10063 Detail Renderer - Blossom User Server List (Detail View)
+ * Shows full Blossom server list with clickable links
+ */
+export function BlossomServerListDetailRenderer({
+ event,
+}: {
+ event: NostrEvent;
+}) {
+ const { addWindow } = useGrimoire();
+ const servers = getServersFromEvent(event);
+
+ const handleServerClick = (serverUrl: string) => {
+ addWindow(
+ "blossom",
+ { subcommand: "servers", serverUrl },
+ `blossom servers`,
+ undefined,
+ );
+ };
+
+ if (servers.length === 0) {
+ return (
+
+ No Blossom servers configured
+
+ );
+ }
+
+ return (
+
+
+
+ Blossom Servers ({servers.length})
+
+ {servers.map((url) => (
+
handleServerClick(url)}
+ >
+
+
+ {url}
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/components/nostr/kinds/index.tsx b/src/components/nostr/kinds/index.tsx
index 5f7411a..842b3fc 100644
--- a/src/components/nostr/kinds/index.tsx
+++ b/src/components/nostr/kinds/index.tsx
@@ -26,6 +26,10 @@ import { Kind9802Renderer } from "./HighlightRenderer";
import { Kind9802DetailRenderer } from "./HighlightDetailRenderer";
import { Kind10002Renderer } from "./RelayListRenderer";
import { Kind10002DetailRenderer } from "./RelayListDetailRenderer";
+import {
+ BlossomServerListRenderer,
+ BlossomServerListDetailRenderer,
+} from "./BlossomServerListRenderer";
import { Kind10317Renderer } from "./GraspListRenderer";
import { Kind10317DetailRenderer } from "./GraspListDetailRenderer";
import { Kind30023Renderer } from "./ArticleRenderer";
@@ -96,6 +100,7 @@ const kindRenderers: Record> = {
9802: Kind9802Renderer, // Highlight
777: SpellRenderer, // Spell (Grimoire)
10002: Kind10002Renderer, // Relay List Metadata (NIP-65)
+ 10063: BlossomServerListRenderer, // Blossom User Server List (BUD-03)
10317: Kind10317Renderer, // User Grasp List (NIP-34)
10006: GenericRelayListRenderer, // Blocked Relays (NIP-51)
10007: GenericRelayListRenderer, // Search Relays (NIP-51)
@@ -170,6 +175,7 @@ const detailRenderers: Record<
1621: IssueDetailRenderer, // Issue Detail (NIP-34)
9802: Kind9802DetailRenderer, // Highlight Detail
10002: Kind10002DetailRenderer, // Relay List Detail (NIP-65)
+ 10063: BlossomServerListDetailRenderer, // Blossom User Server List Detail (BUD-03)
10317: Kind10317DetailRenderer, // User Grasp List Detail (NIP-34)
777: SpellDetailRenderer, // Spell Detail
30023: Kind30023DetailRenderer, // Long-form Article Detail