Skip to content

Commit 83e8f38

Browse files
committed
support JSON based restore
1 parent aeb548b commit 83e8f38

File tree

4 files changed

+49
-23
lines changed

4 files changed

+49
-23
lines changed

code/client/src/components/Common.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,17 @@ export const getDataFromFile = file =>
109109
reader.addEventListener('error', () => reject(reader.error))
110110
reader.readAsArrayBuffer(file)
111111
})
112+
113+
export const getTextFromFile = file =>
114+
new Promise((resolve, reject) => {
115+
const reader = new FileReader()
116+
reader.addEventListener('load', () => resolve(reader.result))
117+
reader.addEventListener('error', () => reject(reader.error))
118+
reader.readAsText(file)
119+
})
120+
121+
export const getDataURLFromFile = (img) => new Promise((resolve) => {
122+
const reader = new FileReader()
123+
reader.addEventListener('load', () => resolve(reader.result))
124+
reader.readAsDataURL(img)
125+
})

code/client/src/components/QrCodeScanner.jsx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useWindowDimensions } from '../util'
99
import LoadingOutlined from '@ant-design/icons/LoadingOutlined'
1010
import UploadOutlined from '@ant-design/icons/UploadOutlined'
1111
import jsQR from 'jsqr'
12+
import { getDataURLFromFile, getTextFromFile } from './Common'
1213

1314
const QrCodeScanner = ({ onScan, shouldInit, style }) => {
1415
const ref = useRef()
@@ -78,37 +79,45 @@ const QrCodeScanner = ({ onScan, shouldInit, style }) => {
7879
image.src = uri
7980
})
8081

81-
const getBase64 = (img) => new Promise((resolve) => {
82-
const reader = new FileReader()
83-
reader.addEventListener('load', () => resolve(reader.result))
84-
reader.readAsDataURL(img)
85-
})
86-
8782
const onQrcodeChange = async (info) => {
8883
if (info.file.status === 'uploading') {
8984
setQrCodeImageUploading(true)
9085
}
9186

9287
if (info.file.status === 'done') {
93-
const imageUri = await getBase64(info.file.originFileObj)
94-
const imageData = await convertURIToImageData(imageUri)
95-
const qrCode = jsQR(imageData.data, imageData.width, imageData.height)
96-
if (!qrCode) {
97-
message.error('Fail to read the uploaded image.', 15)
88+
try {
89+
if (info.file?.name?.endsWith('.json')) {
90+
const jsonData = await getTextFromFile(info.file.originFileObj)
91+
message.debug(jsonData)
92+
const parsed = JSON.parse(jsonData)
93+
onScan(parsed, true)
94+
return
95+
}
96+
const imageUri = await getDataURLFromFile(info.file.originFileObj)
97+
const imageData = await convertURIToImageData(imageUri)
98+
const qrCode = jsQR(imageData.data, imageData.width, imageData.height)
99+
if (!qrCode) {
100+
message.error('Fail to read the uploaded image.', 15)
101+
return
102+
}
103+
onScan(qrCode.data)
104+
} catch (ex) {
105+
console.error(ex)
106+
message.error('An error occurred while parsing the QR Code image. Please contact 1wallet developer')
107+
} finally {
98108
setQrCodeImageUploading(false)
99-
return
100109
}
101-
onScan(qrCode.data)
102-
setQrCodeImageUploading(false)
103110
}
104111
}
105112

106113
const beforeUpload = (file) => {
107114
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
108-
if (!isJpgOrPng) {
109-
message.error('You can only upload JPG/PNG file')
115+
const isJson = file.type === 'application/json'
116+
// message.debug(`File type: ${file.type}`)
117+
if (!isJpgOrPng && !isJson) {
118+
message.error('You can only upload JSON or JPG/PNG file')
110119
}
111-
return isJpgOrPng
120+
return isJpgOrPng || isJson
112121
}
113122

114123
return (
@@ -151,7 +160,7 @@ const QrCodeScanner = ({ onScan, shouldInit, style }) => {
151160
beforeUpload={beforeUpload}
152161
onChange={onQrcodeChange}
153162
>
154-
<Button shape='round' icon={qrCodeImageUploading ? <LoadingOutlined /> : <UploadOutlined />}>Use Image Instead</Button>
163+
<Button shape='round' icon={qrCodeImageUploading ? <LoadingOutlined /> : <UploadOutlined />}>Use Image or JSON Instead</Button>
155164
</Upload>
156165
</Row>
157166
</>

code/client/src/pages/Restore/RestoreByScan.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ const RestoreByScan = ({ isActive, onComplete, onCancel }) => {
8989
f()
9090
}, [addressInput])
9191

92-
const onScan = async (e) => {
92+
const onScan = async (e, isJson) => {
9393
if (e && !secret) {
9494
const now = performance.now()
9595
if (!(now - control.lastScan > config.scanDelay)) {
@@ -98,7 +98,9 @@ const RestoreByScan = ({ isActive, onComplete, onCancel }) => {
9898
control.lastScan = now
9999
try {
100100
let parsed
101-
if (e.startsWith('otpauth://totp')) {
101+
if (isJson) {
102+
parsed = e
103+
} else if (e.startsWith('otpauth://totp')) {
102104
parsed = parseOAuthOTP(e)
103105
} else {
104106
parsed = parseMigrationPayload(e)

code/client/src/pages/Show/Extend.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,16 +348,17 @@ const Extend = ({
348348
}
349349
}, [method])
350350

351-
const onScan = (e) => {
351+
const onScan = (e, isJson) => {
352352
if (e && !seed) {
353353
try {
354354
let parsed
355-
if (e.startsWith('otpauth://totp')) {
355+
if (isJson) {
356+
parsed = e
357+
} if (e.startsWith('otpauth://totp')) {
356358
parsed = parseOAuthOTP(e)
357359
} else {
358360
parsed = parseMigrationPayload(e)
359361
}
360-
361362
if (!parsed) {
362363
return
363364
}

0 commit comments

Comments
 (0)