mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-14 03:16:24 +00:00
Implement payout invoice from QR camera
This commit is contained in:
parent
51e21f7f6b
commit
6f95d2541c
37
frontend/package-lock.json
generated
37
frontend/package-lock.json
generated
@ -4825,6 +4825,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
||||||
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
|
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
|
||||||
},
|
},
|
||||||
|
"jsqr": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A=="
|
||||||
|
},
|
||||||
"jss": {
|
"jss": {
|
||||||
"version": "10.9.0",
|
"version": "10.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz",
|
||||||
@ -6452,6 +6457,16 @@
|
|||||||
"qr.js": "0.0.0"
|
"qr.js": "0.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-qr-reader": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA==",
|
||||||
|
"requires": {
|
||||||
|
"jsqr": "^1.2.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"webrtc-adapter": "^7.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-refresh": {
|
"react-refresh": {
|
||||||
"version": "0.4.3",
|
"version": "0.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz",
|
||||||
@ -6742,6 +6757,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||||
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="
|
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="
|
||||||
},
|
},
|
||||||
|
"rtcpeerconnection-shim": {
|
||||||
|
"version": "1.2.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
|
||||||
|
"integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
|
||||||
|
"requires": {
|
||||||
|
"sdp": "^2.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@ -6989,6 +7012,11 @@
|
|||||||
"ajv-keywords": "^3.5.2"
|
"ajv-keywords": "^3.5.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sdp": {
|
||||||
|
"version": "2.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
|
||||||
|
"integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
@ -7887,6 +7915,15 @@
|
|||||||
"integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==",
|
"integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"webrtc-adapter": {
|
||||||
|
"version": "7.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz",
|
||||||
|
"integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==",
|
||||||
|
"requires": {
|
||||||
|
"rtcpeerconnection-shim": "^1.2.15",
|
||||||
|
"sdp": "^2.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"websocket": {
|
"websocket": {
|
||||||
"version": "1.0.34",
|
"version": "1.0.34",
|
||||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
|
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"react-native": "^0.66.4",
|
"react-native": "^0.66.4",
|
||||||
"react-native-svg": "^12.1.1",
|
"react-native-svg": "^12.1.1",
|
||||||
"react-qr-code": "^2.0.3",
|
"react-qr-code": "^2.0.3",
|
||||||
|
"react-qr-reader": "^2.2.1",
|
||||||
"react-responsive": "^9.0.0-beta.6",
|
"react-responsive": "^9.0.0-beta.6",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"websocket": "^1.0.34"
|
"websocket": "^1.0.34"
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Paper, Rating, Button, Grid, Typography, TextField, List, ListItem, ListItemText, Divider, ListItemIcon, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
|
import { IconButton, Paper, Rating, Button, Grid, Typography, TextField, List, ListItem, ListItemText, Divider, ListItemIcon, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material"
|
||||||
import QRCode from "react-qr-code";
|
import QRCode from "react-qr-code";
|
||||||
import Countdown from 'react-countdown';
|
import Countdown from 'react-countdown';
|
||||||
import Chat from "./Chat"
|
import Chat from "./Chat"
|
||||||
import MediaQuery from 'react-responsive'
|
import MediaQuery from 'react-responsive'
|
||||||
|
import QrReader from 'react-qr-reader'
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
import PercentIcon from '@mui/icons-material/Percent';
|
import PercentIcon from '@mui/icons-material/Percent';
|
||||||
import BookIcon from '@mui/icons-material/Book';
|
import BookIcon from '@mui/icons-material/Book';
|
||||||
|
import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner';
|
||||||
|
|
||||||
function getCookie(name) {
|
function getCookie(name) {
|
||||||
let cookieValue = null;
|
let cookieValue = null;
|
||||||
@ -39,6 +41,7 @@ export default class TradeBox extends Component {
|
|||||||
openConfirmDispute: false,
|
openConfirmDispute: false,
|
||||||
badInvoice: false,
|
badInvoice: false,
|
||||||
badStatement: false,
|
badStatement: false,
|
||||||
|
qrscanner: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +234,9 @@ export default class TradeBox extends Component {
|
|||||||
<Divider/>
|
<Divider/>
|
||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
<Typography component="body2" variant="body2">
|
<Typography component="body2" variant="body2">
|
||||||
Please wait for the taker to confirm his commitment by locking a bond.
|
Please wait for the taker to confirm by locking a bond.
|
||||||
|
If the taker does not lock a bond in time the orer will be made
|
||||||
|
public again.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
{this.showBondIsLocked()}
|
{this.showBondIsLocked()}
|
||||||
@ -334,13 +339,26 @@ export default class TradeBox extends Component {
|
|||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => this.setState({badStatement:data.bad_statement})
|
.then((data) => this.setState({badStatement:data.bad_statement})
|
||||||
& this.props.completeSetState(data));
|
& this.props.completeSetState(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleScan = data => {
|
||||||
|
if (data) {
|
||||||
|
this.setState({
|
||||||
|
invoice: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleError = err => {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleQRbutton = () => {
|
||||||
|
this.setState({qrscanner: !this.state.qrscanner});
|
||||||
|
}
|
||||||
|
|
||||||
showInputInvoice(){
|
showInputInvoice(){
|
||||||
return (
|
return (
|
||||||
|
|
||||||
// TODO Option to upload using QR from camera
|
|
||||||
|
|
||||||
<Grid container spacing={1}>
|
<Grid container spacing={1}>
|
||||||
{/* In case the taker was very fast to scan the bond, make the taker found alarm sound again */}
|
{/* In case the taker was very fast to scan the bond, make the taker found alarm sound again */}
|
||||||
<this.Sound soundFileName="taker-found"/>
|
<this.Sound soundFileName="taker-found"/>
|
||||||
@ -363,17 +381,29 @@ export default class TradeBox extends Component {
|
|||||||
helperText={this.state.badInvoice ? this.state.badInvoice : "" }
|
helperText={this.state.badInvoice ? this.state.badInvoice : "" }
|
||||||
label={"Payout Lightning Invoice"}
|
label={"Payout Lightning Invoice"}
|
||||||
required
|
required
|
||||||
|
value={this.state.invoice}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
style: {textAlign:"center"},
|
style: {textAlign:"center"},
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
}}
|
}}
|
||||||
multiline
|
multiline
|
||||||
minRows={4}
|
minRows={5}
|
||||||
maxRows={12}
|
maxRows={this.state.qrscanner ? 5 : 14}
|
||||||
onChange={this.handleInputInvoiceChanged}
|
onChange={this.handleInputInvoiceChanged}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{this.state.qrscanner ?
|
||||||
<Grid item xs={12} align="center">
|
<Grid item xs={12} align="center">
|
||||||
|
<QrReader
|
||||||
|
delay={300}
|
||||||
|
onError={this.handleError}
|
||||||
|
onScan={this.handleScan}
|
||||||
|
style={{ width: '75%' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
: null }
|
||||||
|
<Grid item xs={12} align="center">
|
||||||
|
<IconButton><QrCodeScannerIcon onClick={this.handleQRbutton}/></IconButton>
|
||||||
<Button onClick={this.handleClickSubmitInvoiceButton} variant='contained' color='primary'>Submit</Button>
|
<Button onClick={this.handleClickSubmitInvoiceButton} variant='contained' color='primary'>Submit</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
2
frontend/static/frontend/qr-decoding.worker.js
Normal file
2
frontend/static/frontend/qr-decoding.worker.js
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,7 @@
|
|||||||
|
/*!****************************************!*\
|
||||||
|
!*** ./node_modules/jsqr/dist/jsQR.js ***!
|
||||||
|
\****************************************/
|
||||||
|
|
||||||
|
/*!*************************************************************!*\
|
||||||
|
!*** ./node_modules/react-webcam-qr-scanner/dist/Worker.js ***!
|
||||||
|
\*************************************************************/
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,3 @@
|
|||||||
|
/*!****************************************!*\
|
||||||
|
!*** ./node_modules/jsqr/dist/jsQR.js ***!
|
||||||
|
\****************************************/
|
1
setup.md
1
setup.md
@ -127,6 +127,7 @@ npm install react-countdown
|
|||||||
npm install @mui/icons-material
|
npm install @mui/icons-material
|
||||||
npm install @mui/x-data-grid
|
npm install @mui/x-data-grid
|
||||||
npm install react-responsive
|
npm install react-responsive
|
||||||
|
npm install react-qr-reader
|
||||||
```
|
```
|
||||||
Note we are using mostly MaterialUI V5 (@mui/material) but Image loading from V4 (@material-ui/core) extentions (so both V4 and V5 are needed)
|
Note we are using mostly MaterialUI V5 (@mui/material) but Image loading from V4 (@material-ui/core) extentions (so both V4 and V5 are needed)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user