mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 08:52:25 +00:00
Merge pull request #346 from PR0M3TH3AN/codex/extend-profilemodalcontroller-with-event-callbacks-x8ug98
Ensure video grid refresh on auth changes
This commit is contained in:
3 files changed
+299
-28
No files matched your search
@@ -1307,12 +1307,22 @@ class Application {
|
||||
},
|
||||
onRequestSwitchProfile: (payload) =>
|
||||
this.handleProfileSwitchRequest(payload),
|
||||
onRelayOperation: (payload) =>
|
||||
this.handleProfileRelayOperation(payload),
|
||||
onRelayModeToggle: (payload) =>
|
||||
this.handleProfileRelayModeToggle(payload),
|
||||
onRelayRestore: (payload) =>
|
||||
this.handleProfileRelayRestore(payload),
|
||||
onBlocklistMutation: (payload) =>
|
||||
this.handleProfileBlocklistMutation(payload),
|
||||
onWalletPersist: (payload) =>
|
||||
this.handleProfileWalletPersist(payload),
|
||||
onWalletTestRequest: (payload) =>
|
||||
this.handleProfileWalletTest(payload),
|
||||
onWalletDisconnectRequest: (payload) =>
|
||||
this.handleProfileWalletDisconnect(payload),
|
||||
onAdminMutation: (payload) =>
|
||||
this.handleProfileAdminMutation(payload),
|
||||
onAdminNotifyError: (payload) =>
|
||||
this.handleProfileAdminNotifyError(payload),
|
||||
onHistoryReady: (payload) =>
|
||||
@@ -2309,13 +2319,247 @@ class Application {
|
||||
throw new Error("Missing pubkey for profile switch request.");
|
||||
}
|
||||
|
||||
if (!this.profileModalController) {
|
||||
throw new Error("Profile modal controller unavailable for switch.");
|
||||
const result = await this.authService.switchProfile(pubkey);
|
||||
|
||||
if (result?.switched) {
|
||||
try {
|
||||
await this.loadVideos(true);
|
||||
} catch (error) {
|
||||
console.error("Failed to refresh videos after switching profiles:", error);
|
||||
}
|
||||
}
|
||||
|
||||
await this.profileModalController.switchProfile(pubkey);
|
||||
await this.loadVideos(true);
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
async handleProfileRelayOperation({
|
||||
action,
|
||||
url,
|
||||
activePubkey,
|
||||
skipPublishIfUnchanged = true,
|
||||
} = {}) {
|
||||
const context = {
|
||||
action,
|
||||
url,
|
||||
ok: false,
|
||||
changed: false,
|
||||
reason: null,
|
||||
error: null,
|
||||
publishResult: null,
|
||||
operationResult: null,
|
||||
};
|
||||
|
||||
if (!activePubkey) {
|
||||
context.reason = "no-active-pubkey";
|
||||
return context;
|
||||
}
|
||||
|
||||
const previous = relayManager.snapshot();
|
||||
|
||||
let operationResult;
|
||||
try {
|
||||
switch (action) {
|
||||
case "add":
|
||||
operationResult = relayManager.addRelay(url);
|
||||
break;
|
||||
case "remove":
|
||||
operationResult = relayManager.removeRelay(url);
|
||||
break;
|
||||
case "restore":
|
||||
operationResult = relayManager.restoreDefaults();
|
||||
break;
|
||||
case "mode-toggle":
|
||||
operationResult = relayManager.cycleRelayMode(url);
|
||||
break;
|
||||
default: {
|
||||
const error = Object.assign(new Error("Unknown relay operation."), {
|
||||
code: "invalid-operation",
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
context.reason = error?.code || "operation-error";
|
||||
context.error = error;
|
||||
return context;
|
||||
}
|
||||
|
||||
context.operationResult = operationResult;
|
||||
context.changed = Boolean(operationResult?.changed);
|
||||
|
||||
if (!context.changed && skipPublishIfUnchanged) {
|
||||
context.reason = operationResult?.reason || "unchanged";
|
||||
return context;
|
||||
}
|
||||
|
||||
try {
|
||||
const publishResult = await relayManager.publishRelayList(activePubkey);
|
||||
if (!publishResult?.ok) {
|
||||
throw Object.assign(new Error("No relays accepted the update."), {
|
||||
code: "publish-failed",
|
||||
});
|
||||
}
|
||||
context.ok = true;
|
||||
context.publishResult = publishResult;
|
||||
|
||||
const refreshReason = `relay-${action || "update"}`;
|
||||
try {
|
||||
await this.onVideosShouldRefresh({ reason: refreshReason });
|
||||
} catch (refreshError) {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
"[Profile] Failed to refresh videos after relay update:",
|
||||
refreshError,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
} catch (error) {
|
||||
context.reason = error?.code || "publish-failed";
|
||||
context.error = error;
|
||||
try {
|
||||
if (Array.isArray(previous)) {
|
||||
relayManager.setEntries(previous, { allowEmpty: false });
|
||||
}
|
||||
} catch (restoreError) {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
"[Profile] Failed to restore relay preferences after publish error:",
|
||||
restoreError,
|
||||
);
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
handleProfileRelayModeToggle(payload = {}) {
|
||||
return payload?.context || null;
|
||||
}
|
||||
|
||||
handleProfileRelayRestore(payload = {}) {
|
||||
return payload?.context || null;
|
||||
}
|
||||
|
||||
async handleProfileBlocklistMutation({
|
||||
action,
|
||||
actorHex,
|
||||
targetHex,
|
||||
} = {}) {
|
||||
const context = { ok: false, reason: null, error: null };
|
||||
|
||||
if (!actorHex || !targetHex) {
|
||||
context.reason = "invalid-target";
|
||||
return context;
|
||||
}
|
||||
|
||||
try {
|
||||
await userBlocks.ensureLoaded(actorHex);
|
||||
const isBlocked = userBlocks.isBlocked(targetHex);
|
||||
|
||||
if (action === "add") {
|
||||
if (isBlocked) {
|
||||
context.reason = "already-blocked";
|
||||
return context;
|
||||
}
|
||||
await userBlocks.addBlock(targetHex, actorHex);
|
||||
context.ok = true;
|
||||
context.reason = "blocked";
|
||||
} else if (action === "remove") {
|
||||
if (!isBlocked) {
|
||||
context.reason = "not-blocked";
|
||||
return context;
|
||||
}
|
||||
await userBlocks.removeBlock(targetHex, actorHex);
|
||||
context.ok = true;
|
||||
context.reason = "unblocked";
|
||||
} else {
|
||||
context.reason = "invalid-action";
|
||||
return context;
|
||||
}
|
||||
|
||||
if (context.ok) {
|
||||
try {
|
||||
await this.onVideosShouldRefresh({ reason: `blocklist-${action}` });
|
||||
} catch (refreshError) {
|
||||
console.error(
|
||||
"Failed to refresh videos after blocklist mutation:",
|
||||
refreshError,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
} catch (error) {
|
||||
context.error = error;
|
||||
context.reason = error?.code || "service-error";
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
async handleProfileAdminMutation(payload = {}) {
|
||||
const action = payload?.action;
|
||||
const context = { ok: false, error: null, result: null };
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case "ensure-ready":
|
||||
await accessControl.ensureReady();
|
||||
context.ok = true;
|
||||
break;
|
||||
case "add-moderator":
|
||||
context.result = await accessControl.addModerator(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
);
|
||||
context.ok = !!context.result?.ok;
|
||||
break;
|
||||
case "remove-moderator":
|
||||
context.result = await accessControl.removeModerator(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
);
|
||||
context.ok = !!context.result?.ok;
|
||||
break;
|
||||
case "list-mutation":
|
||||
if (payload.listType === "whitelist") {
|
||||
context.result =
|
||||
payload.mode === "add"
|
||||
? await accessControl.addToWhitelist(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
)
|
||||
: await accessControl.removeFromWhitelist(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
);
|
||||
} else {
|
||||
context.result =
|
||||
payload.mode === "add"
|
||||
? await accessControl.addToBlacklist(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
)
|
||||
: await accessControl.removeFromBlacklist(
|
||||
payload.actorNpub,
|
||||
payload.targetNpub,
|
||||
);
|
||||
}
|
||||
context.ok = !!context.result?.ok;
|
||||
break;
|
||||
default:
|
||||
context.error = Object.assign(
|
||||
new Error("Unknown admin mutation."),
|
||||
{ code: "invalid-action" },
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
context.error = error;
|
||||
return context;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
async handleProfileWalletPersist({
|
||||
@@ -2611,7 +2855,11 @@ class Application {
|
||||
this.updateActiveProfileUI(activePubkey, detail.postLogin.profile);
|
||||
}
|
||||
|
||||
await this.loadVideos();
|
||||
try {
|
||||
await this.loadVideos(true);
|
||||
} catch (error) {
|
||||
console.error("Failed to refresh videos after login:", error);
|
||||
}
|
||||
this.forceRefreshAllProfiles();
|
||||
if (this.uploadModal?.refreshCloudflareBucketPreview) {
|
||||
await this.uploadModal.refreshCloudflareBucketPreview();
|
||||
@@ -2679,7 +2927,11 @@ class Application {
|
||||
this.subscriptionsLink.classList.add("hidden");
|
||||
}
|
||||
|
||||
await this.loadVideos();
|
||||
try {
|
||||
await this.loadVideos(true);
|
||||
} catch (error) {
|
||||
console.error("Failed to refresh videos after logout:", error);
|
||||
}
|
||||
this.forceRefreshAllProfiles();
|
||||
if (this.uploadModal?.refreshCloudflareBucketPreview) {
|
||||
await this.uploadModal.refreshCloudflareBucketPreview();
|
||||
|
||||
+37
-15
@@ -1601,13 +1601,41 @@ async function loadUserVideos(pubkey) {
|
||||
|
||||
// 2) Collect raw events from all relays
|
||||
const events = [];
|
||||
for (const url of nostrClient.relays) {
|
||||
const relayList = Array.isArray(nostrClient.relays)
|
||||
? nostrClient.relays
|
||||
: Array.from(nostrClient.relays || []);
|
||||
|
||||
if (relayList.length === 0) {
|
||||
try {
|
||||
const result = await nostrClient.pool.list([url], [filter]);
|
||||
events.push(...result);
|
||||
} catch (relayErr) {
|
||||
console.error(`Relay error (${url}):`, relayErr);
|
||||
const fallbackEvents = await nostrClient.pool.list(
|
||||
nostrClient.relays,
|
||||
[filter]
|
||||
);
|
||||
if (Array.isArray(fallbackEvents)) {
|
||||
events.push(...fallbackEvents);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Relay error (default pool):", error);
|
||||
}
|
||||
} else {
|
||||
const relayPromises = relayList.map((url) =>
|
||||
nostrClient.pool.list([url], [filter])
|
||||
);
|
||||
|
||||
const settled = await Promise.allSettled(relayPromises);
|
||||
settled.forEach((result, index) => {
|
||||
const relayUrl = relayList[index];
|
||||
|
||||
if (result.status === "fulfilled") {
|
||||
const relayEvents = Array.isArray(result.value) ? result.value : [];
|
||||
events.push(...relayEvents);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.reason) {
|
||||
console.error(`Relay error (${relayUrl}):`, result.reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3) Convert to "video" objects and keep everything (including tombstones)
|
||||
@@ -1964,7 +1992,7 @@ async function loadUserVideos(pubkey) {
|
||||
app?.attachMoreMenuHandlers?.(container);
|
||||
|
||||
if (!container.dataset.playHandlerBound) {
|
||||
container.addEventListener("click", (event) => {
|
||||
container.addEventListener("click", async (event) => {
|
||||
if (!event || !(event.target instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
@@ -2010,15 +2038,9 @@ async function loadUserVideos(pubkey) {
|
||||
|
||||
if (videoId && typeof app?.playVideoByEventId === "function") {
|
||||
try {
|
||||
const maybePromise = app.playVideoByEventId(videoId);
|
||||
if (maybePromise && typeof maybePromise.then === "function") {
|
||||
maybePromise.catch((error) => {
|
||||
console.error(
|
||||
"Failed to play via event id from channel grid:",
|
||||
error
|
||||
);
|
||||
playWithUrlAndMagnet();
|
||||
});
|
||||
const result = await app.playVideoByEventId(videoId);
|
||||
if (!result || result.error) {
|
||||
playWithUrlAndMagnet();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
|
||||
@@ -1184,10 +1184,7 @@ export class ProfileModalController {
|
||||
button.setAttribute("aria-busy", "true");
|
||||
|
||||
try {
|
||||
await this.requestSwitchProfile({
|
||||
entry,
|
||||
pubkey: entry.pubkey,
|
||||
});
|
||||
await this.switchProfile(entry.pubkey, { entry });
|
||||
} catch (error) {
|
||||
console.error("Failed to switch profile:", error);
|
||||
} finally {
|
||||
@@ -3829,14 +3826,14 @@ export class ProfileModalController {
|
||||
}
|
||||
}
|
||||
|
||||
async switchProfile(pubkey) {
|
||||
async switchProfile(pubkey, { entry } = {}) {
|
||||
if (!pubkey) {
|
||||
return { switched: false, reason: "missing-pubkey" };
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await this.services.switchProfile(pubkey);
|
||||
result = await this.requestSwitchProfile({ pubkey, entry });
|
||||
} catch (error) {
|
||||
const message =
|
||||
error && typeof error.message === "string" && error.message.trim()
|
||||
|
||||
Reference in new issue
Block a user