mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 04:42:57 +00:00
Adjust NIP-07 permissions for decrypt flows
This commit is contained in:
1 parent
661f501a15
commit
7c47208255
8 files changed
+437
-12
No files matched your search
+115
-1
@@ -201,6 +201,7 @@ import {
|
||||
clearActiveSigner as clearActiveSignerInRegistry,
|
||||
logoutSigner as logoutSignerFromRegistry,
|
||||
resolveActiveSigner as resolveActiveSignerFromRegistry,
|
||||
requestDefaultExtensionPermissions,
|
||||
} from "../nostrClientRegistry.js";
|
||||
import { createNip07Adapter } from "./adapters/nip07Adapter.js";
|
||||
import { createNsecAdapter } from "./adapters/nsecAdapter.js";
|
||||
@@ -1016,6 +1017,63 @@ function buildDmFilters(actorPubkey, { since, until, limit } = {}) {
|
||||
return filters;
|
||||
}
|
||||
|
||||
function normalizeDmEncryptionHint(value) {
|
||||
if (typeof value !== "string") {
|
||||
return "";
|
||||
}
|
||||
return value.trim().toLowerCase().replace(/[^a-z0-9_.-]/g, "");
|
||||
}
|
||||
|
||||
function resolveDmDecryptPermissionMethods(event) {
|
||||
if (!event || typeof event !== "object") {
|
||||
return [];
|
||||
}
|
||||
|
||||
const kind = Number.isFinite(event.kind) ? event.kind : null;
|
||||
if (kind === 1059) {
|
||||
return ["nip44.decrypt", "nip44.v2.decrypt"];
|
||||
}
|
||||
|
||||
const tags = Array.isArray(event.tags) ? event.tags : [];
|
||||
let requiresNip44 = false;
|
||||
let requiresNip04 = false;
|
||||
|
||||
for (const tag of tags) {
|
||||
if (!Array.isArray(tag) || tag.length < 2) {
|
||||
continue;
|
||||
}
|
||||
const label = typeof tag[0] === "string" ? tag[0].trim().toLowerCase() : "";
|
||||
if (label !== "encrypted" && label !== "encryption") {
|
||||
continue;
|
||||
}
|
||||
for (let index = 1; index < tag.length; index += 1) {
|
||||
const normalized = normalizeDmEncryptionHint(tag[index]);
|
||||
if (!normalized) {
|
||||
continue;
|
||||
}
|
||||
if (normalized.includes("nip44")) {
|
||||
requiresNip44 = true;
|
||||
}
|
||||
if (normalized.includes("nip04")) {
|
||||
requiresNip04 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!requiresNip04 && !requiresNip44 && kind === 4) {
|
||||
requiresNip04 = true;
|
||||
}
|
||||
|
||||
const methods = [];
|
||||
if (requiresNip04) {
|
||||
methods.push("nip04.decrypt");
|
||||
}
|
||||
if (requiresNip44) {
|
||||
methods.push("nip44.decrypt", "nip44.v2.decrypt");
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
const EXTENSION_MIME_MAP = Object.freeze(
|
||||
Object.fromEntries(
|
||||
@@ -4650,7 +4708,10 @@ export class NostrClient {
|
||||
return { actorPubkey: normalizedActor, decryptors };
|
||||
}
|
||||
|
||||
async decryptDirectMessageEvent(event, { actorPubkey } = {}) {
|
||||
async decryptDirectMessageEvent(
|
||||
event,
|
||||
{ actorPubkey, onPermissionRequest } = {},
|
||||
) {
|
||||
const eventId = typeof event?.id === "string" ? event.id : "";
|
||||
if (eventId) {
|
||||
const cached = this.dmDecryptCache.get(eventId);
|
||||
@@ -4661,6 +4722,50 @@ export class NostrClient {
|
||||
|
||||
const decryptDM = await this.ensureDmDecryptor();
|
||||
const context = await this.buildDmDecryptContext(actorPubkey);
|
||||
const permissionMethods = resolveDmDecryptPermissionMethods(event);
|
||||
const needsExtensionPermission =
|
||||
permissionMethods.length &&
|
||||
typeof window !== "undefined" &&
|
||||
window?.nostr &&
|
||||
!this.hasRequiredExtensionPermissions(permissionMethods) &&
|
||||
context.decryptors.some(
|
||||
(candidate) => candidate?.source === "extension",
|
||||
);
|
||||
|
||||
if (needsExtensionPermission) {
|
||||
if (typeof onPermissionRequest === "function") {
|
||||
onPermissionRequest({
|
||||
status: "decrypting",
|
||||
methods: permissionMethods,
|
||||
eventId,
|
||||
});
|
||||
}
|
||||
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult?.ok) {
|
||||
const error = new Error("extension-permission-denied");
|
||||
error.code = "extension-permission-denied";
|
||||
error.cause = permissionResult?.error || null;
|
||||
if (typeof onPermissionRequest === "function") {
|
||||
onPermissionRequest({
|
||||
status: "error",
|
||||
methods: permissionMethods,
|
||||
eventId,
|
||||
error,
|
||||
});
|
||||
}
|
||||
return { ok: false, error };
|
||||
}
|
||||
|
||||
if (typeof onPermissionRequest === "function") {
|
||||
onPermissionRequest({
|
||||
status: "ready",
|
||||
methods: permissionMethods,
|
||||
eventId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
@@ -4694,6 +4799,10 @@ export class NostrClient {
|
||||
Number.isFinite(options?.decryptLimit) && options.decryptLimit > 0
|
||||
? Math.floor(options.decryptLimit)
|
||||
: null;
|
||||
const onPermissionRequest =
|
||||
typeof options?.onPermissionRequest === "function"
|
||||
? options.onPermissionRequest
|
||||
: null;
|
||||
|
||||
const relayCandidates = Array.isArray(options.relays)
|
||||
? options.relays
|
||||
@@ -4746,6 +4855,7 @@ export class NostrClient {
|
||||
try {
|
||||
const decrypted = await this.decryptDirectMessageEvent(event, {
|
||||
actorPubkey: context.actorPubkey || actorPubkeyInput,
|
||||
onPermissionRequest,
|
||||
});
|
||||
if (decrypted?.ok) {
|
||||
messages.push(decrypted);
|
||||
@@ -4830,6 +4940,10 @@ export class NostrClient {
|
||||
|
||||
const result = await this.decryptDirectMessageEvent(event, {
|
||||
actorPubkey: context.actorPubkey || actorPubkeyInput,
|
||||
onPermissionRequest:
|
||||
typeof options?.onPermissionRequest === "function"
|
||||
? options.onPermissionRequest
|
||||
: null,
|
||||
});
|
||||
|
||||
if (result?.ok) {
|
||||
|
||||
@@ -22,12 +22,11 @@ export const DEFAULT_NIP07_ENCRYPTION_METHODS = Object.freeze([
|
||||
]);
|
||||
|
||||
export const DEFAULT_NIP07_PERMISSION_METHODS = Object.freeze([
|
||||
// Core auth + relay metadata
|
||||
// Core auth + relay metadata (encryption permissions requested on demand)
|
||||
"get_public_key",
|
||||
"sign_event",
|
||||
"read_relays",
|
||||
"write_relays",
|
||||
...DEFAULT_NIP07_ENCRYPTION_METHODS,
|
||||
]);
|
||||
|
||||
export const NIP07_PRIORITY = Object.freeze({
|
||||
|
||||
@@ -717,7 +717,14 @@ class HashtagPreferencesService {
|
||||
(!signerHasNip04 && requiresNip04)
|
||||
) {
|
||||
try {
|
||||
await requestDefaultExtensionPermissions();
|
||||
const permissionMethods = [];
|
||||
if (requiresNip04) {
|
||||
permissionMethods.push("nip04.decrypt");
|
||||
}
|
||||
if (requiresNip44) {
|
||||
permissionMethods.push("nip44.decrypt", "nip44.v2.decrypt");
|
||||
}
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
`${LOG_PREFIX} Extension permissions request failed while loading preferences`,
|
||||
@@ -920,7 +927,15 @@ class HashtagPreferencesService {
|
||||
}
|
||||
|
||||
if (signer.type === "extension") {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
const permissionMethods = ["sign_event"];
|
||||
if (typeof signer.nip04Encrypt === "function") {
|
||||
permissionMethods.push("nip04.encrypt");
|
||||
}
|
||||
if (typeof signer.nip44Encrypt === "function") {
|
||||
permissionMethods.push("nip44.encrypt", "nip44.v2.encrypt");
|
||||
}
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult?.ok) {
|
||||
const error = new Error(
|
||||
"The active signer must allow encryption and signing before publishing preferences.",
|
||||
|
||||
@@ -958,6 +958,24 @@ export class NostrService {
|
||||
...options,
|
||||
limit: resolvedLimit,
|
||||
decryptLimit: resolvedDecryptLimit,
|
||||
onPermissionRequest: (detail = {}) => {
|
||||
const status = detail?.status;
|
||||
if (status === "decrypting") {
|
||||
this.emit("directMessages:status", {
|
||||
status,
|
||||
message: "Decrypting direct messages…",
|
||||
methods: detail?.methods || [],
|
||||
eventId: detail?.eventId || null,
|
||||
});
|
||||
} else if (status === "ready") {
|
||||
this.emit("directMessages:status", { status: "ready" });
|
||||
} else if (status === "error") {
|
||||
this.emit("directMessages:status", {
|
||||
status: "error",
|
||||
error: detail?.error || null,
|
||||
});
|
||||
}
|
||||
},
|
||||
onMessage: (message) => {
|
||||
this.applyDirectMessage(message, { reason: "load-incremental" });
|
||||
},
|
||||
@@ -1077,6 +1095,24 @@ export class NostrService {
|
||||
{
|
||||
relays: resolvedRelays,
|
||||
onEvent: handlers.onEvent,
|
||||
onPermissionRequest: (detail = {}) => {
|
||||
const status = detail?.status;
|
||||
if (status === "decrypting") {
|
||||
this.emit("directMessages:status", {
|
||||
status,
|
||||
message: "Decrypting direct messages…",
|
||||
methods: detail?.methods || [],
|
||||
eventId: detail?.eventId || null,
|
||||
});
|
||||
} else if (status === "ready") {
|
||||
this.emit("directMessages:status", { status: "ready" });
|
||||
} else if (status === "error") {
|
||||
this.emit("directMessages:status", {
|
||||
status: "error",
|
||||
error: detail?.error || null,
|
||||
});
|
||||
}
|
||||
},
|
||||
onMessage: (message, context = {}) => {
|
||||
this.applyDirectMessage(message, {
|
||||
reason: "subscription",
|
||||
|
||||
+49
-4
@@ -357,6 +357,28 @@ class SubscriptionsManager {
|
||||
});
|
||||
}
|
||||
|
||||
emitStatus(detail = {}) {
|
||||
this.emitter.emit("status", detail);
|
||||
|
||||
if (detail?.status !== "loading") {
|
||||
return;
|
||||
}
|
||||
|
||||
const message =
|
||||
typeof detail?.message === "string" && detail.message.trim()
|
||||
? detail.message.trim()
|
||||
: "Decrypting subscriptions…";
|
||||
const container =
|
||||
this.lastContainerId &&
|
||||
typeof document !== "undefined" &&
|
||||
document.getElementById
|
||||
? document.getElementById(this.lastContainerId)
|
||||
: null;
|
||||
if (container) {
|
||||
container.innerHTML = getSidebarLoadingMarkup(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the subscription list from kind=30000 (d="subscriptions").
|
||||
*/
|
||||
@@ -751,9 +773,21 @@ class SubscriptionsManager {
|
||||
(!signerHasNip04 && !windowHasNip04 && requiresNip04)
|
||||
) {
|
||||
try {
|
||||
const hasCachedPermissions = hasDefaultExtensionPermissions();
|
||||
const permissionMethods = [];
|
||||
if (requiresNip04) {
|
||||
permissionMethods.push("nip04.decrypt");
|
||||
}
|
||||
if (requiresNip44) {
|
||||
permissionMethods.push("nip44.decrypt", "nip44.v2.decrypt");
|
||||
}
|
||||
const hasCachedPermissions = hasDefaultExtensionPermissions(permissionMethods);
|
||||
if (!hasCachedPermissions) {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
this.emitStatus({
|
||||
status: "loading",
|
||||
message: "Decrypting subscriptions…",
|
||||
});
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult?.ok) {
|
||||
const error =
|
||||
permissionResult?.error instanceof Error
|
||||
@@ -769,6 +803,8 @@ class SubscriptionsManager {
|
||||
const wrapped = error instanceof Error ? error : new Error(String(error));
|
||||
wrapped.code = "nostr-permission-error";
|
||||
return { ok: false, error: wrapped };
|
||||
} finally {
|
||||
this.emitStatus({ status: "idle" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,9 +1019,18 @@ class SubscriptionsManager {
|
||||
}
|
||||
|
||||
if (signer.type === "extension") {
|
||||
const hasCachedPermissions = hasDefaultExtensionPermissions();
|
||||
const permissionMethods = ["sign_event"];
|
||||
if (typeof signer.nip04Encrypt === "function") {
|
||||
permissionMethods.push("nip04.encrypt");
|
||||
}
|
||||
if (typeof signer.nip44Encrypt === "function") {
|
||||
permissionMethods.push("nip44.encrypt", "nip44.v2.encrypt");
|
||||
}
|
||||
const hasCachedPermissions =
|
||||
hasDefaultExtensionPermissions(permissionMethods);
|
||||
if (!hasCachedPermissions) {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult.ok) {
|
||||
userLogger.warn(
|
||||
"[SubscriptionsManager] Signer permissions denied while updating subscriptions.",
|
||||
|
||||
@@ -940,7 +940,8 @@ export class UploadModal {
|
||||
|
||||
try {
|
||||
if (signer?.type === "extension") {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(["nip04.decrypt"]);
|
||||
if (!permissionResult?.ok) {
|
||||
alert("Extension permissions are required to unlock storage.");
|
||||
return;
|
||||
|
||||
@@ -1270,6 +1270,8 @@ export class ProfileModalController {
|
||||
this.blockListEmpty = null;
|
||||
this.blockListStatus = null;
|
||||
this.blockListLoadingState = "idle";
|
||||
this.subscriptionsStatus = null;
|
||||
this.subscriptionsLoadingState = "idle";
|
||||
this.blockInput = null;
|
||||
this.addBlockedButton = null;
|
||||
this.profileBlockedList = null;
|
||||
@@ -1415,6 +1417,9 @@ export class ProfileModalController {
|
||||
this.subscriptionsService.on("change", () => {
|
||||
void this.populateSubscriptionsList();
|
||||
});
|
||||
this.subscriptionsService.on("status", (detail) => {
|
||||
this.handleSubscriptionsStatus(detail);
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -1424,6 +1429,9 @@ export class ProfileModalController {
|
||||
this.services.userBlocks.on("change", () => {
|
||||
this.populateBlockedList();
|
||||
});
|
||||
this.services.userBlocks.on("status", (detail) => {
|
||||
this.handleBlockListStatus(detail);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1953,6 +1961,9 @@ export class ProfileModalController {
|
||||
subscribe("directMessages:updated", (detail) => {
|
||||
this.handleDirectMessagesUpdated(detail);
|
||||
});
|
||||
subscribe("directMessages:status", (detail) => {
|
||||
this.handleDirectMessagesStatus(detail);
|
||||
});
|
||||
subscribe("directMessages:cleared", () => {
|
||||
this.handleDirectMessagesCleared();
|
||||
});
|
||||
@@ -5018,6 +5029,38 @@ export class ProfileModalController {
|
||||
});
|
||||
}
|
||||
|
||||
handleDirectMessagesStatus(detail = {}) {
|
||||
const status = typeof detail?.status === "string" ? detail.status : "";
|
||||
if (status === "decrypting") {
|
||||
this.setMessagesLoadingState("loading", {
|
||||
message:
|
||||
typeof detail?.message === "string" && detail.message.trim()
|
||||
? detail.message.trim()
|
||||
: "Decrypting direct messages…",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "error") {
|
||||
this.setMessagesLoadingState("error", {
|
||||
message:
|
||||
"Unable to decrypt direct messages. Check your extension permissions.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "ready" && this.messagesLoadingState === "loading") {
|
||||
const actor = this.resolveActiveDmActor();
|
||||
if (!actor) {
|
||||
this.setMessagesLoadingState("unauthenticated");
|
||||
} else if (!this.directMessagesCache.length) {
|
||||
this.setMessagesLoadingState("empty");
|
||||
} else {
|
||||
this.setMessagesLoadingState("ready");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleDirectMessagesCleared() {
|
||||
if (this.activeMessagesRequest) {
|
||||
return;
|
||||
@@ -7393,6 +7436,144 @@ export class ProfileModalController {
|
||||
}
|
||||
}
|
||||
|
||||
handleBlockListStatus(detail = {}) {
|
||||
const status = typeof detail?.status === "string" ? detail.status : "";
|
||||
const message =
|
||||
typeof detail?.message === "string" && detail.message.trim()
|
||||
? detail.message.trim()
|
||||
: "";
|
||||
|
||||
if (status === "loading") {
|
||||
this.setBlockListLoadingState("loading", { message });
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "error") {
|
||||
this.setBlockListLoadingState("error", { message });
|
||||
return;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
this.setBlockListLoadingState("idle");
|
||||
}
|
||||
}
|
||||
|
||||
ensureSubscriptionsStatusElement() {
|
||||
if (this.subscriptionsStatus instanceof HTMLElement) {
|
||||
return this.subscriptionsStatus;
|
||||
}
|
||||
|
||||
const anchor =
|
||||
this.subscriptionList instanceof HTMLElement
|
||||
? this.subscriptionList
|
||||
: this.subscriptionListEmpty instanceof HTMLElement
|
||||
? this.subscriptionListEmpty
|
||||
: null;
|
||||
|
||||
if (!anchor || !(anchor.parentElement instanceof HTMLElement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const existing = anchor.parentElement.querySelector(
|
||||
'[data-role="subscriptions-status"]',
|
||||
);
|
||||
if (existing instanceof HTMLElement) {
|
||||
this.subscriptionsStatus = existing;
|
||||
return existing;
|
||||
}
|
||||
|
||||
const status = document.createElement("div");
|
||||
status.dataset.role = "subscriptions-status";
|
||||
status.className = "mt-4 flex items-center gap-3 text-sm text-muted hidden";
|
||||
status.setAttribute("role", "status");
|
||||
status.setAttribute("aria-live", "polite");
|
||||
|
||||
if (this.subscriptionList instanceof HTMLElement) {
|
||||
anchor.parentElement.insertBefore(status, this.subscriptionList);
|
||||
} else {
|
||||
anchor.parentElement.appendChild(status);
|
||||
}
|
||||
|
||||
this.subscriptionsStatus = status;
|
||||
return status;
|
||||
}
|
||||
|
||||
setSubscriptionsLoadingState(state = "idle", options = {}) {
|
||||
const statusEl = this.ensureSubscriptionsStatusElement();
|
||||
if (!statusEl) {
|
||||
this.subscriptionsLoadingState = state;
|
||||
return;
|
||||
}
|
||||
|
||||
const message =
|
||||
typeof options.message === "string" && options.message.trim()
|
||||
? options.message.trim()
|
||||
: "";
|
||||
|
||||
statusEl.innerHTML = "";
|
||||
statusEl.classList.remove("text-status-warning");
|
||||
statusEl.classList.add("text-muted");
|
||||
statusEl.classList.add("hidden");
|
||||
|
||||
this.subscriptionsLoadingState = state;
|
||||
|
||||
if (state === "loading") {
|
||||
if (this.subscriptionListEmpty instanceof HTMLElement) {
|
||||
this.subscriptionListEmpty.classList.add("hidden");
|
||||
}
|
||||
|
||||
const spinner = document.createElement("span");
|
||||
spinner.className = "status-spinner status-spinner--inline";
|
||||
spinner.setAttribute("aria-hidden", "true");
|
||||
|
||||
const text = document.createElement("span");
|
||||
text.textContent = message || "Loading subscriptions…";
|
||||
|
||||
statusEl.appendChild(spinner);
|
||||
statusEl.appendChild(text);
|
||||
statusEl.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
if (state === "error") {
|
||||
statusEl.classList.remove("text-muted");
|
||||
statusEl.classList.add("text-status-warning");
|
||||
|
||||
if (this.subscriptionListEmpty instanceof HTMLElement) {
|
||||
this.subscriptionListEmpty.classList.add("hidden");
|
||||
}
|
||||
|
||||
const text = document.createElement("span");
|
||||
text.textContent =
|
||||
message || "Subscriptions may be out of date. Try again later.";
|
||||
|
||||
statusEl.appendChild(text);
|
||||
statusEl.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
handleSubscriptionsStatus(detail = {}) {
|
||||
const status = typeof detail?.status === "string" ? detail.status : "";
|
||||
const message =
|
||||
typeof detail?.message === "string" && detail.message.trim()
|
||||
? detail.message.trim()
|
||||
: "";
|
||||
|
||||
if (status === "loading") {
|
||||
this.setSubscriptionsLoadingState("loading", { message });
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "error") {
|
||||
this.setSubscriptionsLoadingState("error", { message });
|
||||
return;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
this.setSubscriptionsLoadingState("idle");
|
||||
}
|
||||
}
|
||||
|
||||
normalizeHashtagTag(value) {
|
||||
return normalizeHashtag(value);
|
||||
}
|
||||
@@ -8141,6 +8322,9 @@ export class ProfileModalController {
|
||||
if (!deduped.length) {
|
||||
this.subscriptionListEmpty.classList.remove("hidden");
|
||||
this.subscriptionList.classList.add("hidden");
|
||||
if (this.subscriptionsLoadingState === "loading") {
|
||||
this.setSubscriptionsLoadingState("idle");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8224,6 +8408,10 @@ export class ProfileModalController {
|
||||
this.subscriptionList.appendChild(item);
|
||||
});
|
||||
|
||||
if (this.subscriptionsLoadingState === "loading") {
|
||||
this.setSubscriptionsLoadingState("idle");
|
||||
}
|
||||
|
||||
if (
|
||||
entriesNeedingFetch.size &&
|
||||
typeof this.services.batchFetchProfiles === "function"
|
||||
@@ -8251,6 +8439,10 @@ export class ProfileModalController {
|
||||
if (this.subscriptionListEmpty instanceof HTMLElement) {
|
||||
this.subscriptionListEmpty.classList.remove("hidden");
|
||||
}
|
||||
|
||||
if (this.subscriptionsLoadingState === "loading") {
|
||||
this.setSubscriptionsLoadingState("idle");
|
||||
}
|
||||
}
|
||||
|
||||
async handleUnsubscribeFromCreator(candidate) {
|
||||
|
||||
+25
-2
@@ -825,7 +825,20 @@ class UserBlockListManager {
|
||||
let permissionError = null;
|
||||
if ((!signerHasNip44 && requiresNip44) || (!signerHasNip04 && requiresNip04)) {
|
||||
try {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
const permissionMethods = [];
|
||||
if (requiresNip04) {
|
||||
permissionMethods.push("nip04.decrypt");
|
||||
}
|
||||
if (requiresNip44) {
|
||||
permissionMethods.push("nip44.decrypt", "nip44.v2.decrypt");
|
||||
}
|
||||
emitStatus({
|
||||
status: "loading",
|
||||
message: "Decrypting blocked creators…",
|
||||
reason: "permissions",
|
||||
});
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult?.ok) {
|
||||
permissionError =
|
||||
permissionResult?.error instanceof Error
|
||||
@@ -836,6 +849,8 @@ class UserBlockListManager {
|
||||
}
|
||||
} catch (error) {
|
||||
permissionError = error instanceof Error ? error : new Error(String(error));
|
||||
} finally {
|
||||
emitStatus({ status: "settled", reason: "permissions" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1789,7 +1804,15 @@ class UserBlockListManager {
|
||||
}
|
||||
|
||||
if (signer.type === "extension") {
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
const permissionMethods = ["sign_event"];
|
||||
if (typeof signer.nip04Encrypt === "function") {
|
||||
permissionMethods.push("nip04.encrypt");
|
||||
}
|
||||
if (typeof signer.nip44Encrypt === "function") {
|
||||
permissionMethods.push("nip44.encrypt", "nip44.v2.encrypt");
|
||||
}
|
||||
const permissionResult =
|
||||
await requestDefaultExtensionPermissions(permissionMethods);
|
||||
if (!permissionResult.ok) {
|
||||
userLogger.warn(
|
||||
"[UserBlockList] Signer permissions denied while updating the block list.",
|
||||
|
||||
Reference in new issue
Block a user