@@ -8,9 +8,26 @@ import { useNavigate } from "react-router";
88const QRCodeScannerModal = ( ) => {
99 const [ visible , setVisible ] = useState ( false ) ;
1010 const [ lastError , setLastError ] = useState < string | null > ( null ) ;
11+ const [ scannerSession , setScannerSession ] = useState ( 0 ) ;
1112 const t = useTranslate ( ) ;
1213 const navigate = useNavigate ( ) ;
1314
15+ // Force a fresh scanner instance after each open/close cycle so stale camera errors do not persist.
16+ const resetScanner = ( ) => {
17+ setLastError ( null ) ;
18+ setScannerSession ( ( current ) => current + 1 ) ;
19+ } ;
20+
21+ const openScanner = ( ) => {
22+ resetScanner ( ) ;
23+ setVisible ( true ) ;
24+ } ;
25+
26+ const closeScanner = ( ) => {
27+ setVisible ( false ) ;
28+ resetScanner ( ) ;
29+ } ;
30+
1431 const onScan = ( detectedCodes : IDetectedBarcode [ ] ) => {
1532 if ( detectedCodes . length === 0 ) {
1633 return ;
@@ -20,25 +37,25 @@ const QRCodeScannerModal = () => {
2037 // Check for the spoolman ID format
2138 const spoolMatch = result . match ( / ^ w e b \+ s p o o l m a n : s - (?< id > [ 0 - 9 ] + ) $ / i) ;
2239 if ( spoolMatch && spoolMatch . groups ) {
23- setVisible ( false ) ;
40+ closeScanner ( ) ;
2441 navigate ( `/spool/show/${ spoolMatch . groups . id } ` ) ;
2542 return ;
2643 }
2744 const filamentMatch = result . match ( / ^ w e b \+ s p o o l m a n : f - (?< id > [ 0 - 9 ] + ) $ / i) ;
2845 if ( filamentMatch && filamentMatch . groups ) {
29- setVisible ( false ) ;
46+ closeScanner ( ) ;
3047 navigate ( `/filament/show/${ filamentMatch . groups . id } ` ) ;
3148 return ;
3249 }
3350 const spoolURLmatch = result . match ( / ^ h t t p s ? : \/ \/ [ ^ / ] + (?: \/ [ ^ / ] + ) * \/ s p o o l \/ s h o w \/ (?< id > [ 0 - 9 ] + ) $ / i) ;
3451 if ( spoolURLmatch && spoolURLmatch . groups ) {
35- setVisible ( false ) ;
52+ closeScanner ( ) ;
3653 navigate ( `/spool/show/${ spoolURLmatch . groups . id } ` ) ;
3754 return ;
3855 }
3956 const filamentURLmatch = result . match ( / ^ h t t p s ? : \/ \/ [ ^ / ] + (?: \/ [ ^ / ] + ) * \/ f i l a m e n t \/ s h o w \/ (?< id > [ 0 - 9 ] + ) $ / i) ;
4057 if ( filamentURLmatch && filamentURLmatch . groups ) {
41- setVisible ( false ) ;
58+ closeScanner ( ) ;
4259 navigate ( `/filament/show/${ filamentURLmatch . groups . id } ` ) ;
4360 }
4461 } ;
@@ -47,15 +64,16 @@ const QRCodeScannerModal = () => {
4764 < >
4865 < FloatButton
4966 type = "primary"
50- onClick = { ( ) => setVisible ( true ) }
67+ onClick = { openScanner }
5168 icon = { < CameraOutlined /> }
5269 shape = "circle"
5370 style = { { right : "var(--camera-button-right)" , bottom : "var(--camera-button-bottom)" } }
5471 />
55- < Modal open = { visible } destroyOnHidden onCancel = { ( ) => setVisible ( false ) } footer = { null } title = { t ( "scanner.title" ) } >
72+ < Modal open = { visible } destroyOnHidden onCancel = { closeScanner } footer = { null } title = { t ( "scanner.title" ) } >
5673 < Space direction = "vertical" style = { { width : "100%" } } >
5774 < p > { t ( "scanner.description" ) } </ p >
5875 < Scanner
76+ key = { scannerSession }
5977 constraints = { {
6078 facingMode : "environment" ,
6179 } }
0 commit comments