diff --git a/package.json b/package.json index e7988ab..bd19304 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react": "^17.0.2", "react-dom": "^17.0.2", "react-icons": "^3.0.0", + "react-qr-reader": "^2.2.1", "react-redux": "^7.2.4", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", diff --git a/src/App.js b/src/App.js index 2083f8e..550d125 100644 --- a/src/App.js +++ b/src/App.js @@ -7,6 +7,7 @@ import Create from './screens/CreateScreen'; import Success from './screens/SuccessScreen'; import './App.css'; import Verify from './screens/VerifyScreen'; +import Scanner from './screens/ScannerScreen'; function App() { return ( @@ -24,6 +25,9 @@ function App() { + + + diff --git a/src/screens/HomeScreen.js b/src/screens/HomeScreen.js index e940355..cafed57 100644 --- a/src/screens/HomeScreen.js +++ b/src/screens/HomeScreen.js @@ -1,8 +1,8 @@ -import { Flex, Image, Spinner, Text } from '@chakra-ui/react'; +import { Button, Divider, Flex, Image, Spinner, Text } from '@chakra-ui/react'; import axios from 'axios'; import { React, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { Redirect } from 'react-router-dom'; +import { Redirect, useHistory } from 'react-router-dom'; import { authLogout } from '../features/auth/authSlice'; function QRCode() { @@ -34,9 +34,11 @@ function QRCode() { } function Home() { + const history = useHistory(); + const isAuthenticated = useSelector(state => state.auth.isAuthenticated); if (!isAuthenticated) return ; - + return ( - + This is your QR code. Show this to others to allow them to confirm a contact, or allow them to create an account! + + ); diff --git a/src/screens/ScannerScreen.js b/src/screens/ScannerScreen.js new file mode 100644 index 0000000..08641af --- /dev/null +++ b/src/screens/ScannerScreen.js @@ -0,0 +1,99 @@ +import { Button, Divider, Flex, useToast } from '@chakra-ui/react'; +import axios from 'axios'; +import { useEffect, useState } from 'react'; +import QrReader from 'react-qr-reader'; +import { useDispatch, useSelector } from 'react-redux'; +import { Redirect, useHistory } from 'react-router-dom'; +import { authLogout } from '../features/auth/authSlice'; + +function Scanner() { + const toast = useToast(); + const history = useHistory(); + const dispatch = useDispatch(); + + const [scanData, setScanData] = useState(null); + + const handleError = err => { + console.log(err); + }; + + const handleScan = res => { + if (res && res !== scanData) { + setScanData(res); + } + }; + + useEffect(() => { + if (scanData) { + // fucking safari on ios doesn't support lookbehind, so have to workaround with substr + // const re = /(?<=verify\/).*$/; + const re = /verify\/.*$/; + const hash = re.exec(scanData); + if (hash) { + axios + .post( + `${process.env.REACT_APP_API_URL}/verify`, + { + id: hash[0].substr(7), + }, + { withCredentials: true } + ) + .then(res => { + if (res.data.success) { + if (res.data.loggedIn) { + toast({ + title: 'Contact Succesfully Logged', + status: 'info', + duration: 2000, + }); + } else { + console.log('Time to logout!'); + dispatch(authLogout()); + history.push('/login'); + } + } + }) + .catch(e => { + toast({ + title: 'Bad Verification', + status: 'error', + duration: 2000, + }); + }); + } + } + }, [scanData, dispatch, history, toast]); + + const isAuthenticated = useSelector(state => state.auth.isAuthenticated); + if (!isAuthenticated) return ; + + return ( + + + + + + + + ); +} + +export default Scanner; diff --git a/yarn.lock b/yarn.lock index 4830fb3..488a218 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7606,6 +7606,11 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsqr@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.4.0.tgz#8efb8d0a7cc6863cb6d95116b9069123ce9eb2d1" + integrity sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A== + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" @@ -9925,6 +9930,15 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== +react-qr-reader@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-2.2.1.tgz#dc89046d1c1a1da837a683dd970de5926817d55b" + integrity sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA== + dependencies: + jsqr "^1.2.0" + prop-types "^15.7.2" + webrtc-adapter "^7.2.1" + react-redux@^7.2.4: version "7.2.4" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225" @@ -10522,6 +10536,13 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +rtcpeerconnection-shim@^1.2.15: + version "1.2.15" + resolved "https://registry.yarnpkg.com/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz#e7cc189a81b435324c4949aa3dfb51888684b243" + integrity sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw== + dependencies: + sdp "^2.6.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -10636,6 +10657,11 @@ schema-utils@^3.0.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +sdp@^2.12.0, sdp@^2.6.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/sdp/-/sdp-2.12.0.tgz#338a106af7560c86e4523f858349680350d53b22" + integrity sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw== + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -12150,6 +12176,14 @@ webpack@4.44.2: watchpack "^1.7.4" webpack-sources "^1.4.1" +webrtc-adapter@^7.2.1: + version "7.7.1" + resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz#b2c227a6144983b35057df67bd984a7d4bfd17f1" + integrity sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A== + dependencies: + rtcpeerconnection-shim "^1.2.15" + sdp "^2.12.0" + websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"