1
1
<script lang="ts" setup>
2
- import { binaryToBlock , createDecoder } from ' ~~/utils/lt-code'
2
+ import { binaryToBlock , ContentType , createDecoder } from ' ~~/utils/lt-code'
3
3
import { toUint8Array } from ' js-base64'
4
4
import { scan } from ' qr-scanner-wechat'
5
5
import { useBytesRate } from ' ~/composables/timeseries'
@@ -91,6 +91,7 @@ onMounted(async () => {
91
91
}
92
92
catch (e ) {
93
93
error .value = e
94
+ console .error (e )
94
95
}
95
96
},
96
97
() => props .speed ,
@@ -124,6 +125,8 @@ async function connectCamera() {
124
125
video .value ! .play ()
125
126
}
126
127
catch (e ) {
128
+ console .error (e )
129
+
127
130
if ((e as Error ).name === ' NotAllowedError' || (e as Error ).name === ' NotFoundError' ) {
128
131
cameraSignalStatus .value = CameraSignalStatus .NotGranted
129
132
return
@@ -134,9 +137,11 @@ async function connectCamera() {
134
137
}
135
138
136
139
const decoder = ref (createDecoder ())
140
+
137
141
const k = ref (0 )
138
142
const bytes = ref (0 )
139
143
const checksum = ref (0 )
144
+
140
145
const cached = new Set <string >()
141
146
const startTime = ref (0 )
142
147
const endTime = ref (0 )
@@ -147,6 +152,10 @@ const status = ref<number[]>([])
147
152
const decodedBlocks = computed (() => status .value .filter (i => i === 1 ).length )
148
153
const receivedBytes = computed (() => decoder .value .encodedCount * (decoder .value .meta ?.data .length ?? 0 ))
149
154
155
+ const filename = ref <string | undefined >()
156
+ const contentType = ref <string | undefined >()
157
+ const textContent = ref <string | undefined >()
158
+
150
159
function getStatus() {
151
160
const array = Array .from ({ length: k .value }, () => 0 )
152
161
for (let i = 0 ; i < k .value ; i ++ ) {
@@ -180,6 +189,49 @@ function pluse(index: number) {
180
189
el .style .filter = ' none'
181
190
}
182
191
192
+ /**
193
+ * Proposed ideal processing method for decoded data from LT codes
194
+ *
195
+ * @param data - The decoded data from LT codes
196
+ * @param type - The content type of the merged data, specified when encoding
197
+ */
198
+ function toData(data : Uint8Array , type : ContentType ): Uint8Array | string | any {
199
+ // Binary data, no need to process
200
+ if (type === ContentType .Binary ) {
201
+ return data
202
+ }
203
+ // Text data, decode and return
204
+ else if (type === ContentType .Text ) {
205
+ return new TextDecoder ().decode (data )
206
+ }
207
+ // Base64 encoded JSON data, decode and return
208
+ else {
209
+ const decodedFromBase64 = toUint8Array (new TextDecoder ().decode (data ))
210
+ const decodedJSONBodyStr = new TextDecoder ().decode (decodedFromBase64 )
211
+ const decodedJSONBody = JSON .parse (decodedJSONBodyStr )
212
+ return decodedJSONBody
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Proposed ideal method to convert data to a data URL
218
+ *
219
+ * @param data - The data to convert
220
+ * @param type - The content type of the data
221
+ */
222
+ function toDataURL(data : Uint8Array | string | any , type : ContentType ): string {
223
+ if (type === ContentType .Binary ) {
224
+ return URL .createObjectURL (new Blob ([data ], { type: ' application/octet-stream' }))
225
+ }
226
+ else if (type === ContentType .Text ) {
227
+ return URL .createObjectURL (new Blob ([new TextEncoder ().encode (data )], { type: ' text/plain' }))
228
+ }
229
+ else {
230
+ const json = JSON .stringify (data )
231
+ return URL .createObjectURL (new Blob ([new TextEncoder ().encode (json )], { type: ' application/json' }))
232
+ }
233
+ }
234
+
183
235
async function scanFrame() {
184
236
if (cameraSignalStatus .value === CameraSignalStatus .NotGranted
185
237
|| cameraSignalStatus .value === CameraSignalStatus .NotSupported ) {
@@ -231,13 +283,36 @@ async function scanFrame() {
231
283
232
284
cached .add (result .text )
233
285
k .value = data .k
286
+
234
287
data .indices .map (i => pluse (i ))
235
288
const success = decoder .value .addBlock (data )
236
289
status .value = getStatus ()
237
290
if (success ) {
238
291
endTime .value = performance .now ()
292
+
239
293
const merged = decoder .value .getDecoded ()!
240
- dataUrl .value = URL .createObjectURL (new Blob ([merged ], { type: ' application/octet-stream' }))
294
+
295
+ const mergedData = toData (merged , data .contentType )
296
+ dataUrl .value = toDataURL (mergedData , data .contentType )
297
+
298
+ if (data .contentType === ContentType .Text ) {
299
+ textContent .value = mergedData
300
+ }
301
+ if (data .contentType === ContentType .JSON ) {
302
+ const jsonBody = mergedData as unknown as {
303
+ filename: string
304
+ contentType: string
305
+ content: string
306
+ }
307
+
308
+ filename .value = jsonBody .filename
309
+ contentType .value = jsonBody .contentType
310
+
311
+ const payloadData = toUint8Array (jsonBody .content )
312
+ if (contentType .value .startsWith (' text/' )) {
313
+ textContent .value = new TextDecoder ().decode (payloadData )
314
+ }
315
+ }
241
316
}
242
317
// console.log({ data })
243
318
// if (Array.isArray(data)) {
@@ -289,6 +364,8 @@ function now() {
289
364
290
365
<Collapsable >
291
366
<p w-full of-x-auto ws-nowrap px2 py1 font-mono :class =" endTime ? 'text-green' : ''" >
367
+ <span >Filename: {{ filename }}</span ><br >
368
+ <span >Content-Type: {{ contentType }}</span ><br >
292
369
<span >Checksum: {{ checksum }}</span ><br >
293
370
<span >Indices: {{ k }}</span ><br >
294
371
<span >Decoded: {{ decodedBlocks }}</span ><br >
@@ -322,12 +399,17 @@ function now() {
322
399
323
400
<Collapsable v-if =" dataUrl" label =" Download" :default =" true" >
324
401
<div flex =" ~ col gap-2" max-w-150 p2 >
325
- <img :src =" dataUrl" >
402
+ <img v-if =" contentType?.startsWith('image/')" :src =" dataUrl" >
403
+ <p v-if =" contentType?.startsWith('text/')" :src =" dataUrl" >
404
+ {{ textContent }}
405
+ </p >
326
406
<a
327
- class =" w-max border border-gray:50 rounded-md px2 py1 text-sm hover:bg-gray:10"
328
407
:href =" dataUrl"
329
- download =" foo.png"
330
- >Download</a >
408
+ :download =" filename"
409
+ class =" w-max border border-gray:50 rounded-md px2 py1 text-sm hover:bg-gray:10"
410
+ >
411
+ Download
412
+ </a >
331
413
</div >
332
414
</Collapsable >
333
415
0 commit comments