mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 12:52:26 +00:00
feat(blossom): Phase 2 management — blob delete-on-orphan + kind-10063 server list (#30)
- deleteByUrl maps a Blossom URL back to its content-addressed blob (blobSha256FromUrl) and deletes it via BUD-12, defaulting to the URL's own origin. Wired into the edit-modal orphan cleanup so a superseded Blossom video/thumbnail is reclaimed (best-effort, never blocks the edit). - BUD-03 kind-10063 server-list discovery: read (serversFromServerListEvent) + build (buildBlossomServerListEvent) + an extracted, testable import/publish helper (blossomServerList.js), plus 'Import from my server list' / 'Publish my server list' controls in the Storage pane's Blossom section. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
51072e4871
commit
e81e65ff40
9 files changed
+515
No files matched your search
@@ -9,6 +9,10 @@ import {
|
||||
import { getActiveSigner } from "../../nostr/client.js";
|
||||
import { FEATURE_BLOSSOM_STORAGE } from "../../constants.js";
|
||||
import { BLOSSOM_PROVIDER } from "../../services/blossomService.js";
|
||||
import {
|
||||
importBlossomServerList,
|
||||
publishBlossomServerList,
|
||||
} from "./blossomServerList.js";
|
||||
import { DEFAULT_NIP07_ENCRYPTION_METHODS } from "../../nostr/nip07Permissions.js";
|
||||
import { storageSyncService } from "../../services/storageSyncService.js";
|
||||
import { StorageCorsHelp } from "./storageCorsHelp.js";
|
||||
@@ -106,6 +110,12 @@ export class ProfileStorageController {
|
||||
document.getElementById("storageBlossomSection") || null;
|
||||
this.storageBlossomServersInput =
|
||||
document.getElementById("storageBlossomServers") || null;
|
||||
this.storageBlossomImportBtn =
|
||||
document.getElementById("storageBlossomImportBtn") || null;
|
||||
this.storageBlossomPublishBtn =
|
||||
document.getElementById("storageBlossomPublishBtn") || null;
|
||||
this.storageBlossomServerListStatus =
|
||||
document.getElementById("storageBlossomServerListStatus") || null;
|
||||
this.storageProviderBlossomOption =
|
||||
document.getElementById("storageProviderBlossomOption") || null;
|
||||
// Reveal the Blossom provider option only when the deployment enables it.
|
||||
@@ -161,6 +171,18 @@ export class ProfileStorageController {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.storageBlossomImportBtn instanceof HTMLElement) {
|
||||
this.storageBlossomImportBtn.addEventListener("click", () => {
|
||||
void this.handleImportBlossomServerList();
|
||||
});
|
||||
}
|
||||
|
||||
if (this.storageBlossomPublishBtn instanceof HTMLElement) {
|
||||
this.storageBlossomPublishBtn.addEventListener("click", () => {
|
||||
void this.handlePublishBlossomServerList();
|
||||
});
|
||||
}
|
||||
|
||||
if (this.storageProviderInput instanceof HTMLElement) {
|
||||
this.storageProviderInput.addEventListener("change", () => {
|
||||
void this.handleProviderChange();
|
||||
@@ -560,6 +582,50 @@ export class ProfileStorageController {
|
||||
this.storageUnlockFailure = null;
|
||||
}
|
||||
|
||||
setBlossomServerListStatus(message, kind = "info") {
|
||||
if (!(this.storageBlossomServerListStatus instanceof HTMLElement)) return;
|
||||
this.storageBlossomServerListStatus.textContent = message || "";
|
||||
const tone =
|
||||
kind === "error"
|
||||
? "text-status-danger"
|
||||
: kind === "success"
|
||||
? "text-status-success"
|
||||
: "text-muted";
|
||||
this.storageBlossomServerListStatus.className = `text-xs ${tone}`;
|
||||
}
|
||||
|
||||
blossomServerListArgs() {
|
||||
return {
|
||||
client: this.mainController.services?.nostrClient,
|
||||
pubkey: this.mainController.normalizeHexPubkey(
|
||||
this.mainController.getActivePubkey(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
async handleImportBlossomServerList() {
|
||||
this.setBlossomServerListStatus("Fetching your server list…");
|
||||
const res = await importBlossomServerList(this.blossomServerListArgs());
|
||||
if (
|
||||
res.servers?.length &&
|
||||
this.storageBlossomServersInput instanceof HTMLElement
|
||||
) {
|
||||
this.storageBlossomServersInput.value = res.servers.join("\n");
|
||||
}
|
||||
if (res.error) devLogger.warn("[ProfileModal] Blossom import:", res.error);
|
||||
this.setBlossomServerListStatus(res.message, res.kind);
|
||||
}
|
||||
|
||||
async handlePublishBlossomServerList() {
|
||||
this.setBlossomServerListStatus("Publishing your server list…");
|
||||
const res = await publishBlossomServerList({
|
||||
...this.blossomServerListArgs(),
|
||||
servers: this.parseBlossomServers(),
|
||||
});
|
||||
if (res.error) devLogger.warn("[ProfileModal] Blossom publish:", res.error);
|
||||
this.setBlossomServerListStatus(res.message, res.kind);
|
||||
}
|
||||
|
||||
// After a page reload, a persisted nsec session restores the logged-in pubkey + UI
|
||||
// but NOT the in-memory signer (the key is passphrase-encrypted). Storage unlock then
|
||||
// has no usable signer, and the generic "No active signer" error is misleading.
|
||||
|
||||
Reference in new issue
Block a user