mirror of
https://github.com/block/buzz.git
synced 2026-11-02 23:41:08 +00:00
## Summary Project channels previously appeared as ordinary channels until the community-wide project enumeration completed, delaying the contextual right rail most noticeably on larger relays. - Restore the last fully validated, relay-and-identity-scoped project collection immediately while keeping live relay data authoritative. - Resolve the active channel's project home through scoped `#buzz-channel` queries instead of waiting for the complete project scan. - Keep snapshots aligned with community removal and relay reconnect invalidation. ### Related issue None found. ### Testing - Pre-push `file-size-check`, `desktop-check`, `desktop-typecheck`, and `desktop-test` - Project enumeration, snapshot persistence, and relay invalidation unit coverage - Targeted Playwright scenario: project sidebar rows open the home channel and nest extra channels No numeric startup benchmark was captured; this draft validates the cache and scoped-query behavior while leaving timing measurement for review. --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com>
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import * as React from "react";
|
|
|
|
import { homeRepositoriesToBind } from "@/features/projects/lib/projectCollection";
|
|
import type { Project } from "@/features/projects/projectModels";
|
|
import { useAttachProjectRepositoryMutation } from "@/features/projects/useAttachProjectRepository";
|
|
import { relayClient } from "@/shared/api/relayClient";
|
|
import { KIND_PROJECT_ANNOUNCEMENT } from "@/shared/constants/kinds";
|
|
import { normalizePubkey } from "@/shared/lib/pubkey";
|
|
|
|
/** Allows automatic healing only from relay-validated owner project data. */
|
|
export function canHealProjectHomeRepositories({
|
|
identityPubkey,
|
|
project,
|
|
projectDataIsAuthoritative,
|
|
}: {
|
|
identityPubkey?: string;
|
|
project: Pick<Project, "owner" | "repositories">;
|
|
projectDataIsAuthoritative: boolean;
|
|
}): boolean {
|
|
return Boolean(
|
|
projectDataIsAuthoritative &&
|
|
identityPubkey &&
|
|
normalizePubkey(identityPubkey) === normalizePubkey(project.owner) &&
|
|
project.repositories.length > 0,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* When the signed-in user owns this project, bind absorbed home-channel
|
|
* repositories onto the `kind:30621` so Overview, other clients, and NIP-MP
|
|
* agree. Agents can announce a repo with `--channel` but cannot edit the
|
|
* owner's project event.
|
|
*/
|
|
export function useHealProjectHomeRepositories(
|
|
project: Project,
|
|
projectDataIsAuthoritative: boolean,
|
|
identityPubkey?: string,
|
|
) {
|
|
const attachMutation = useAttachProjectRepositoryMutation();
|
|
const attemptedRef = React.useRef(new Set<string>());
|
|
const mutateAsync = attachMutation.mutateAsync;
|
|
|
|
React.useEffect(() => {
|
|
if (
|
|
!canHealProjectHomeRepositories({
|
|
identityPubkey,
|
|
project,
|
|
projectDataIsAuthoritative,
|
|
})
|
|
) {
|
|
return;
|
|
}
|
|
|
|
let cancelled = false;
|
|
void (async () => {
|
|
const liveHeads = await relayClient.fetchEvents({
|
|
authors: [project.owner],
|
|
kinds: [KIND_PROJECT_ANNOUNCEMENT],
|
|
limit: 1,
|
|
"#d": [project.dtag],
|
|
});
|
|
if (cancelled) return;
|
|
const liveHead = liveHeads[0];
|
|
if (!liveHead) return;
|
|
const signedAddresses = liveHead.tags
|
|
.filter((tag) => tag[0] === "a" && tag[1])
|
|
.map((tag) => tag[1] as string);
|
|
const pending = homeRepositoriesToBind(project, signedAddresses);
|
|
for (const repository of pending) {
|
|
const key = `${project.projectAddress}:${repository.repoAddress}`;
|
|
if (attemptedRef.current.has(key)) continue;
|
|
attemptedRef.current.add(key);
|
|
try {
|
|
await mutateAsync({ project, repository });
|
|
} catch {
|
|
// Already bound, raced, or not owner-writable this session.
|
|
}
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [identityPubkey, mutateAsync, project, projectDataIsAuthoritative]);
|
|
}
|