Address review feedback round 6

Keep permission-loading rows stable for the open menu, treat query failures as resolved, and make the cold-cache assertion deterministic.

Co-authored-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e <e18f3511303812c437d487ac4bf46ad897dc46946699b18ab2e60bf8ee0ea851@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
npub1ux8n2yfs8qfvgd75s7kyhar2mztac355v6vmrz4juc9l3msw4pgstums9e
2026-07-13 18:49:08 -07:00
parent e1dcc064c7
commit bc49be33e2
2 changed files with 16 additions and 9 deletions

View File

@@ -1,3 +1,5 @@
import * as React from "react";
import {
Archive,
Bell,
@@ -229,17 +231,22 @@ export function ChannelContextMenuItems({
selfMember?.role === "owner" ||
selfMember?.role === "admin" ||
canManageOwnedAgentChannel;
const hasResolvedMembers = membersQuery.data !== undefined;
const hasResolvedMembers =
membersQuery.data !== undefined || membersQuery.isError;
const hasResolvedOwnerProfiles =
ownerPubkeys.length === 0 || ownerProfilesQuery.data !== undefined;
ownerPubkeys.length === 0 ||
ownerProfilesQuery.data !== undefined ||
ownerProfilesQuery.isError;
const isManagementCandidate =
channel.channelType !== "dm" && channel.archivedAt === null;
// Reserve disabled rows while capability queries resolve. This keeps the
// menu stable under the pointer without making owners close and reopen a
// cold-cache menu before the actions appear.
const showManagementActions =
isManagementCandidate &&
(!hasResolvedMembers || !hasResolvedOwnerProfiles || canManageChannel);
// Context-menu content mounts per open session. Once these rows are reserved,
// keep them until close so permission resolution cannot move another action
// beneath the pointer; eligible rows transition from disabled to enabled.
const [showManagementActions] = React.useState(
() =>
isManagementCandidate &&
(!hasResolvedMembers || !hasResolvedOwnerProfiles || canManageChannel),
);
const disableManagementActions = !canManageChannel;
const showStar = Boolean(onStarChannel && onUnstarChannel);
const showReadToggle = hasUnread

View File

@@ -2335,7 +2335,7 @@ test("open channel management supports join and leave", async ({ page }) => {
});
test("channel context menu edits a stream", async ({ page }) => {
await installMockBridge(page, { channelMembersDelayMs: 500 });
await installMockBridge(page, { channelMembersDelayMs: 2_000 });
await page.goto("/");
await page.getByTestId("channel-agents").click({ button: "right" });