Started working on sandbox

feature/109
Christoph Oberhofer 9 years ago
parent 308544c0dd
commit d6f1ed59ad

1029
dist/quagga.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,4 @@
{
"plugins": ["transform-class-properties"],
"presets": ["es2015-webpack", "stage-0", "react"]
}

@ -0,0 +1 @@
static/*.js*

@ -0,0 +1,9 @@
# Quagga meets React
This example uses webpack & babel to transpile/bundle the required files.
## How to run the example
```console
> npm install && webpack
```

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>index</title>
<meta name="description" content="" />
<meta name="author" content="Christoph Oberhofer" />
<link rel="stylesheet" type="text/css" href="static/style.css" />
<meta name="viewport" content="width=device-width; initial-scale=1.0" />
</head>
<body style="margin: 0">
<div id="react"></div>
<script src="static/bundle.js" type="text/javascript"></script>
</body>
</html>

@ -0,0 +1,26 @@
{
"name": "quagga-react",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Christoph Oberhofer <ch.oberhofer@gmail.com>",
"license": "MIT",
"devDependencies": {
"babel-core": "^6.9.0",
"babel-loader": "^6.2.4",
"babel-plugin-transform-class-properties": "^6.9.0",
"babel-preset-es2015-webpack": "^6.4.1",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"webpack": "^2.1.0-beta.7"
},
"dependencies": {
"material-ui": "^0.15.0",
"react": "^15.1.0",
"react-dom": "^15.1.0",
"react-tap-event-plugin": "^1.0.0"
}
}

@ -0,0 +1,108 @@
import React from 'react';
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
import Paper from 'material-ui/Paper';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import ContentAdd from 'material-ui/svg-icons/content/add';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import {Card, CardTitle, CardText} from 'material-ui/Card';
import Scanner from './Scanner';
import ScanIcon from './ScanIcon';
export default class App extends React.Component {
state = {
drawerOpen: false,
scanning: false,
scannedCodes: [{
codeResult: {
code: "FANAVF1461710",
format: "code_128"
},
timestamp: new Date()
}]
};
_handleClose = () => this.setState({drawerOpen: false});
_handleOpen = () => this.setState({drawerOpen: true});
_handleOpenChange = () => (drawerOpen) => this.setState({drawerOpen});
_startScanning = (e) => {
e.preventDefault();
if (!this.state.scanning) {
this.setState({scanning: true});
}
};
_stopScanning = () => {
this.setState({scanning: false});
};
_handleResult = (result) => {
this._stopScanning();
this.setState({
scannedCodes: [{...result, timestamp: new Date()}]
.concat(this.state.scannedCodes)});
}
render() {
return (
<div>
<Drawer
docked={false}
width={200}
open={this.state.drawerOpen}
onRequestChange={this._handleOpenChange}
>
<MenuItem onTouchTap={this._handleClose}>Menu Item</MenuItem>
<MenuItem onTouchTap={this._handleClose}>Menu Item 2</MenuItem>
</Drawer>
<AppBar
style={{position: 'fixed', top: '0px'}}
title="QuaggaJS"
iconClassNameRight="muidocs-icon-navigation-expand-more"
onLeftIconButtonTouchTap={this._handleOpen}
/>
<FloatingActionButton
secondary={true}
onMouseDown={this._startScanning}
style={{position: 'fixed', right: 0, bottom: 0, margin: '0 1em 1em 0'}}
>
<ScanIcon />
</FloatingActionButton>
<Dialog
style={{paddingTop: '0px'}}
bodyStyle={{padding: '0.5rem'}}
repositionOnUpdate={false}
actions={[
<FlatButton
label="Cancel"
primary={true}
onTouchTap={this._stopScanning}/>
]}
modal={true}
contentStyle={{width: '95%', maxWidth: '95%', height: '95%', maxHeight: '95%'}}
open={this.state.scanning}
>
<Scanner onDetected={this._handleResult} onCancel={this._stopScanning} />
</Dialog>
<div style={{paddingTop: '64px'}}>
{this.state.scannedCodes.map((scannedCode, i) => (
<Card key={i} style={{margin: '0.5em 0.25em 0em'}}>
<CardTitle
titleStyle={{textOverflow: 'ellipsis', overflow: 'hidden'}}
title={scannedCode.codeResult.code}
subtitle={scannedCode.codeResult.format}
/>
<CardText>
Scanned on {scannedCode.timestamp.toLocaleString()}
</CardText>
</Card>
))}
</div>
</div>
);
}
}

@ -0,0 +1,15 @@
import React from 'react';
import pure from 'recompose/pure';
import SvgIcon from 'material-ui/SvgIcon';
let ActionScanBarcode = (props) => (
<SvgIcon {...props}>
<path d="M0 4h4v20h-4zM6 4h2v20h-2zM10 4h2v20h-2zM16 4h2v20h-2zM24 4h2v20h-2zM30 4h2v20h-2zM20 4h1v20h-1zM14 4h1v20h-1zM27 4h1v20h-1zM0 26h2v2h-2zM6 26h2v2h-2zM10 26h2v2h-2zM20 26h2v2h-2zM30 26h2v2h-2zM24 26h4v2h-4zM14 26h4v2h-4z"/>
</SvgIcon>
);
ActionScanBarcode = pure(ActionScanBarcode);
ActionScanBarcode.displayName = 'ActionAccessibility';
ActionScanBarcode.muiName = 'SvgIcon';
export default ActionScanBarcode;

@ -0,0 +1,47 @@
import React from 'react';
import Quagga from '../../../../dist/quagga';
export default class Scanner extends React.Component {
constructor(props) {
super(props);
this._scanner = Quagga
.decoder({readers: ['code_128_reader']})
.locator({patchSize: 'medium'})
.throttle(500)
.fromSource({
target: '.overlay__content',
constraints: {
width: 800,
height: 600,
facingMode: "environment"
}
});
this._onCancel = this._onCancel.bind(this);
}
_onCancel(e) {
e.preventDefault();
if (this._scanUntilResult) {
this._scanUntilResult.cancel();
this._scanUntilResult = null;
}
}
render() {
return (
<div className="overlay__content">
<div className="overlay__close" onClick={this._onCancel}>X</div>
</div>
);
}
componentDidMount() {
this._scanUntilResult = this._scanner.toPromise();
this._scanUntilResult.promise
.then(this.props.onDetected)
.catch(this.props.onCancel);
}
componentWillUnmount() {
this._scanner
.removeEventListener('detected', this.props.onDetected)
.stop();
}
}

@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
ReactDOM.render(
<MuiThemeProvider muiTheme={getMuiTheme()}>
<App />
</MuiThemeProvider>,
document.getElementById('react')
);

@ -0,0 +1,3 @@
video {
max-width: 100%;
}

@ -0,0 +1,23 @@
module.exports = {
entry: [
'./src/index.js'
],
devtool: 'source-map',
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /(node_modules|quagga\.js)/,
loader: 'babel-loader'
}]
},
resolve: {
modules: [
'node_modules'
]
},
output: {
path: __dirname + '/static',
publicPath: '/',
filename: 'bundle.js'
}
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -35,15 +35,40 @@ function fromSource(config, source, inputConfig = {}) {
return this; return this;
}, },
toPromise() { toPromise() {
// how to cancel?? timeout! if (config.inputStream.type === 'LiveStream'
return new Promise((resolve, reject) => { || config.inputStream.type === 'VideoStream') {
scanner.decodeSingle(config, (result) => { let cancelRequested = false;
if (result && result.codeResult && result.codeResult.code) { return {
return resolve(result); cancel() {
} cancelRequested = true;
return reject(result); },
promise: new Promise((resolve, reject) => {
function onProcessed(result) {
if (result && result.codeResult && result.codeResult.code) {
scanner.stop();
scanner.unsubscribe("processed", onProcessed);
resolve(result);
}
if (cancelRequested) {
scanner.stop();
scanner.unsubscribe("processed", onProcessed);
reject("cancelled!");
}
}
scanner.subscribe("processed", onProcessed);
this.start();
})
};
} else {
return new Promise((resolve, reject) => {
scanner.decodeSingle(config, (result) => {
if (result && result.codeResult && result.codeResult.code) {
return resolve(result);
}
return reject(result);
});
}); });
}); }
} }
}; };
} }
@ -66,6 +91,9 @@ function createApi(configuration = Config) {
locator(conf) { locator(conf) {
return setConfig(configuration, "locator", conf); return setConfig(configuration, "locator", conf);
}, },
throttle(timeInMs) {
return setConfig(configuration, "frequency", 1000 / parseInt(timeInMs));
},
config(conf) { config(conf) {
return createApi(merge({}, configuration, conf)); return createApi(merge({}, configuration, conf));
}, },

Loading…
Cancel
Save