-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Barcode scanner #1834
Merged
Merged
Barcode scanner #1834
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
882aa3d
feat(barcode): create basic ui & scanner component
r0xsh e386778
wip
r0xsh a6c305b
feat(ui): build all the UI and small logic
r0xsh 1af156c
fix: make unused argument deprecated
r0xsh 668dbe5
feat: app fully functionnal
r0xsh 01940c0
feat(barcode): polish :clean:
r0xsh 3dceb6e
Merge branch 'master' into feature/barcode
r0xsh 6ef3e4b
Merge branch 'master' into feature/barcode
r0xsh 874ada4
Merge branch 'master' into feature/barcode
r0xsh a14f4a7
feat: enable `client action` behaviors
r0xsh 7c449d0
feat: add `ask_to_complete` behavior.
r0xsh bf939ea
fix: fix navigation flow after completing a task via the barcode
r0xsh 3315760
feat: Simplify Barcode component state. Introduce "actions queue"
r0xsh f0d4672
fix: just forward the promise.
r0xsh 5ebf3f6
feat(i18n): add translations
r0xsh 30aa645
feat: add support for action token and forward it to `X-Action-Token`
r0xsh dec59da
fix: navigation callback was not called due to a change of params of
r0xsh bcd16f7
fix: fix navigation behavior when navigate to `Task`
r0xsh 2b154f6
add translations.
r0xsh 77450b7
Merge branch 'master' into feature/barcode
r0xsh d2ee8e1
add little-date dep
r0xsh 3e1cd64
fix: handle dark mode
r0xsh df749ac
fix: show status when scanned
r0xsh a421250
feat: do not display push notifications while in barcode view.
r0xsh f9a6ba2
improve status label on barcode screen. Fix navigator warning
r0xsh 818eeba
fix linter
r0xsh 990d170
clean code.
r0xsh aaaf9b7
fix lint error
r0xsh e963610
add missing dep in useCallback
r0xsh 31bb1a9
make the linter happy again
r0xsh 80aa194
fix(ui): change `Add note` color back to blue
r0xsh 9232e77
feat(barcode): add Start task button
r0xsh 3210222
feat: Add ask to start pickup action
r0xsh b58147e
Merge branch 'master' into feature/barcode
r0xsh ade5eb2
fix linter.
r0xsh a3913da
fix json
r0xsh bcc9096
fix json.
r0xsh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import React, { useState, forwardRef } from 'react'; | ||
import { Dimensions, Text } from 'react-native'; | ||
import { View, Vibration } from 'react-native'; | ||
import { CameraView, useCameraPermissions } from 'expo-camera/next'; | ||
import _ from 'lodash'; | ||
import { Icon } from 'native-base'; | ||
import Ionicons from 'react-native-vector-icons/Ionicons'; | ||
import { TouchableOpacity } from 'react-native-gesture-handler'; | ||
import FocusHandler from './FocusHandler'; | ||
|
||
function getBoxBoundaries(points) { | ||
const xs = points.map(point => point.x); | ||
const ys = points.map(point => point.y); | ||
const minX = Math.min(...xs); | ||
const maxX = Math.max(...xs); | ||
const minY = Math.min(...ys); | ||
const maxY = Math.max(...ys); | ||
return { minX, maxX, minY, maxY }; | ||
} | ||
|
||
function horizontalLineIntersectsBox(lineY, lineStartX, lineEndX, points) { | ||
const { minX, maxX, minY, maxY } = getBoxBoundaries(points); | ||
|
||
if (lineY < minY || lineY > maxY) { | ||
return false; | ||
} | ||
if (lineStartX > lineEndX) { | ||
[lineStartX, lineEndX] = [lineEndX, lineStartX]; | ||
} | ||
return lineEndX >= minX && lineStartX <= maxX; | ||
} | ||
|
||
function BarcodeCameraView({ disabled, ...props }, ref) { | ||
const [hasPermission, requestPermission] = useCameraPermissions(); | ||
|
||
const { width: CameraWidth } = Dimensions.get('window'); | ||
const CameraHeight = CameraWidth * 0.55; | ||
const PaddingHorizontal = CameraWidth * 0.1618; | ||
|
||
const [barcode, setBarcode] = useState(null); | ||
const [flash, setFlash] = useState(false); | ||
|
||
//The hide behavior is a hack to force the camera to re-render | ||
//if another camera is opened on modal. If we don't do this, the | ||
//camera will not render. | ||
const [hide, setHide] = useState(disabled ?? false); | ||
|
||
if (!hasPermission) { | ||
return ( | ||
<View> | ||
<Text>No camera permission</Text> | ||
</View> | ||
); | ||
} | ||
|
||
if (!hasPermission.granted) { | ||
requestPermission(); | ||
return <View />; | ||
} | ||
|
||
const onScanned = _.throttle(result => { | ||
const { data, cornerPoints } = result; | ||
if ( | ||
!horizontalLineIntersectsBox( | ||
CameraHeight / 2, | ||
PaddingHorizontal, | ||
CameraWidth - PaddingHorizontal, | ||
cornerPoints, | ||
) | ||
) { | ||
return; | ||
} | ||
|
||
if (data !== barcode) { | ||
Vibration.vibrate(); | ||
setBarcode(data); | ||
props.onScanned(data); | ||
} | ||
}, 200); | ||
|
||
return ( | ||
<> | ||
<FocusHandler | ||
onFocus={() => { | ||
if (!disabled) { | ||
setHide(false); | ||
} | ||
}} | ||
onBlur={() => { | ||
setHide(true); | ||
}} | ||
/> | ||
{!hide && ( | ||
<CameraView | ||
ref={ref} | ||
enableTorch={flash} | ||
style={{ | ||
height: CameraHeight, | ||
width: CameraWidth, | ||
position: 'relative', | ||
}} | ||
onBarcodeScanned={onScanned} | ||
barcodeScannerSettings={{ | ||
barcodeTypes: ['code128'], | ||
}}> | ||
<View | ||
style={{ | ||
position: 'absolute', | ||
borderColor: 'rgba(255, 0, 0, 0.6)', | ||
borderBottomWidth: 1, | ||
top: CameraHeight / 2, | ||
left: PaddingHorizontal, | ||
right: PaddingHorizontal, | ||
}} | ||
/> | ||
<View | ||
style={{ | ||
position: 'absolute', | ||
top: 10, | ||
right: 10, | ||
}}> | ||
<TouchableOpacity onPress={() => setFlash(!flash)}> | ||
<Icon | ||
as={Ionicons} | ||
name={flash ? 'flash-sharp' : 'flash-off-sharp'} | ||
style={{ color: 'rgba(255, 255, 255, 0.6)' }} | ||
/> | ||
</TouchableOpacity> | ||
</View> | ||
</CameraView> | ||
)} | ||
{hide && ( | ||
<View | ||
style={{ | ||
height: CameraHeight, | ||
width: CameraWidth, | ||
backgroundColor: 'black', | ||
}}></View> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
export default forwardRef(BarcodeCameraView); |
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
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
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe write a more helpful message? like "Allow camera in app setting to use the barcode scanner"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup this is intentional behavior, but this feature is hard to design since it can be used is many scenarios. But i think is can be solve by having a "batch scanning mode".
The feature was originally thought for doing batch scan at morning when the rider prepares his route. But you're right this create some friction in a rider workflow.
Just go back, no ?
Yup expected behavior, the alert is shown only when the task is already assigned to self or another rider.
It just close the modal, maybe No label will be clearer 👍
You can't scan twice the same barcode ? But i agree this is a bit annoying. I already thought about a potential fix for that: https://github.com/coopcycle/coopcycle-app/pull/1834/files#diff-044fc4e1bab6b1c678131dde9f7719a282973acbf04d245c16c2fd26cb335d8aR248-R254
The task should be in
DOING
status to trigger the complete behavior