-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* WIP: Torch/Flashlight support * Refactor torch into seperate component Fixes issues with state updates breaking the camera * Hide away button, add permission checks * Fix incorrect torch toggle state icons * Turn off the torch when navigating away from the scan page * Redesign torch button * Address feedback * Improve error handling * Improve torch switch-off handling * Remove unnecessary react fragements * Add visual feedback to torch button interactions
- Loading branch information
1 parent
6355ee7
commit df30933
Showing
2 changed files
with
109 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import {MutableRefObject, useState, useEffect} from 'react'; | ||
import {BoltIcon, BoltSlashIcon, ExclamationCircleIcon} from '@heroicons/react/24/solid'; | ||
import {Html5Qrcode} from 'html5-qrcode'; | ||
import PropTypes from 'prop-types'; | ||
import {useLogError} from '../../hooks/useError'; | ||
|
||
interface TorchButtonProps { | ||
html5CustomScanner: MutableRefObject<Html5Qrcode | null>; | ||
canUseCamera: boolean; | ||
} | ||
|
||
export function TorchButton({html5CustomScanner, canUseCamera}: TorchButtonProps) { | ||
const [torchOn, setTorchOn] = useState(false); | ||
const [torchUnavailable, setTorchUnavailable] = useState(false); | ||
const logError = useLogError(); | ||
|
||
useEffect(() => { | ||
const toggleTorch = async () => { | ||
try { | ||
const track = html5CustomScanner?.current?.getRunningTrackCameraCapabilities(); | ||
if (track && track.torchFeature().isSupported()) { | ||
await track.torchFeature().apply(torchOn); | ||
} else if (track && !track.torchFeature().isSupported()) { | ||
setTorchUnavailable(true); | ||
console.warn('Torch feature is not supported on this device.'); | ||
} | ||
} catch (error) { | ||
setTorchUnavailable(true); | ||
console.warn('Failed to toggle torch:', error); | ||
logError(`Failed to toggle torch: ${error}`); | ||
} | ||
}; | ||
|
||
toggleTorch(); | ||
}, [torchOn, html5CustomScanner, logError]); | ||
|
||
if (!canUseCamera) { | ||
return; | ||
} | ||
|
||
if (torchUnavailable) { | ||
return ( | ||
<div className="fit-content flex justify-center gap-1 bg-yellow-500 py-3 text-center text-amber-900"> | ||
<span className="flex items-center"> | ||
<ExclamationCircleIcon className="mr-1 h-6 w-6" /> | ||
Your device's torch is unavailable | ||
</span> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div | ||
onClick={() => setTorchOn(prev => !prev)} | ||
className="fit-content flex justify-center gap-1 bg-primary py-3 text-center text-white active:bg-blue-800 dark:bg-blue-600 dark:active:bg-blue-700" | ||
> | ||
<span className="flex items-center"> | ||
{torchOn ? ( | ||
<> | ||
<BoltSlashIcon className="mr-1 h-6 w-6" /> | ||
Turn torch off | ||
</> | ||
) : ( | ||
<> | ||
<BoltIcon className="mr-1 h-6 w-6" /> | ||
Turn torch on | ||
</> | ||
)} | ||
</span> | ||
</div> | ||
); | ||
} | ||
|
||
TorchButton.propTypes = { | ||
html5CustomScanner: PropTypes.object.isRequired, | ||
canUseCamera: PropTypes.bool.isRequired, | ||
}; |