mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
fix: post-integration review — discard in-flight guards, tooltip comment truth
This commit is contained in:
@@ -5120,6 +5120,9 @@ const App: React.FC = () => {
|
||||
}
|
||||
case 'discard': {
|
||||
// The DecisionControl / compact ConfirmDialog has already confirmed.
|
||||
// Same in-flight guard as the primary path: a confirm left open
|
||||
// across an in-flight decision POST must not produce a second one.
|
||||
if (submitted || isSubmitting || isExiting) return;
|
||||
if (action.route === 'approve') {
|
||||
const approve = () =>
|
||||
headerHandlersRef.current.handleAnnotateApprove({ discardAnnotations: true });
|
||||
@@ -5135,7 +5138,7 @@ const App: React.FC = () => {
|
||||
send();
|
||||
}
|
||||
}
|
||||
}, [gate, maybeConfirmUnsavedSourceFileEdits, queueNoteDecision, submitPrimaryDecision]);
|
||||
}, [gate, isExiting, isSubmitting, maybeConfirmUnsavedSourceFileEdits, queueNoteDecision, submitPrimaryDecision, submitted]);
|
||||
|
||||
const annotateDecisionSpec = useMemo(() => buildDecisionSpec({
|
||||
app: 'annotate',
|
||||
|
||||
@@ -3726,7 +3726,10 @@ const ReviewApp: React.FC = () => {
|
||||
}
|
||||
case 'discard':
|
||||
// The DecisionControl / compact ConfirmDialog has already confirmed;
|
||||
// the bare approve posts `feedback: '', annotations: []`.
|
||||
// the bare approve posts `feedback: '', annotations: []`. Same
|
||||
// in-flight guard as the sibling routes: a confirm left open across
|
||||
// an in-flight decision POST must not produce a second decision.
|
||||
if (submitted || busyWithDecision) return;
|
||||
void handleApprove();
|
||||
return;
|
||||
case 'approve-with-notes':
|
||||
@@ -4602,8 +4605,9 @@ const ReviewApp: React.FC = () => {
|
||||
control shape. No composer on this side, ever — every
|
||||
action opens the existing ReviewSubmissionDialog, whose
|
||||
general-comment field is the only note field here. The
|
||||
muted primary carries the self-approval reason in its
|
||||
native title tooltip. */}
|
||||
muted primary carries the self-approval reason via the
|
||||
shared Tooltip + aria-describedby (native title dropped
|
||||
when muted, pinned by test). */}
|
||||
<ExitButton
|
||||
appearance="ghost"
|
||||
labelBreakpoint="lg"
|
||||
|
||||
@@ -35,10 +35,11 @@ export interface DecisionPrimary {
|
||||
icon: 'check' | 'send';
|
||||
count?: number; // rendered as the inline pill; omitted when 0
|
||||
/**
|
||||
* Platform self-approval (PR6, §3.4): rendered dimmed but NOT disabled —
|
||||
* the native `title` tooltip must still show the reason — and every
|
||||
* invocation path (click, Mod+Enter, compact row) is a no-op. The caret
|
||||
* stays live so the menu's non-approve paths remain reachable.
|
||||
* Platform self-approval (PR6, §3.4): rendered dimmed but NOT disabled.
|
||||
* The reason surfaces through the shared Tooltip + aria-describedby (the
|
||||
* native title is deliberately dropped when muted, pinned by test), and
|
||||
* every invocation path (click, Mod+Enter, compact row) is a no-op. The
|
||||
* caret stays live so the menu's non-approve paths remain reachable.
|
||||
*/
|
||||
muted?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user