@onekeyfe/hd-core 1.2.0-alpha.120 → 1.2.0-alpha.122

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,7 +77,7 @@ describe('DeviceSettings protocol routing', () => {
77
77
  expect(method.unlockPolicy).toBe('unlock-before-run');
78
78
  });
79
79
 
80
- it('uses ApplySettings and refreshes Protocol V1 settings from the device', async () => {
80
+ it('uses ApplySettings and commits the confirmed patch for Protocol V1', async () => {
81
81
  const { device, typedCall, updateState } = createDevice({ protocol: 'V1' });
82
82
  const method = new DeviceSettings({
83
83
  id: 1,
@@ -107,8 +107,13 @@ describe('DeviceSettings protocol routing', () => {
107
107
  use_ble: true,
108
108
  haptic_feedback: undefined,
109
109
  });
110
- expect(device.getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
111
- expect(updateState).not.toHaveBeenCalled();
110
+ expect(updateState).toHaveBeenCalledWith(
111
+ {
112
+ identity: { label: 'Shared Label' },
113
+ settings: { language: 'ja', bleEnabled: true },
114
+ },
115
+ 'settings-write'
116
+ );
112
117
  });
113
118
 
114
119
  it('normalizes legacy Protocol V1 never values before ApplySettings', async () => {
@@ -133,33 +138,15 @@ describe('DeviceSettings protocol routing', () => {
133
138
  auto_shutdown_delay_ms: DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
134
139
  })
135
140
  );
136
- expect(device.getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
137
- expect(updateState).not.toHaveBeenCalled();
138
- });
139
-
140
- it('refreshes Protocol V1 settings after the on-device brightness update completes', async () => {
141
- const { device, typedCall, updateState, getDeviceState } = createDevice({ protocol: 'V1' });
142
- const method = new DeviceSettings({
143
- id: 3,
144
- payload: {
145
- method: 'deviceSettings',
146
- changeBrightness: true,
141
+ expect(updateState).toHaveBeenCalledWith(
142
+ {
143
+ settings: {
144
+ autoLockDelayMs: DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
145
+ autoShutdownDelayMs: DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
146
+ },
147
147
  },
148
- });
149
- method.init();
150
- (method as any).device = device;
151
-
152
- await expect(method.run()).resolves.toEqual({ message: 'Success' });
153
- expect(typedCall).toHaveBeenCalledWith(
154
- 'ApplySettings',
155
- 'Success',
156
- expect.objectContaining({ change_brightness: true })
157
- );
158
- expect(getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
159
- expect(typedCall.mock.invocationCallOrder[0]).toBeLessThan(
160
- getDeviceState.mock.invocationCallOrder[0]
148
+ 'settings-write'
161
149
  );
162
- expect(updateState).not.toHaveBeenCalled();
163
150
  });
164
151
 
165
152
  it('uses DeviceSettingsSet and reloads Protocol V2 status and settings from the device', async () => {
@@ -338,7 +325,7 @@ describe('DeviceSettings protocol routing', () => {
338
325
  'Success',
339
326
  expect.objectContaining({ use_passphrase: true })
340
327
  );
341
- expect(getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
328
+ expect(getDeviceState).not.toHaveBeenCalled();
342
329
  });
343
330
 
344
331
  it('rejects combining a Pro2 device-side toggle with direct settings', async () => {
@@ -203,6 +203,69 @@ describe.each([
203
203
  });
204
204
  });
205
205
 
206
+ describe('FirmwareUpdateV2 WebUSB bootloader polling', () => {
207
+ beforeEach(() => {
208
+ jest.useFakeTimers({ doNotFake: ['setImmediate', 'performance'] });
209
+ });
210
+
211
+ afterEach(() => {
212
+ jest.clearAllTimers();
213
+ jest.useRealTimers();
214
+ jest.restoreAllMocks();
215
+ });
216
+
217
+ test('skips interval ticks while a bootloader probe is in flight and resumes afterward', async () => {
218
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('desktop' as never);
219
+ jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(false);
220
+ jest.spyOn(DataManager, 'isBrowserWebUsb').mockReturnValue(false);
221
+
222
+ const method = new FirmwareUpdateV2({
223
+ id: 1,
224
+ payload: { method: 'firmwareUpdateV2', connectId: WEBUSB_ID },
225
+ });
226
+
227
+ let inFlight = 0;
228
+ let maxInFlight = 0;
229
+ const resolveProbes: Array<(found: boolean) => void> = [];
230
+ const probe = jest.spyOn(method as any, '_checkDeviceInBootloaderMode').mockImplementation(
231
+ () =>
232
+ new Promise<boolean>(resolve => {
233
+ inFlight += 1;
234
+ maxInFlight = Math.max(maxInFlight, inFlight);
235
+ resolveProbes.push(found => {
236
+ inFlight -= 1;
237
+ resolve(found);
238
+ });
239
+ })
240
+ );
241
+
242
+ method.device = {
243
+ getCurrentDeviceType: jest.fn(() => EDeviceType.Classic),
244
+ } as unknown as Device;
245
+
246
+ method.checkDeviceToBootloader(WEBUSB_ID);
247
+
248
+ for (let elapsed = 0; elapsed < 6500; elapsed += 500) {
249
+ jest.advanceTimersByTime(500);
250
+ // eslint-disable-next-line no-await-in-loop
251
+ await flush();
252
+ }
253
+
254
+ expect(probe).toHaveBeenCalled();
255
+ expect(maxInFlight).toBe(1);
256
+
257
+ resolveProbes[0]?.(false);
258
+ await flush();
259
+ jest.advanceTimersByTime(2000);
260
+ await flush();
261
+
262
+ expect(probe).toHaveBeenCalledTimes(2);
263
+ expect(maxInFlight).toBe(1);
264
+ resolveProbes[1]?.(false);
265
+ await flush();
266
+ });
267
+ });
268
+
206
269
  describe.each([
207
270
  [
208
271
  'FirmwareUpdateV2',
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA2B1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;IAiGJ,cAAc,YAAa,MAAM,UAS/B;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YAwJvC,4BAA4B;IAyB1C,qBAAqB;IAUrB,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAc1C,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,YAAY,EAAE,aAAa;IAwBtF,GAAG;CAkRV"}
1
+ {"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA2B1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;IAiGJ,cAAc,YAAa,MAAM,UAS/B;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YA2JvC,4BAA4B;IAyB1C,qBAAqB;IAUrB,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAc1C,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,YAAY,EAAE,aAAa;IAwBtF,GAAG;CAkRV"}
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceSettings.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceSettings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAa3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA0D5D,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU,CAAC,aAAa,CAAC;IACnE,qBAAqB;IAIrB,IAAI;IA0EJ,eAAe;;;;;;;IAWT,GAAG;CAyIV"}
1
+ {"version":3,"file":"DeviceSettings.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceSettings.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAgB3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA0D5D,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU,CAAC,aAAa,CAAC;IACnE,qBAAqB;IAIrB,IAAI;IA0EJ,eAAe;;;;;;;IAWT,GAAG;CAyIV"}
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceUploadResource.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUploadResource.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,OAAO,KAAK,EAA8B,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,UAAU,CAAC,cAAc,CAAC;IAC1E,UAAU;;;;MAIR;IAEF,OAAO,CAAC,cAAc,CAIpB;IAEF,eAAe;;;;;IAQf,qBAAqB;IAgBrB,IAAI;IA+CJ,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAoBtB,sBAAsB,QAEhB,qBAAqB,iBAAiB,CAAC,GACvC,qBAAqB,aAAa,CAAC,GACnC,qBAAqB,aAAa,CAAC,GACnC,qBAAqB,SAAS,CAAC,KAClC,QAAQ,4BAA4B,CAAC,CAuDtC;IAEI,GAAG;CAiBV"}
1
+ {"version":3,"file":"DeviceUploadResource.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUploadResource.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,OAAO,KAAK,EAA8B,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,UAAU,CAAC,cAAc,CAAC;IAC1E,UAAU;;;;MAIR;IAEF,OAAO,CAAC,cAAc,CAIpB;IAEF,eAAe;;;;;IAQf,qBAAqB;IAgBrB,IAAI;IA+CJ,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAoBtB,sBAAsB,QAEhB,qBAAqB,iBAAiB,CAAC,GACvC,qBAAqB,aAAa,CAAC,GACnC,qBAAqB,aAAa,CAAC,GACnC,qBAAqB,SAAS,CAAC,KAClC,QAAQ,4BAA4B,CAAC,CAuDtC;IAEI,GAAG;CAaV"}
package/dist/index.js CHANGED
@@ -44617,6 +44617,22 @@ const mapProtocolV2DeviceStatusToState = (status) => {
44617
44617
  raw: { protocolV2DeviceStatus: status },
44618
44618
  });
44619
44619
  };
44620
+ const mapApplySettingsToState = (settings) => {
44621
+ const identity = definedEntries({ label: settings.label });
44622
+ const status = definedEntries({ passphraseProtection: settings.use_passphrase });
44623
+ const stateSettings = definedEntries({
44624
+ language: settings.language,
44625
+ autoLockDelayMs: settings.auto_lock_delay_ms,
44626
+ autoShutdownDelayMs: settings.auto_shutdown_delay_ms,
44627
+ displayRotation: settings.display_rotation,
44628
+ passphraseAlwaysOnDevice: settings.passphrase_always_on_device,
44629
+ safetyChecks: normalizeSafetyCheckLevel(settings.safety_checks),
44630
+ experimentalFeatures: settings.experimental_features,
44631
+ hapticFeedback: settings.haptic_feedback,
44632
+ bleEnabled: settings.use_ble,
44633
+ });
44634
+ return Object.assign(Object.assign(Object.assign({}, (Object.keys(identity).length ? { identity } : {})), (Object.keys(status).length ? { status } : {})), (Object.keys(stateSettings).length ? { settings: stateSettings } : {}));
44635
+ };
44620
44636
  const mapDeviceSettingsToState = (settings) => {
44621
44637
  const identity = definedEntries({ label: settings.label });
44622
44638
  const status = definedEntries({ passphraseProtection: settings.passphrase_enable });
@@ -48503,7 +48519,7 @@ class DeviceSettings extends BaseMethod {
48503
48519
  }
48504
48520
  const protocolV1Params = Object.assign(Object.assign({}, this.params), { auto_lock_delay_ms: normalizeProtocolV1DelayMs(this.params.auto_lock_delay_ms), auto_shutdown_delay_ms: normalizeProtocolV1DelayMs(this.params.auto_shutdown_delay_ms) });
48505
48521
  const res = yield this.device.commands.typedCall('ApplySettings', 'Success', protocolV1Params);
48506
- yield this.device.getDeviceState({ refreshSections: ['settings'] });
48522
+ this.device.updateState(mapApplySettingsToState(protocolV1Params), 'settings-write');
48507
48523
  return res.message;
48508
48524
  }
48509
48525
  catch (error) {
@@ -48702,11 +48718,7 @@ class DeviceUploadResource extends BaseMethod {
48702
48718
  this.checkUploadNFTSupport();
48703
48719
  }
48704
48720
  const res = yield this.device.commands.typedCall('ResourceUpload', ['ResourceRequest', 'ZoomRequest', 'BlurRequest', 'Success'], this.params);
48705
- const result = yield this.processResourceRequest(res);
48706
- if (this.payload.resType === hdTransport.Messages.ResourceType.WallPaper) {
48707
- yield this.device.getDeviceState({ refreshSections: ['settings'] });
48708
- }
48709
- return result;
48721
+ return this.processResourceRequest(res);
48710
48722
  });
48711
48723
  }
48712
48724
  }
@@ -50451,7 +50463,7 @@ class FirmwareUpdateV2 extends BaseMethod {
50451
50463
  this.checkPromise = hdShared.createDeferred();
50452
50464
  const env = DataManager.getSettings('env');
50453
50465
  const isBleReconnect = connectId && DataManager.isBleConnect(env);
50454
- let bleProbeInFlight = false;
50466
+ let probeInFlight = false;
50455
50467
  Log$8.log('FirmwareUpdateV2 [checkDeviceToBootloader] isBleReconnect: ', isBleReconnect);
50456
50468
  let isFirstCheck = true;
50457
50469
  let checkCount = 0;
@@ -50483,8 +50495,9 @@ class FirmwareUpdateV2 extends BaseMethod {
50483
50495
  let startPolling = () => undefined;
50484
50496
  const pollForBootloader = () => __awaiter(this, void 0, void 0, function* () {
50485
50497
  var _b, _c, _d, _e;
50486
- if (isFinished || isPromptingWebDevice)
50498
+ if (isFinished || isPromptingWebDevice || probeInFlight)
50487
50499
  return;
50500
+ probeInFlight = true;
50488
50501
  checkCount += 1;
50489
50502
  Log$8.log('FirmwareUpdateV2 [checkDeviceToBootloader] isFirstCheck: ', isFirstCheck);
50490
50503
  if (isTouchOrProDevice && isFirstCheck) {
@@ -50518,13 +50531,11 @@ class FirmwareUpdateV2 extends BaseMethod {
50518
50531
  }
50519
50532
  finally {
50520
50533
  isPromptingWebDevice = false;
50534
+ probeInFlight = false;
50521
50535
  }
50522
50536
  return;
50523
50537
  }
50524
50538
  if (isBleReconnect) {
50525
- if (bleProbeInFlight)
50526
- return;
50527
- bleProbeInFlight = true;
50528
50539
  try {
50529
50540
  yield ((_c = this.device.deviceConnector) === null || _c === void 0 ? void 0 : _c.acquire(this.device.originalDescriptor.id, null, true, (_d = this.payload.connectProtocol) !== null && _d !== void 0 ? _d : this.device.originalDescriptor.protocolType));
50530
50541
  yield this.device.initialize({ timeoutMs: BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS });
@@ -50538,11 +50549,16 @@ class FirmwareUpdateV2 extends BaseMethod {
50538
50549
  Log$8.log('catch Bluetooth error when device is restarting: ', e);
50539
50550
  }
50540
50551
  finally {
50541
- bleProbeInFlight = false;
50552
+ probeInFlight = false;
50542
50553
  }
50543
50554
  }
50544
50555
  else {
50545
- yield checkForBootloader(true);
50556
+ try {
50557
+ yield checkForBootloader(true);
50558
+ }
50559
+ finally {
50560
+ probeInFlight = false;
50561
+ }
50546
50562
  }
50547
50563
  });
50548
50564
  startPolling = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.120",
3
+ "version": "1.2.0-alpha.122",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.120",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.120",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.122",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.122",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "buffer": "^6.0.3",
@@ -46,5 +46,5 @@
46
46
  "@types/w3c-web-usb": "^1.0.10",
47
47
  "@types/web-bluetooth": "^0.0.21"
48
48
  },
49
- "gitHead": "8aaff2584cedc5fcb5dc68e0ca19588e9965bb8a"
49
+ "gitHead": "f0a85119fe7f8607768bc77b0ac4eb527d55e1cc"
50
50
  }
@@ -276,10 +276,9 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
276
276
  this.checkPromise = createDeferred();
277
277
  const env = DataManager.getSettings('env');
278
278
  const isBleReconnect = connectId && DataManager.isBleConnect(env);
279
- // Tracks the in-flight BLE probe so interval ticks never overlap: a superseded
280
- // Initialize left pending on the V1 transport is exactly what later times out
281
- // and used to tear down the connection mid-firmware-upload.
282
- let bleProbeInFlight = false;
279
+ // Bootloader probes can outlive the polling interval. Keep discovery and
280
+ // acquire serialized so concurrent ticks never race the same connection.
281
+ let probeInFlight = false;
283
282
 
284
283
  Log.log('FirmwareUpdateV2 [checkDeviceToBootloader] isBleReconnect: ', isBleReconnect);
285
284
 
@@ -321,7 +320,8 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
321
320
 
322
321
  let startPolling: () => void = () => undefined;
323
322
  const pollForBootloader = async () => {
324
- if (isFinished || isPromptingWebDevice) return;
323
+ if (isFinished || isPromptingWebDevice || probeInFlight) return;
324
+ probeInFlight = true;
325
325
  checkCount += 1;
326
326
  Log.log('FirmwareUpdateV2 [checkDeviceToBootloader] isFirstCheck: ', isFirstCheck);
327
327
  if (isTouchOrProDevice && isFirstCheck) {
@@ -362,13 +362,12 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
362
362
  this.checkPromise?.reject(e);
363
363
  } finally {
364
364
  isPromptingWebDevice = false;
365
+ probeInFlight = false;
365
366
  }
366
367
  return;
367
368
  }
368
369
 
369
370
  if (isBleReconnect) {
370
- if (bleProbeInFlight) return;
371
- bleProbeInFlight = true;
372
371
  try {
373
372
  await this.device.deviceConnector?.acquire(
374
373
  this.device.originalDescriptor.id,
@@ -389,10 +388,14 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
389
388
  // ignore error because of device is not connected
390
389
  Log.log('catch Bluetooth error when device is restarting: ', e);
391
390
  } finally {
392
- bleProbeInFlight = false;
391
+ probeInFlight = false;
393
392
  }
394
393
  } else {
395
- await checkForBootloader(true);
394
+ try {
395
+ await checkForBootloader(true);
396
+ } finally {
397
+ probeInFlight = false;
398
+ }
396
399
  }
397
400
  };
398
401
 
@@ -4,7 +4,10 @@ import { DeviceSessionPinType, DeviceSettingsPage } from '@onekeyfe/hd-transport
4
4
  import { BaseMethod } from '../BaseMethod';
5
5
  import { invalidParameter } from '../helpers/filesystemValidation';
6
6
  import { validateParams } from '../helpers/paramsValidator';
7
- import { mapCommonSettingsToProtocolV2 } from '../../device/DeviceStateMapper';
7
+ import {
8
+ mapApplySettingsToState,
9
+ mapCommonSettingsToProtocolV2,
10
+ } from '../../device/DeviceStateMapper';
8
11
  import { getProtocolV2SettingsBehavior } from '../../protocols/protocol-v2/settingsUnlockPolicy';
9
12
  import {
10
13
  DEVICE_SETTINGS_NEVER_TIMEOUT_MS,
@@ -268,7 +271,7 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
268
271
  'Success',
269
272
  protocolV1Params
270
273
  );
271
- await this.device.getDeviceState({ refreshSections: ['settings'] });
274
+ this.device.updateState(mapApplySettingsToState(protocolV1Params), 'settings-write');
272
275
  return res.message;
273
276
  } catch (error) {
274
277
  if (error.message?.toLowerCase().includes('no setting provided')) {
@@ -198,10 +198,6 @@ export default class DeviceUploadResource extends BaseMethod<ResourceUpload> {
198
198
  this.params
199
199
  );
200
200
 
201
- const result = await this.processResourceRequest(res);
202
- if (this.payload.resType === PROTO.ResourceType.WallPaper) {
203
- await this.device.getDeviceState({ refreshSections: ['settings'] });
204
- }
205
- return result;
201
+ return this.processResourceRequest(res);
206
202
  }
207
203
  }
@@ -1,53 +0,0 @@
1
- import { EDeviceType } from '@onekeyfe/hd-shared';
2
- import { ResourceType } from '@onekeyfe/hd-transport';
3
-
4
- import DeviceUploadResource from '../src/api/device/DeviceUploadResource';
5
-
6
- jest.mock('../src/data/config', () => ({
7
- DEFAULT_DOMAIN: 'https://example.com/',
8
- getSDKVersion: () => '0.0.0-test',
9
- }));
10
-
11
- describe('DeviceUploadResource state refresh', () => {
12
- it('refreshes Protocol V1 settings inside a wallpaper update', async () => {
13
- const typedCall = jest.fn().mockResolvedValue({
14
- type: 'Success',
15
- message: { message: 'Success' },
16
- });
17
- const getDeviceState = jest.fn().mockResolvedValue({
18
- settings: { language: 'en-US' },
19
- });
20
- const method = new DeviceUploadResource({
21
- id: 1,
22
- payload: {
23
- method: 'deviceUploadResource',
24
- suffix: 'jpg',
25
- dataHex: '00',
26
- thumbnailDataHex: '00',
27
- blurDataHex: '00',
28
- resType: ResourceType.WallPaper,
29
- },
30
- });
31
- method.init();
32
- (method as any).device = {
33
- commands: { typedCall },
34
- getCurrentDeviceType: () => EDeviceType.Pro,
35
- getCurrentFirmwareVersionString: () => '4.21.0',
36
- getDeviceState,
37
- };
38
-
39
- await expect(method.run()).resolves.toEqual({
40
- message: 'Success',
41
- applyScreen: false,
42
- });
43
- expect(typedCall).toHaveBeenCalledWith(
44
- 'ResourceUpload',
45
- ['ResourceRequest', 'ZoomRequest', 'BlurRequest', 'Success'],
46
- expect.objectContaining({ res_type: ResourceType.WallPaper })
47
- );
48
- expect(getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
49
- expect(typedCall.mock.invocationCallOrder[0]).toBeLessThan(
50
- getDeviceState.mock.invocationCallOrder[0]
51
- );
52
- });
53
- });