fix(vision): hide detection overlay when auto-detection disabled
Add ENABLE_AUTO_DETECTION flag to ObserverVisionFeed.tsx to hide the useless detection overlay that always showed "---" and "0%" since auto-detection is globally disabled. This matches the pattern already used in DockedVisionFeed.tsx. Also includes minor formatting fixes from Biome. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -614,7 +614,11 @@ export function AbacusVisionBridge({
|
||||
</div>
|
||||
|
||||
{/* Camera feed - HERO ELEMENT */}
|
||||
<div ref={cameraFeedContainerRef} data-element="camera-feed-container" className={css({ position: 'relative' })}>
|
||||
<div
|
||||
ref={cameraFeedContainerRef}
|
||||
data-element="camera-feed-container"
|
||||
className={css({ position: 'relative' })}
|
||||
>
|
||||
{cameraSource === 'local' ? (
|
||||
<>
|
||||
<VisionCameraFeed
|
||||
@@ -759,7 +763,9 @@ export function AbacusVisionBridge({
|
||||
borderRadius: 'md',
|
||||
cursor: 'pointer',
|
||||
fontSize: 'md',
|
||||
_hover: { bg: vision.isTorchOn ? 'yellow.500' : 'rgba(255, 255, 255, 0.25)' },
|
||||
_hover: {
|
||||
bg: vision.isTorchOn ? 'yellow.500' : 'rgba(255, 255, 255, 0.25)',
|
||||
},
|
||||
})}
|
||||
title={vision.isTorchOn ? 'Turn off flash' : 'Turn on flash'}
|
||||
>
|
||||
@@ -988,7 +994,9 @@ export function AbacusVisionBridge({
|
||||
borderRadius: 'md',
|
||||
cursor: 'pointer',
|
||||
fontSize: 'md',
|
||||
_hover: { bg: remoteIsTorchOn ? 'yellow.500' : 'rgba(255, 255, 255, 0.25)' },
|
||||
_hover: {
|
||||
bg: remoteIsTorchOn ? 'yellow.500' : 'rgba(255, 255, 255, 0.25)',
|
||||
},
|
||||
})}
|
||||
title={remoteIsTorchOn ? 'Turn off flash' : 'Turn on flash'}
|
||||
>
|
||||
@@ -1144,8 +1152,8 @@ export function AbacusVisionBridge({
|
||||
<span className={css({ fontSize: 'sm', fontWeight: 'medium' })}>Crop</span>
|
||||
<span className={css({ color: 'gray.400', fontSize: 'sm' })}>·</span>
|
||||
{/* Status summary */}
|
||||
{((cameraSource === 'local' && vision.isCalibrated) ||
|
||||
(cameraSource === 'phone' && remoteCalibration)) ? (
|
||||
{(cameraSource === 'local' && vision.isCalibrated) ||
|
||||
(cameraSource === 'phone' && remoteCalibration) ? (
|
||||
<span className={css({ color: 'blue.300', fontSize: 'sm' })}>Manual</span>
|
||||
) : (
|
||||
<span
|
||||
@@ -1310,7 +1318,9 @@ export function AbacusVisionBridge({
|
||||
handleRemoteStartCalibration()
|
||||
}
|
||||
}}
|
||||
disabled={cameraSource === 'local' ? !vision.videoStream : !remoteIsPhoneConnected}
|
||||
disabled={
|
||||
cameraSource === 'local' ? !vision.videoStream : !remoteIsPhoneConnected
|
||||
}
|
||||
className={css({
|
||||
px: 3,
|
||||
py: 1.5,
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
import type { ObservedVisionFrame } from '@/hooks/useSessionObserver'
|
||||
import { css } from '../../../styled-system/css'
|
||||
|
||||
/**
|
||||
* Feature flag to control auto-detection display
|
||||
* When false, hides the detection overlay since auto-detection is disabled globally
|
||||
*/
|
||||
const ENABLE_AUTO_DETECTION = false
|
||||
|
||||
interface ObserverVisionFeedProps {
|
||||
/** The latest vision frame from the observed student */
|
||||
frame: ObservedVisionFrame
|
||||
@@ -45,62 +51,64 @@ export function ObserverVisionFeed({ frame }: ObserverVisionFeedProps) {
|
||||
})}
|
||||
/>
|
||||
|
||||
{/* Detection overlay */}
|
||||
<div
|
||||
data-element="detection-overlay"
|
||||
className={css({
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
p: 2,
|
||||
bg: 'rgba(0, 0, 0, 0.7)',
|
||||
backdropFilter: 'blur(4px)',
|
||||
})}
|
||||
>
|
||||
{/* Detected value */}
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: 2 })}>
|
||||
<span
|
||||
className={css({
|
||||
fontSize: 'lg',
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
fontFamily: 'mono',
|
||||
})}
|
||||
>
|
||||
{frame.detectedValue !== null ? frame.detectedValue : '---'}
|
||||
</span>
|
||||
{frame.detectedValue !== null && (
|
||||
<span className={css({ fontSize: 'xs', color: 'gray.400' })}>
|
||||
{Math.round(frame.confidence * 100)}%
|
||||
{/* Detection overlay - only shown when auto-detection is enabled */}
|
||||
{ENABLE_AUTO_DETECTION && (
|
||||
<div
|
||||
data-element="detection-overlay"
|
||||
className={css({
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
p: 2,
|
||||
bg: 'rgba(0, 0, 0, 0.7)',
|
||||
backdropFilter: 'blur(4px)',
|
||||
})}
|
||||
>
|
||||
{/* Detected value */}
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: 2 })}>
|
||||
<span
|
||||
className={css({
|
||||
fontSize: 'lg',
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
fontFamily: 'mono',
|
||||
})}
|
||||
>
|
||||
{frame.detectedValue !== null ? frame.detectedValue : '---'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{frame.detectedValue !== null && (
|
||||
<span className={css({ fontSize: 'xs', color: 'gray.400' })}>
|
||||
{Math.round(frame.confidence * 100)}%
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Live indicator */}
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: 1 })}>
|
||||
<div
|
||||
className={css({
|
||||
w: '8px',
|
||||
h: '8px',
|
||||
borderRadius: 'full',
|
||||
bg: isStale ? 'gray.500' : 'green.500',
|
||||
animation: isStale ? 'none' : 'pulse 2s infinite',
|
||||
})}
|
||||
/>
|
||||
<span
|
||||
className={css({
|
||||
fontSize: 'xs',
|
||||
color: isStale ? 'gray.500' : 'green.400',
|
||||
})}
|
||||
>
|
||||
{isStale ? 'Stale' : 'Live'}
|
||||
</span>
|
||||
{/* Live indicator */}
|
||||
<div className={css({ display: 'flex', alignItems: 'center', gap: 1 })}>
|
||||
<div
|
||||
className={css({
|
||||
w: '8px',
|
||||
h: '8px',
|
||||
borderRadius: 'full',
|
||||
bg: isStale ? 'gray.500' : 'green.500',
|
||||
animation: isStale ? 'none' : 'pulse 2s infinite',
|
||||
})}
|
||||
/>
|
||||
<span
|
||||
className={css({
|
||||
fontSize: 'xs',
|
||||
color: isStale ? 'gray.500' : 'green.400',
|
||||
})}
|
||||
>
|
||||
{isStale ? 'Stale' : 'Live'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Vision mode badge */}
|
||||
<div
|
||||
|
||||
@@ -32,8 +32,15 @@ export function RemoteCameraQRCode({
|
||||
existingSessionId,
|
||||
compact = false,
|
||||
}: RemoteCameraQRCodeProps) {
|
||||
const { session, isCreating, error, createSession, setExistingSession, clearSession, getPhoneUrl } =
|
||||
useRemoteCameraSession()
|
||||
const {
|
||||
session,
|
||||
isCreating,
|
||||
error,
|
||||
createSession,
|
||||
setExistingSession,
|
||||
clearSession,
|
||||
getPhoneUrl,
|
||||
} = useRemoteCameraSession()
|
||||
|
||||
// Ref to track if we've already initiated session creation
|
||||
// This prevents React 18 Strict Mode from creating duplicate sessions
|
||||
|
||||
Reference in New Issue
Block a user