@@ -9,14 +9,20 @@ import { DeviceModelToTypes, DeviceUploadResourceParams } from '../../types';
99import { BaseMethod } from '../BaseMethod' ;
1010import { validateParams } from '../helpers/paramsValidator' ;
1111import { hexToBytes } from '../helpers/hexUtils' ;
12- import { createUiMessage , UI_REQUEST } from '../../events' ;
1312import { getDeviceType , getDeviceFirmwareVersion } from '../../utils' ;
1413import { PROTO } from '../../constants' ;
1514
1615export default class DeviceUploadResource extends BaseMethod < ResourceUpload > {
1716 paramsData = {
1817 data : new Uint8Array ( ) ,
1918 thumbnailData : new Uint8Array ( ) ,
19+ blurData : new Uint8Array ( ) ,
20+ } ;
21+
22+ private uploadProgress = {
23+ totalBytes : 0 ,
24+ uploadedBytes : 0 ,
25+ currentFile : 'main' as 'main' | 'thumbnail' | 'blur' ,
2026 } ;
2127
2228 getVersionRange ( ) {
@@ -52,20 +58,28 @@ export default class DeviceUploadResource extends BaseMethod<ResourceUpload> {
5258 { name : 'suffix' , type : 'string' , required : true } ,
5359 { name : 'dataHex' , type : 'string' , required : true } ,
5460 { name : 'thumbnailDataHex' , type : 'string' , required : true } ,
61+ { name : 'blurDataHex' , type : 'hexString' , required : true } ,
5562 { name : 'resType' , type : 'number' , required : true } ,
5663 { name : 'nftMetaData' , type : 'string' } ,
5764 { name : 'fileNameNoExt' , type : 'string' } ,
5865 ] ) ;
5966
60- const { suffix, dataHex, thumbnailDataHex, resType, nftMetaData } = this
67+ const { suffix, dataHex, thumbnailDataHex, blurDataHex , resType, nftMetaData } = this
6168 . payload as DeviceUploadResourceParams ;
6269
6370 // init params
6471 this . paramsData = {
65- data : hexToBytes ( dataHex ) ,
66- thumbnailData : hexToBytes ( thumbnailDataHex ) ,
72+ data : new Uint8Array ( hexToBytes ( dataHex ) ) ,
73+ thumbnailData : new Uint8Array ( hexToBytes ( thumbnailDataHex ) ) ,
74+ blurData : new Uint8Array ( hexToBytes ( blurDataHex ) ) ,
6775 } ;
6876
77+ this . uploadProgress . totalBytes =
78+ this . paramsData . data . byteLength +
79+ this . paramsData . thumbnailData . byteLength +
80+ this . paramsData . blurData . byteLength ;
81+ this . uploadProgress . uploadedBytes = 0 ;
82+
6983 const fileHash = bytesToHex ( blake2s ( this . payload . dataHex ) ) . slice ( 0 , 8 ) ;
7084 const file_name_no_ext = isEmpty ( this . payload . fileNameNoExt )
7185 ? `${ resType === 0 ? 'wp' : 'nft' } -${ fileHash } -${ Math . floor ( Date . now ( ) / 1000 ) } `
@@ -75,48 +89,86 @@ export default class DeviceUploadResource extends BaseMethod<ResourceUpload> {
7589 extension : suffix ,
7690 data_length : this . paramsData . data . byteLength ,
7791 zoom_data_length : this . paramsData . thumbnailData . byteLength ,
92+ blur_data_length : this . paramsData . blurData . byteLength ,
7893 res_type : resType ,
7994 nft_meta_data : nftMetaData ,
8095 file_name_no_ext,
8196 } ;
8297 }
8398
99+ private getDataChunk ( sourceData : Uint8Array , offset : number , length : number ) : Uint8Array {
100+ const endOffset = Math . min ( offset + length , sourceData . byteLength ) ;
101+
102+ return sourceData . subarray ( offset , endOffset ) ;
103+ }
104+
105+ private updateProgress ( chunkSize : number , requestType : string ) {
106+ this . uploadProgress . uploadedBytes += chunkSize ;
107+
108+ if ( requestType === 'ResourceRequest' ) {
109+ this . uploadProgress . currentFile = 'main' ;
110+ } else if ( requestType === 'ZoomRequest' ) {
111+ this . uploadProgress . currentFile = 'thumbnail' ;
112+ } else {
113+ this . uploadProgress . currentFile = 'blur' ;
114+ }
115+
116+ const progress = Math . round (
117+ ( this . uploadProgress . uploadedBytes / this . uploadProgress . totalBytes ) * 100
118+ ) ;
119+
120+ if ( process . env . NODE_ENV === 'development' ) {
121+ console . log ( `Upload progress: ${ progress } % (${ this . uploadProgress . currentFile } )` ) ;
122+ }
123+ }
124+
84125 processResourceRequest = async (
85126 res :
86127 | TypedResponseMessage < 'ResourceRequest' >
87128 | TypedResponseMessage < 'ZoomRequest' >
129+ | TypedResponseMessage < 'BlurRequest' >
88130 | TypedResponseMessage < 'Success' >
89131 ) : Promise < Success > => {
90132 if ( res . type === 'Success' ) {
91133 return res . message ;
92134 }
93135
94136 const { offset, data_length } = res . message ;
95- const { data, thumbnailData } = this . paramsData ;
137+ const { data, thumbnailData, blurData } = this . paramsData ;
96138
97139 if ( offset === undefined ) {
98140 throw new Error ( 'offset is undefined' ) ;
99141 }
100142
101- let payload : Uint8Array ;
102- if ( res . type === 'ResourceRequest' ) {
103- payload = new Uint8Array ( data . slice ( offset , Math . min ( offset + data_length , data . byteLength ) ) ) ;
104- } else {
105- payload = new Uint8Array (
106- thumbnailData . slice ( offset , Math . min ( offset + data_length , thumbnailData . byteLength ) )
107- ) ;
143+ let sourceData : Uint8Array ;
144+
145+ switch ( res . type ) {
146+ case 'ResourceRequest' :
147+ sourceData = data ;
148+ break ;
149+ case 'BlurRequest' :
150+ sourceData = blurData ;
151+ break ;
152+ case 'ZoomRequest' :
153+ sourceData = thumbnailData ;
154+ break ;
155+ default :
156+ throw new Error ( 'Invalid request type' ) ;
108157 }
109158
159+ const payload = this . getDataChunk ( sourceData , offset , data_length ) ;
110160 const digest = blake2s ( payload ) ;
111161
162+ this . updateProgress ( payload . byteLength , res . type ) ;
163+
112164 const resourceAckParams = {
113165 data_chunk : bytesToHex ( payload ) ,
114166 hash : bytesToHex ( digest ) ,
115167 } ;
116168
117169 const response = await this . device . commands . typedCall (
118170 'ResourceAck' ,
119- [ 'ResourceRequest' , 'ZoomRequest' , 'Success' ] ,
171+ [ 'ResourceRequest' , 'ZoomRequest' , 'BlurRequest' , ' Success'] ,
120172 resourceAckParams
121173 ) ;
122174 return this . processResourceRequest ( response ) ;
@@ -129,12 +181,10 @@ export default class DeviceUploadResource extends BaseMethod<ResourceUpload> {
129181
130182 const res = await this . device . commands . typedCall (
131183 'ResourceUpload' ,
132- [ 'ResourceRequest' , 'ZoomRequest' , 'Success' ] ,
184+ [ 'ResourceRequest' , 'ZoomRequest' , 'BlurRequest' , ' Success'] ,
133185 this . params
134186 ) ;
135187
136- this . postMessage ( createUiMessage ( UI_REQUEST . CLOSE_UI_WINDOW ) ) ;
137-
138188 return this . processResourceRequest ( res ) ;
139189 }
140190}
0 commit comments