From 7bfc9cf24b0d2afdd571b3de99b5b1de6fdbd898 Mon Sep 17 00:00:00 2001 From: bashybaranaba Date: Thu, 28 May 2026 00:38:44 +0300 Subject: [PATCH] improve claiming ui --- examples/chat/components/chat/chat-input.tsx | 312 ++++++++++++------- 1 file changed, 191 insertions(+), 121 deletions(-) diff --git a/examples/chat/components/chat/chat-input.tsx b/examples/chat/components/chat/chat-input.tsx index 1dc2171..2c0f8b0 100644 --- a/examples/chat/components/chat/chat-input.tsx +++ b/examples/chat/components/chat/chat-input.tsx @@ -213,6 +213,117 @@ export function ChatInput({ ); } +function AttachmentGovernanceControls({ + governance, + onChange, +}: { + governance: NonNullable; + onChange?: (governance: NonNullable) => void; +}) { + if (!onChange) return null; + + return ( +
+ +
+ + + + +
+ onChange({ ...governance, scope: e.target.value })} + placeholder="Authorized scope" + className="mt-1 h-6 w-full rounded border border-border bg-background px-1 text-[10px] text-muted-foreground outline-none" + /> +
+ {governance.authorizationStatus === "authorized" ? ( + + ) : ( + + )} + + {governance.licenseType} · AI training {governance.aiTraining} + +
+
+ ); +} + /** Compact provenance indicator for an attachment chip. * Runs a background search on mount; shows a small status row. * On match → clickable badge that opens the ProvenanceFileDialog. @@ -222,12 +333,14 @@ function AttachmentProvenance({ onMatchFound, onCidAssigned, governance, + onGovernanceChange, userId, }: { file: File; onMatchFound?: (cid: string) => void; onCidAssigned?: (cid: string) => void; governance?: FileAttachment["governance"]; + onGovernanceChange?: (governance: NonNullable) => void; userId?: string; }) { const { pk } = useProvenanceKit(); @@ -249,9 +362,12 @@ function AttachmentProvenance({ if (!result.matches?.length || result.verdict === "no-match") { setStatus("not-found"); } else { - setTopMatch(result.matches[0]); + const match = result.matches[0]; + setTopMatch(match); setStatus("found"); - onMatchFound?.(result.matches[0].cid); + if (match.score >= 0.95) { + onMatchFound?.(match.cid); + } } }) .catch(() => setStatus("error")); @@ -292,6 +408,16 @@ function AttachmentProvenance({ if (status === "found" && topMatch) { const pct = Math.round(topMatch.score * 100); const isHigh = pct >= 95; + if (claimDone) { + return ( +
+ + + {claimDone === "claimed" ? "Claimed as your work" : "Recorded as governed source"} + +
+ ); + } return ( <> + {!isHigh && governance && ( +
+
+ + Low match. Record a clearer claim? +
+ +
+ {claiming ? ( + + ) : ( + <> + + / + + + )} +
+
+ )} setDialogOpen(false)} @@ -330,30 +488,37 @@ function AttachmentProvenance({ ); } return ( -
- - New file — yours? - {claiming ? ( - - ) : ( - <> - - / - - +
+
+ + No match found. Register this file? +
+ {governance && ( + )} +
+ {claiming ? ( + + ) : ( + <> + + / + + + )} +
); } @@ -397,105 +562,10 @@ function AttachmentChip({ onMatchFound={onCidAssigned} onCidAssigned={onCidAssigned} governance={governance} + onGovernanceChange={onGovernanceChange} userId={userId} /> )} - -
- - - - -
- onGovernanceChange?.({ ...governance, scope: e.target.value })} - placeholder="Authorized scope" - className="mt-1 h-6 rounded border border-border bg-background px-1 text-[10px] text-muted-foreground outline-none" - /> -
- {governance.authorizationStatus === "authorized" ? ( - - ) : ( - - )} - - {governance.licenseType} · AI training {governance.aiTraining} - -
); }