diff --git a/example/sandbox/index.html b/example/sandbox/index.html index 6ae8902..cc94d1d 100644 --- a/example/sandbox/index.html +++ b/example/sandbox/index.html @@ -10,7 +10,7 @@ - + diff --git a/example/sandbox/src/components/App.js b/example/sandbox/src/components/App.js index e66b204..5a7b016 100644 --- a/example/sandbox/src/components/App.js +++ b/example/sandbox/src/components/App.js @@ -4,13 +4,15 @@ import Drawer from 'material-ui/Drawer'; import FloatingActionButton from 'material-ui/FloatingActionButton'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {Card, CardTitle, CardText} from 'material-ui/Card'; +import {Card, CardText} from 'material-ui/Card'; import IconButton from 'material-ui/IconButton'; import TuneIcon from 'material-ui/svg-icons/image/tune'; import Scanner from './Scanner'; import ScanIcon from './ScanIcon'; +import ScannedCode from './ScannedCode'; import ConfigView from './ConfigView'; +import {persist, load} from '../utils/Storage'; const cleanConfig = config => { if (typeof config.inputStream.constraints.deviceId === 'number') { @@ -19,50 +21,46 @@ const cleanConfig = config => { return config; }; +const defaultConfig = { + frequency: 5, + numOfWorkers: 2, + locate: true, + inputStream: { + name: "Live", + type: "LiveStream", + constraints: { + width: 800, + height: 600, + deviceId: 0, + facingMode: "environment", + }, + area: { + top: "0%", + right: "0%", + left: "0%", + bottom: "0%", + }, + }, + decoder: { + readers: [ + 'ean_reader', + 'code_39_reader', + 'code_128_reader', + ], + }, + locator: { + halfSample: true, + patchSize: "medium", + }, +}; + export default class App extends React.Component { state = { drawerOpen: false, scanning: false, currentView: 'root', - config: { - frequency: 5, - numOfWorkers: 2, - locate: true, - inputStream: { - name: "Live", - type: "LiveStream", - constraints: { - width: 640, - height: 480, - deviceId: 0, - facingMode: "environment", - }, - area: { - top: "0%", - right: "0%", - left: "0%", - bottom: "0%", - }, - }, - decoder: { - readers: [ - 'ean_reader', - 'code_39_reader', - 'code_128_reader', - ], - }, - locator: { - halfSample: true, - patchSize: "medium", - }, - }, - scannedCodes: [{ - codeResult: { - code: "FANAVF1461710", - format: "code_128", - }, - timestamp: new Date(), - }], + config: load("config") || defaultConfig, + scannedCodes: load('scannedCodes') || [], }; _handleToggle = () => { @@ -86,9 +84,20 @@ export default class App extends React.Component { _handleResult = (result) => { this._stopScanning(); - this.setState({ - scannedCodes: [{...result, timestamp: new Date()}] - .concat(this.state.scannedCodes)}); + const scannedCodes = + [{ + angle: result.angle, + box: result.box, + codeResult: { + code: result.codeResult.code, + direction: result.codeResult.direction, + format: result.codeResult.format, + }, + line: result.line, + }] + .concat(this.state.scannedCodes); + this.setState({scannedCodes}); + persist('scannedCodes', scannedCodes); } _navigateTo = (route) => { @@ -100,7 +109,17 @@ export default class App extends React.Component { _handleConfigChange = config => { this.setState({config: cleanConfig(config)}); - console.log(config); + persist("config", config); + } + + _handleDelete = (scannedCode) => { + const index = this.state.scannedCodes.indexOf(scannedCode); + if (index !== -1) { + const newArray = this.state.scannedCodes.slice(); + newArray.splice(index, 1); + this.setState({scannedCodes: newArray}); + persist('scannedCodes', newArray); + } } render() { @@ -119,13 +138,6 @@ export default class App extends React.Component { iconElementLeft={} onLeftIconButtonTouchTap={this._handleToggle} /> - - -
- {this.state.currentView === 'root' && this.state.scannedCodes.map((scannedCode, i) => ( - - + {this.state.currentView === 'root' && this.state.scannedCodes.length === 0 && + - Scanned on {scannedCode.timestamp.toLocaleString()} + Nothing scanned yet + } + {this.state.currentView === 'root' && this.state.scannedCodes.map((scannedCode, i) => ( + ))}
+ + + ); } diff --git a/example/sandbox/src/components/ScanIcon.js b/example/sandbox/src/components/ScanIcon.js index b920cb1..1cd9758 100644 --- a/example/sandbox/src/components/ScanIcon.js +++ b/example/sandbox/src/components/ScanIcon.js @@ -4,7 +4,7 @@ import SvgIcon from 'material-ui/SvgIcon'; let ActionScanBarcode = (props) => ( - + ); diff --git a/example/sandbox/src/components/ScannedCode.js b/example/sandbox/src/components/ScannedCode.js new file mode 100644 index 0000000..e866d16 --- /dev/null +++ b/example/sandbox/src/components/ScannedCode.js @@ -0,0 +1,99 @@ +import React from 'react'; +import {Card, CardActions, CardText, CardHeader} from 'material-ui/Card'; +import FlatButton from 'material-ui/FlatButton'; +import DeleteIcon from 'material-ui/svg-icons/action/delete'; +import Divider from 'material-ui/Divider'; + +const pointGenerator = points => i => `(${points[i][0].toFixed(0)}, ${points[i][1].toFixed(0)})`; +const lineGenerator = line => i => `(${line[i].x.toFixed(0)}, ${line[i].y.toFixed(0)})`; + +const renderLineSegments = items => ( +
+ {items.map((item, i) => ( +
{item}
+ ))} +
+); + +const renderBox = box => { + const p = pointGenerator(box); + const items = [p(1), `→`, p(2), `↑`, ' ', `↓`, p(0), `←`, p(3)]; + return renderLineSegments(items); +}; + +const renderLine = line => { + const l = lineGenerator(line); + const items = [l(0), `→`, l(1)]; + return renderLineSegments(items); +}; + +const renderAngle = angle => ( + + {(angle * 180 / Math.PI).toFixed(2)} + +); + +const renderDirection = direction => ( + + {direction === -1 ? 'forward' : `reverse`} + +); + +const keyStyle = { + fontWeight: 'bold', + flex: '0 1 70px', +}; + +const lineStyle = { + marginBottom: '0.5rem', + marginTop: '0.5rem', + display: 'flex', + alignItems: 'center', +}; + +const ScannedCode = ({scannedCode, onDelete}) => { + return ( + + + +
+
Direction:
{renderDirection(scannedCode.codeResult.direction)}
+
+ +
+
Angle:
{renderAngle(scannedCode.angle)} deg
+
+ +
+
Line:
{renderLine(scannedCode.line)} +
+ +
+
Box:
+ {renderBox(scannedCode.box)} +
+
+ + } /> + +
+ ); +}; + +ScannedCode.propTypes = { + scannedCode: React.PropTypes.object.isRequired, + onDelete: React.PropTypes.func, +}; + +export default ScannedCode; diff --git a/example/sandbox/src/utils/Storage.js b/example/sandbox/src/utils/Storage.js new file mode 100644 index 0000000..b4d087d --- /dev/null +++ b/example/sandbox/src/utils/Storage.js @@ -0,0 +1,35 @@ +function storageWrapper(cb) { + if (typeof window.localStorage !== 'undefined') { + return cb(window.localStorage); + } else { + console.log("localStorage not available"); + } +} + + +export function persist(key, object) { + storageWrapper((storage) => { + storage.setItem(key, JSON.stringify(object)); + }); +}; + +export function push(key, object) { + storageWrapper((storage) => { + const item = storage.getItem() || "[]", + parsed = JSON.parse(item); + if (Array.isArray(parsed)) { + parsed.push(object); + storage.setItem(key, JSON.stringify(parsed)); + } + }); +} + +export function load(key) { + return storageWrapper((storage) => { + const item = storage.getItem(key); + if (item) { + return JSON.parse(item); + } + return null; + }); +}