import React, { useRef } from 'react'; import superagent from 'superagent'; import { Message, Segment, Grid, Header, Icon, Button, Table, Form, Divider, Label, Transition, Image } from 'semantic-ui-react' export default class HandScannerInput extends React.Component { timeout; constructor(props) { super(props); this.state = { scannedSerialNumber: props.value || "", shiftKeyHeld: false, ctrlKeyHeld: false, show: false, fastStrokes : 0, }; } async handleKeyDown(event) { if (event.key === "Control") { console.log("Ctrl pressed"); //debug this.setState({ ctrlKeyHeld: true }); } else if (event.key === "Shift") { console.log("Shift pressed", { shiftState: this.state.shiftKeyHeld }); //debug this.setState({ shiftKeyHeld: true }); } } async handleKeyUp(event) { event.preventDefault(); let fastStrokes = this.state.fastStrokes + 1; if (event.key === "Control") { console.log("Ctrl released"); this.setState({ ctrlKeyHeld: false }); } else if (event.key === "Shift") { //Nixed as the scanner releases shift before the triggering the shifted keypress // console.log("Shift released", {shiftState: this.state.shiftKeyHeld}); //debug // this.setState({ shiftKeyHeld: false }); } if (event.target.name && event.target.name !== "scannedSerialNumber") { return; } if (event.key === "Backspace" && event.target.name !== "scannedSerialNumber") { let scannedSerialNumber = this.state.scannedSerialNumber; this.setState({ scannedSerialNumber: scannedSerialNumber.slice(0, -1) }); } else if (event.key === " ") { let altSn = this.state.altSerialNumber ? this.state.altSerialNumber : ""; console.log("Space pressed"); console.log(this.state.scannedSerialNumber + altSn); this.setState({ scannedSerialNumber: this.state.scannedSerialNumber + altSn }); } else { let key = ""; if (event.key.length === 1 && event.target.name !== "scannedSerialNumber" && !this.state.ctrlKeyHeld) { key = this.getShiftedKeypress(event); this.setState({ shiftKeyHeld: false }); } let scannedSerialNumber = this.state.scannedSerialNumber; this.setState({ scannedSerialNumber: scannedSerialNumber + key }); } if (this.timeout) { // console.log({sn: this.state.scannedSerialNumber}); //debug clearTimeout(this.timeout); } this.setState({ fastStrokes }); this.strokesTimeout = setTimeout(this.resetFastStrokes.bind(this), 5); this.timeout = setTimeout(this.onScanFinished.bind(this, (event.key === "Enter" || event.key === " " || fastStrokes >= 8)), 250); } async componentDidMount() { this.setState({ menuLoading: true }); document.addEventListener('keyup', this.handleKeyUp.bind(this)); document.addEventListener('keydown', this.handleKeyDown.bind(this)); setTimeout(() => {this.setState({ show: true })}, 250); } async onScanFinished(forceSubmit = true) { let scannedSerialNumber = this.state.scannedSerialNumber; if (forceSubmit) { // HACK HACK HACK // // The Bigscreen serial numbers are all lowercase. if (scannedSerialNumber.startsWith("bs")) { scannedSerialNumber = scannedSerialNumber.toUpperCase(); } console.log("Scan finished", scannedSerialNumber); //debug await this.props.onScanFinished(scannedSerialNumber); this.setState({ scannedSerialNumber: "" }); } } onChange(e, { name, value }) { this.setState({ [name]: value }) } onSearch(e) { if (this.timeout) { clearTimeout(this.timeout); } this.setState({ scannedSerialNumber: this.state.altSerialNumber }, this.onScanFinished.bind(this)); } onIngestInventoryItem(e) { e.preventDefault(); } onDismissMessage(e) { this.setState({ message: null }); } onClearValue(e, { name, value }) { this.setState({ scannedSerialNumber: "" }, this.onScanFinished.bind(this)); } resetFastStrokes() { this.setState({ fastStrokes: 0 }); } /* * We use this function to get shift-modified input from the scanner. It is specifically needed for input when the textbox is not focused. * * Reason: event.key always returns the "unshifted" version of the key's name. */ getShiftedKeypress(event) { const shiftedKeys = { '`': '~', '1': '!', '2': '@', '3': '#', '4': '$', '5': '%', '6': '^', '7': '&', '8': '*', '9': '(', '0': ')', '-': '_', '=': '+', '[': '{', ']': '}', '\\': '|', ';': ':', "'": '"', ',': '<', '.': '>', '/': '?' }; const shiftKeyHeld = this.state.shiftKeyHeld; let retVal = event.key; // if(shiftKeyHeld) console.log("getActualKeyPressed()", { shiftState: shiftKeyHeld, key: retVal, shiftedLookup: shiftedKeys[retVal] }); //debug if (shiftKeyHeld && shiftedKeys[retVal]) { console.log("Shifted key:", shiftedKeys[event.key]); //debug retVal = shiftedKeys[retVal]; } else if (shiftKeyHeld && retVal.length === 1 && retVal.match(/[a-zA-Z]/)) { console.log("Shifted letter:", retVal.toUpperCase()); //debug retVal = retVal.toUpperCase(); } return retVal; } render() { let images = ['/images/scanner.png', '/images/nfc.png']; let title = "Scan a barcode"; let altTitle = "Scan a barcode"; if (this.props.type === "inventory") { title = "Scan a barcode or NFC Tag"; altTitle = "Enter serial number"; } else if (this.props.type === "trackingLabel") { images = ['/images/sample_label.png']; title = "Scan a tracking label"; altTitle = "Enter a tracking number"; } if (this.props.inlineFormInput) { return (