@nordicsemiconductor/pc-nrfconnect-shared 121.0.0 → 122.0.0

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.
Files changed (115) hide show
  1. package/Changelog.md +34 -0
  2. package/coverage/cobertura-coverage.xml +1330 -1197
  3. package/nrfutil/device/__mocks__/device.ts +2 -0
  4. package/nrfutil/device/batch.ts +18 -2
  5. package/nrfutil/device/common.ts +17 -38
  6. package/nrfutil/device/device.ts +2 -0
  7. package/nrfutil/device/deviceInfo.ts +70 -0
  8. package/nrfutil/device/erase.ts +2 -2
  9. package/nrfutil/device/firmwareRead.ts +2 -2
  10. package/nrfutil/device/getCoreInfo.ts +2 -2
  11. package/nrfutil/device/getFwInfo.ts +2 -2
  12. package/nrfutil/device/getProtectionStatus.ts +2 -2
  13. package/nrfutil/device/list.ts +4 -30
  14. package/nrfutil/device/program.ts +4 -4
  15. package/nrfutil/device/recover.ts +2 -2
  16. package/nrfutil/device/reset.ts +2 -2
  17. package/nrfutil/device/setMcuState.ts +2 -5
  18. package/nrfutil/device/setProtectionStatus.ts +2 -2
  19. package/nrfutil/index.ts +1 -1
  20. package/nrfutil/moduleVersion.ts +20 -0
  21. package/nrfutil/sandboxTypes.ts +14 -0
  22. package/package.json +1 -1
  23. package/src/About/DeviceCard.tsx +6 -5
  24. package/src/About/SupportCard.tsx +2 -2
  25. package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +12 -6
  26. package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +1 -1
  27. package/src/Device/DeviceSelector/DeviceList/Device.tsx +7 -5
  28. package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +23 -5
  29. package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +7 -6
  30. package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +26 -30
  31. package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +1 -2
  32. package/src/Device/DeviceSelector/DeviceSelector.test.tsx +17 -37
  33. package/src/Device/DeviceSelector/DeviceSelector.tsx +38 -13
  34. package/src/Device/DeviceSelector/Favorite.tsx +10 -10
  35. package/src/Device/DeviceSelector/basic-device-info.scss +0 -12
  36. package/src/Device/deviceInfo/deviceInfo.ts +2 -2
  37. package/src/Device/deviceLister.ts +52 -43
  38. package/src/Device/deviceSetup.ts +27 -10
  39. package/src/Device/deviceSlice.ts +148 -84
  40. package/src/Device/jprogOperations.ts +56 -27
  41. package/src/Device/sdfuOperations.ts +25 -31
  42. package/src/InlineInput/NumberInlineInput.tsx +1 -1
  43. package/src/InlineInput/NumberInputWithDropdown.tsx +1 -2
  44. package/src/index.ts +1 -0
  45. package/src/logging/sendInitialLogMessages.ts +13 -9
  46. package/src/utils/logLibVersions.ts +1 -1
  47. package/src/utils/systemReport.ts +3 -3
  48. package/typings/generated/nrfutil/device/__mocks__/device.d.ts +1 -0
  49. package/typings/generated/nrfutil/device/__mocks__/device.d.ts.map +1 -1
  50. package/typings/generated/nrfutil/device/batch.d.ts +3 -2
  51. package/typings/generated/nrfutil/device/batch.d.ts.map +1 -1
  52. package/typings/generated/nrfutil/device/common.d.ts +6 -33
  53. package/typings/generated/nrfutil/device/common.d.ts.map +1 -1
  54. package/typings/generated/nrfutil/device/device.d.ts +13 -12
  55. package/typings/generated/nrfutil/device/device.d.ts.map +1 -1
  56. package/typings/generated/nrfutil/device/deviceInfo.d.ts +40 -0
  57. package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -0
  58. package/typings/generated/nrfutil/device/erase.d.ts +2 -2
  59. package/typings/generated/nrfutil/device/erase.d.ts.map +1 -1
  60. package/typings/generated/nrfutil/device/firmwareRead.d.ts +2 -2
  61. package/typings/generated/nrfutil/device/firmwareRead.d.ts.map +1 -1
  62. package/typings/generated/nrfutil/device/getCoreInfo.d.ts +2 -2
  63. package/typings/generated/nrfutil/device/getCoreInfo.d.ts.map +1 -1
  64. package/typings/generated/nrfutil/device/getFwInfo.d.ts +2 -2
  65. package/typings/generated/nrfutil/device/getFwInfo.d.ts.map +1 -1
  66. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +2 -2
  67. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
  68. package/typings/generated/nrfutil/device/list.d.ts +3 -3
  69. package/typings/generated/nrfutil/device/list.d.ts.map +1 -1
  70. package/typings/generated/nrfutil/device/program.d.ts +2 -2
  71. package/typings/generated/nrfutil/device/program.d.ts.map +1 -1
  72. package/typings/generated/nrfutil/device/recover.d.ts +2 -2
  73. package/typings/generated/nrfutil/device/recover.d.ts.map +1 -1
  74. package/typings/generated/nrfutil/device/reset.d.ts +2 -2
  75. package/typings/generated/nrfutil/device/reset.d.ts.map +1 -1
  76. package/typings/generated/nrfutil/device/setMcuState.d.ts +2 -2
  77. package/typings/generated/nrfutil/device/setMcuState.d.ts.map +1 -1
  78. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts +2 -2
  79. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts.map +1 -1
  80. package/typings/generated/nrfutil/index.d.ts +2 -1
  81. package/typings/generated/nrfutil/index.d.ts.map +1 -1
  82. package/typings/generated/nrfutil/moduleVersion.d.ts +4 -0
  83. package/typings/generated/nrfutil/moduleVersion.d.ts.map +1 -1
  84. package/typings/generated/nrfutil/sandboxTypes.d.ts +9 -0
  85. package/typings/generated/nrfutil/sandboxTypes.d.ts.map +1 -1
  86. package/typings/generated/src/About/DeviceCard.d.ts.map +1 -1
  87. package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts.map +1 -1
  88. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +0 -1
  89. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts.map +1 -1
  90. package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts.map +1 -1
  91. package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts.map +1 -1
  92. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +0 -1
  93. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts.map +1 -1
  94. package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts.map +1 -1
  95. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +0 -1
  96. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts.map +1 -1
  97. package/typings/generated/src/Device/deviceLister.d.ts +1 -15
  98. package/typings/generated/src/Device/deviceLister.d.ts.map +1 -1
  99. package/typings/generated/src/Device/deviceSetup.d.ts +6 -5
  100. package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
  101. package/typings/generated/src/Device/deviceSlice.d.ts +12 -15
  102. package/typings/generated/src/Device/deviceSlice.d.ts.map +1 -1
  103. package/typings/generated/src/Device/jprogOperations.d.ts.map +1 -1
  104. package/typings/generated/src/Device/sdfuOperations.d.ts.map +1 -1
  105. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +1 -1
  106. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
  107. package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts.map +1 -1
  108. package/typings/generated/src/index.d.ts +1 -1
  109. package/typings/generated/src/index.d.ts.map +1 -1
  110. package/typings/generated/src/logging/sendInitialLogMessages.d.ts.map +1 -1
  111. package/typings/generated/src/utils/systemReport.d.ts +1 -1
  112. package/typings/generated/src/utils/systemReport.d.ts.map +1 -1
  113. package/src/Device/DeviceSelector/DeviceList/device.scss +0 -28
  114. package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +0 -33
  115. package/src/Device/DeviceSelector/favorite.scss +0 -17
@@ -28,13 +28,15 @@ interface Props {
28
28
  const DeviceName = ({ device, inputRef, messageType }: Props) => {
29
29
  const dispatch = useDispatch();
30
30
  const setOrResetNickname = (name: string) => {
31
+ if (!device.serialNumber) return;
32
+
31
33
  const newNameIsEqualToDefaultName =
32
34
  name === displayedDeviceName(device, { respectNickname: false });
33
35
 
34
36
  if (newNameIsEqualToDefaultName) {
35
- dispatch(resetDeviceNickname(device.serialNumber));
37
+ dispatch(resetDeviceNickname(device));
36
38
  } else {
37
- dispatch(setDeviceNickname(device.serialNumber, name));
39
+ dispatch(setDeviceNickname(device, name));
38
40
  }
39
41
  };
40
42
 
@@ -79,7 +81,9 @@ export default ({
79
81
  const autoReselectDevice = useSelector(getAutoReselectDevice);
80
82
  const waitingToAutoReselect = useSelector(getWaitingToAutoReselect);
81
83
  const waitingForDevice = useSelector(getWaitingForDeviceTimeout);
82
- const thisDevice = device.serialNumber === autoReselectDevice?.serialNumber;
84
+ const thisDevice =
85
+ device.serialNumber &&
86
+ device.serialNumber === autoReselectDevice?.serialNumber;
83
87
 
84
88
  useEffect(() => {
85
89
  if (!showWaitingStatus) {
@@ -99,9 +103,9 @@ export default ({
99
103
  ]);
100
104
 
101
105
  return (
102
- <div className="basic-device-info">
106
+ <div className="basic-device-info tw-h-[42px]">
103
107
  <DeviceIcon device={device} />
104
- <div className="details">
108
+ <div className="details tw-flex tw-flex-col">
105
109
  <DeviceName
106
110
  device={device}
107
111
  inputRef={deviceNameInputRef}
@@ -109,7 +113,9 @@ export default ({
109
113
  />
110
114
  <DeviceSerialNumber device={device} />
111
115
  </div>
112
- <div className="toggles">{toggles}</div>
116
+ <div className="tw-mr-2.5 tw-flex tw-h-full tw-w-11 tw-flex-col tw-items-center tw-justify-center">
117
+ {toggles}
118
+ </div>
113
119
  </div>
114
120
  );
115
121
  };
@@ -57,6 +57,6 @@ export const AnimatedItem: FC<{
57
57
  children: ReactNode;
58
58
  }> = ({ children, itemKey }) => (
59
59
  <Flipped flipId={itemKey} onAppear={fadeIn} onExit={fadeOut}>
60
- <li>{children}</li>
60
+ <li className="tw-group">{children}</li>
61
61
  </Flipped>
62
62
  );
@@ -14,8 +14,6 @@ import { FavoriteIndicator } from '../Favorite';
14
14
  import EditDeviceButtons from './EditDeviceButtons';
15
15
  import MoreDeviceInfo from './MoreDeviceInfo';
16
16
 
17
- import './device.scss';
18
-
19
17
  const ShowMoreInfo = ({
20
18
  isVisible,
21
19
  toggleVisible,
@@ -24,7 +22,10 @@ const ShowMoreInfo = ({
24
22
  toggleVisible: () => void;
25
23
  }) => (
26
24
  <PseudoButton
27
- className={`show-more mdi mdi-chevron-${isVisible ? 'up' : 'down'}`}
25
+ className={classNames(
26
+ isVisible ? 'tw-visible' : 'tw-invisible group-hover:tw-visible',
27
+ `mdi mdi-chevron-${isVisible ? 'up' : 'down'}`
28
+ )}
28
29
  testId="show-more-device-info"
29
30
  onClick={toggleVisible}
30
31
  />
@@ -52,8 +53,9 @@ export default ({ device, doSelectDevice, allowMoreInfoVisible }: Props) => {
52
53
  return (
53
54
  <PseudoButton
54
55
  className={classNames(
55
- 'device',
56
- moreVisible && 'more-infos-visible'
56
+ 'tw-flex tw-flex-col tw-gap-2 tw-py-3 tw-font-light group-hover:tw-bg-white',
57
+ moreVisible && 'tw-bg-white',
58
+ moreVisible && device.serialNumber && 'tw-pb-0'
57
59
  )}
58
60
  onClick={() => doSelectDevice(device, false)}
59
61
  >
@@ -11,7 +11,11 @@ import { Toggle } from '../../../Toggle/Toggle';
11
11
  import classNames from '../../../utils/classNames';
12
12
  import { getAutoReselect, setAutoReselect } from '../../deviceAutoSelectSlice';
13
13
  import { displayedDeviceName } from '../../deviceInfo/deviceInfo';
14
- import { Device as DeviceProps, getDevices } from '../../deviceSlice';
14
+ import {
15
+ Device as DeviceProps,
16
+ getDevices,
17
+ selectedDevice,
18
+ } from '../../deviceSlice';
15
19
  import { AnimatedItem, AnimatedList } from './AnimatedList';
16
20
  import BrokenDevice from './BrokenDevice';
17
21
  import Device from './Device';
@@ -40,7 +44,7 @@ const showAllDevices = () => true;
40
44
 
41
45
  const sorted = (devices: DeviceProps[]) =>
42
46
  [...devices].sort((a, b) => {
43
- if (a.favorite !== b.favorite) {
47
+ if (!!a.favorite !== !!b.favorite) {
44
48
  return a.favorite ? -1 : 1;
45
49
  }
46
50
 
@@ -60,6 +64,7 @@ const DeviceList: FC<Props> = ({
60
64
  const dispatch = useDispatch();
61
65
  const autoReconnect = useSelector(getAutoReselect);
62
66
  const devices = useSelector(getDevices);
67
+ const currentDevice = useSelector(selectedDevice);
63
68
 
64
69
  const sortedDevices = useMemo(
65
70
  () => sorted([...devices.values()]),
@@ -71,13 +76,26 @@ const DeviceList: FC<Props> = ({
71
76
  [deviceFilter, sortedDevices]
72
77
  );
73
78
 
79
+ const canUseAutoReconnect =
80
+ (!!currentDevice && !!currentDevice?.serialNumber) || !currentDevice;
81
+
74
82
  return (
75
83
  <div className={classNames('device-list', isVisible || 'hidden')}>
76
84
  <div className="global-auto-reconnect">
77
85
  <Toggle
78
86
  id="toggle-global-auto-reconnect"
79
87
  label="Auto Reconnect"
80
- isToggled={autoReconnect}
88
+ title={
89
+ !canUseAutoReconnect
90
+ ? 'Cannot auto reconnect to a device with no serial number'
91
+ : ''
92
+ }
93
+ disabled={!canUseAutoReconnect}
94
+ isToggled={
95
+ autoReconnect &&
96
+ ((!!currentDevice && !!currentDevice?.serialNumber) ||
97
+ !currentDevice)
98
+ }
81
99
  onToggle={value => {
82
100
  dispatch(setAutoReselect(value));
83
101
  }}
@@ -90,8 +108,8 @@ const DeviceList: FC<Props> = ({
90
108
  <AnimatedList devices={sortedDevices}>
91
109
  {filteredDevices.map(device => (
92
110
  <AnimatedItem
93
- key={device.serialNumber}
94
- itemKey={device.serialNumber}
111
+ key={device.id.toString()}
112
+ itemKey={device.id.toString()}
95
113
  >
96
114
  {device.traits.broken ? (
97
115
  <BrokenDevice device={device} />
@@ -18,11 +18,12 @@ interface Props {
18
18
  startEditingDeviceName: () => void;
19
19
  }
20
20
 
21
- const EditDeviceButtons: FC<Props> = ({ device, startEditingDeviceName }) => (
22
- <ButtonGroup className="edit-device-buttons">
23
- <MakeDeviceFavorite device={device} />
24
- <RenameDevice startEditingDeviceName={startEditingDeviceName} />
25
- </ButtonGroup>
26
- );
21
+ const EditDeviceButtons: FC<Props> = ({ device, startEditingDeviceName }) =>
22
+ device.serialNumber ? (
23
+ <ButtonGroup className="edit-device-buttons">
24
+ <MakeDeviceFavorite device={device} />
25
+ <RenameDevice startEditingDeviceName={startEditingDeviceName} />
26
+ </ButtonGroup>
27
+ ) : null;
27
28
 
28
29
  export default EditDeviceButtons;
@@ -10,56 +10,52 @@ import { SerialPort } from '../../../../nrfutil/device/common';
10
10
  import { displayedDeviceName } from '../../deviceInfo/deviceInfo';
11
11
  import { Device } from '../../deviceSlice';
12
12
 
13
- import './more-device-info.scss';
14
-
15
13
  const Row = ({ children }: { children: ReactNode }) => (
16
- <div className="info-row">
17
- <div className="flex-space" />
14
+ <div className=" tw-flex tw-flex-row tw-pr-5">
15
+ <div className=" tw-w-[68px]" />
18
16
  {children}
19
17
  </div>
20
18
  );
21
19
 
22
20
  const PcaNumber = ({ device }: { device: Device }) => {
23
- if (!device.jlink?.boardVersion) {
21
+ if (!device.devkit?.boardVersion) {
24
22
  return null;
25
23
  }
26
24
 
27
- return <div>{device.jlink.boardVersion}</div>;
25
+ return (
26
+ <Row>
27
+ <div>{device.devkit.boardVersion}</div>
28
+ </Row>
29
+ );
28
30
  };
29
31
 
30
32
  const MaybeDeviceName = ({ device }: { device: Device }) => {
31
- const hasNickname = device.nickname !== '';
32
- if (!hasNickname) {
33
+ if (!device.nickname) {
33
34
  return null;
34
35
  }
35
36
 
36
37
  return (
37
- <div className="name">
38
- {displayedDeviceName(device, { respectNickname: false })}
39
- </div>
38
+ <Row>
39
+ <div>{displayedDeviceName(device, { respectNickname: false })}</div>
40
+ </Row>
40
41
  );
41
42
  };
42
43
 
43
- const Serialports = ({ ports }: { ports: SerialPort[] }) => (
44
- <ul className="ports">
45
- {ports.map(port => (
46
- <li key={port.path}>{port.comName}</li>
47
- ))}
48
- </ul>
49
- );
50
-
51
- export default ({ device }: { device: Device }) => (
52
- <div className="more-infos">
44
+ const Serialports = ({ ports }: { ports: SerialPort[] }) =>
45
+ ports.length > 0 ? (
53
46
  <Row>
54
- <PcaNumber device={device} />
47
+ <ul className="tw-text-center tw-underline">
48
+ {ports.map(port => (
49
+ <li key={port.path}>{port.comName}</li>
50
+ ))}
51
+ </ul>
55
52
  </Row>
56
- <Row>
57
- <MaybeDeviceName device={device} />
58
- </Row>
59
- {device.serialPorts && (
60
- <Row>
61
- <Serialports ports={device.serialPorts} />
62
- </Row>
63
- )}
53
+ ) : null;
54
+
55
+ export default ({ device }: { device: Device }) => (
56
+ <div className="tw-preflight tw-flex tw-flex-col tw-gap-2">
57
+ <PcaNumber device={device} />
58
+ <MaybeDeviceName device={device} />
59
+ <Serialports ports={device.serialPorts ?? []} />
64
60
  </div>
65
61
  );
@@ -4,11 +4,10 @@
4
4
  * SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
5
5
  */
6
6
 
7
- @import "../../../variables";
7
+ @import '../../../variables';
8
8
 
9
9
  .core19-device-selector {
10
10
  .edit-device-buttons {
11
- margin-top: 10px;
12
11
  height: 35px;
13
12
 
14
13
  font-size: 11px;
@@ -14,18 +14,13 @@ import DeviceSelector from './DeviceSelector';
14
14
 
15
15
  jest.mock('../../../nrfutil/device/device');
16
16
 
17
+ const DEVICE_SERIAL_NUMBER = '000000001';
18
+
17
19
  const testDevice: Device = {
18
20
  id: 1,
19
- hwInfo: {
20
- romSize: 123,
21
- ramSize: 456,
22
- romPageSize: 789,
23
- deviceFamily: 'PCATest',
24
- deviceVersion: 'PCATest',
25
- },
26
21
  broken: null,
27
22
  usb: {
28
- serialNumber: '000000001',
23
+ serialNumber: DEVICE_SERIAL_NUMBER,
29
24
  manufacturer: 'testManufacturer',
30
25
  product: 'testProduct',
31
26
  osDevicePath: '/some-path',
@@ -66,26 +61,13 @@ const testDevice: Device = {
66
61
  vcom: 2,
67
62
  },
68
63
  ],
69
- boardVersion: 'PCATest',
70
- serialport: {
71
- path: 'COM1',
72
- manufacturer: 'testManufacturer',
73
- productId: 'testProduct',
74
- serialNumber: '000000001',
75
- vendorId: 'testVendor',
76
- comName: 'COM1',
77
- vcom: 0,
78
- },
79
64
  favorite: false,
80
65
  traits: {
81
66
  jlink: true,
82
67
  },
83
- jlink: {
68
+ devkit: {
84
69
  boardVersion: 'PCATest',
85
- serialNumber: 'PCATest',
86
- jlinkObFirmwareVersion: 'PCATest',
87
70
  deviceFamily: 'PCATest',
88
- deviceVersion: 'PCATest',
89
71
  },
90
72
  };
91
73
 
@@ -151,7 +133,7 @@ describe('DeviceSelector', () => {
151
133
  />,
152
134
  [addDevice(testDevice)]
153
135
  );
154
- expect(screen.getByText(testDevice.serialNumber)).toBeInTheDocument();
136
+ expect(screen.getByText(DEVICE_SERIAL_NUMBER)).toBeInTheDocument();
155
137
  });
156
138
 
157
139
  it('should unlist disconnected devices', () => {
@@ -166,7 +148,7 @@ describe('DeviceSelector', () => {
166
148
  />,
167
149
  [addDevice(testDevice), removeDevice(testDevice)]
168
150
  );
169
- expect(screen.queryByText(testDevice.serialNumber)).toBeNull();
151
+ expect(screen.queryByText(DEVICE_SERIAL_NUMBER)).toBeNull();
170
152
  });
171
153
 
172
154
  it('should show more device info when selecting the expand button', () => {
@@ -200,8 +182,8 @@ describe('DeviceSelector', () => {
200
182
  );
201
183
 
202
184
  fireEvent.click(screen.getByText('Select device'));
203
- fireEvent.click(screen.getByText(testDevice.serialNumber));
204
- expect(screen.getAllByText(testDevice.serialNumber)).toHaveLength(2);
185
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
186
+ expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2);
205
187
  });
206
188
 
207
189
  it('can deselect selected devices', async () => {
@@ -217,10 +199,10 @@ describe('DeviceSelector', () => {
217
199
  [addDevice(testDevice)]
218
200
  );
219
201
  fireEvent.click(screen.getByText('Select device'));
220
- fireEvent.click(screen.getByText(testDevice.serialNumber));
202
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
221
203
  await screen.findByTestId('disconnect-device');
222
204
  fireEvent.click(screen.getByTestId('disconnect-device'));
223
- expect(screen.getAllByText(testDevice.serialNumber)).toHaveLength(1);
205
+ expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1);
224
206
  expect(screen.getByText('Select device')).toBeInTheDocument();
225
207
  });
226
208
 
@@ -250,10 +232,10 @@ describe('DeviceSelector', () => {
250
232
  [addDevice(testDevice)]
251
233
  );
252
234
  fireEvent.click(screen.getByText('Select device'));
253
- fireEvent.click(screen.getByText(testDevice.serialNumber));
235
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
254
236
 
255
237
  expect(screen.queryByText('OK')).toBeNull();
256
- expect(screen.getAllByText(testDevice.serialNumber)).toHaveLength(2);
238
+ expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2);
257
239
  });
258
240
 
259
241
  it('should deselect device when custom devices are disabled and no valid firmware is defined', async () => {
@@ -283,13 +265,11 @@ describe('DeviceSelector', () => {
283
265
  );
284
266
 
285
267
  fireEvent.click(screen.getByText('Select device'));
286
- fireEvent.click(screen.getByText(testDevice.serialNumber));
268
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
287
269
 
288
270
  expect(screen.queryByText('OK')).toBeNull();
289
271
  await waitFor(() => {
290
- expect(screen.getAllByText(testDevice.serialNumber)).toHaveLength(
291
- 1
292
- );
272
+ expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1);
293
273
  });
294
274
  await screen.findByText('Select device');
295
275
  });
@@ -309,7 +289,7 @@ describe('DeviceSelector', () => {
309
289
  );
310
290
 
311
291
  fireEvent.click(screen.getByText('Select device'));
312
- fireEvent.click(screen.getByText(testDevice.serialNumber));
292
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
313
293
 
314
294
  await screen.findByText(
315
295
  'Device must be programmed, do you want to proceed?'
@@ -331,7 +311,7 @@ describe('DeviceSelector', () => {
331
311
  );
332
312
 
333
313
  fireEvent.click(screen.getByText('Select device'));
334
- fireEvent.click(screen.getByText(testDevice.serialNumber));
314
+ fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
335
315
 
336
316
  await screen.findByText(
337
317
  'Device must be programmed, do you want to proceed?'
@@ -345,6 +325,6 @@ describe('DeviceSelector', () => {
345
325
  )
346
326
  ).toBeNull();
347
327
 
348
- expect(screen.getAllByText(testDevice.serialNumber)).toHaveLength(2);
328
+ expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2);
349
329
  });
350
330
  });
@@ -4,10 +4,12 @@
4
4
  * SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
5
5
  */
6
6
 
7
- import React, { useCallback, useEffect, useState } from 'react';
7
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
8
8
  import { useDispatch, useSelector } from 'react-redux';
9
9
 
10
+ import { NrfutilDeviceLib } from '../../../nrfutil';
10
11
  import { DeviceTraits } from '../../../nrfutil/device/common';
12
+ import logger from '../../logging';
11
13
  import useHotKey from '../../utils/useHotKey';
12
14
  import {
13
15
  clearWaitForDevice,
@@ -22,7 +24,8 @@ import {
22
24
  Device,
23
25
  deviceIsSelected as deviceIsSelectedSelector,
24
26
  selectDevice,
25
- selectedSerialNumber,
27
+ selectedDevice,
28
+ setSelectedDeviceInfo,
26
29
  } from '../deviceSlice';
27
30
  import DeviceList from './DeviceList/DeviceList';
28
31
  import SelectDevice from './SelectDevice';
@@ -54,7 +57,7 @@ export default ({
54
57
  const [deviceListVisible, setDeviceListVisible] = useState(false);
55
58
 
56
59
  const deviceIsSelected = useSelector(deviceIsSelectedSelector);
57
- const selectedSN = useSelector(selectedSerialNumber);
60
+ const currentDevice = useSelector(selectedDevice);
58
61
  const waitingToAutoReconnect = useSelector(getWaitingToAutoReselect);
59
62
  const showSelectedDevice = deviceIsSelected || waitingToAutoReconnect;
60
63
 
@@ -65,25 +68,47 @@ export default ({
65
68
  dispatch(deselectDevice());
66
69
  }, [dispatch, onDeviceDeselected]);
67
70
 
71
+ const abortController = useRef<AbortController>();
72
+
68
73
  // Ensure that useCallback is
69
74
  // not updated frequently as this
70
75
  // will have a side effect to stop and start the hotplug events
71
76
  const doSelectDevice = useCallback(
72
- (device: Device, autoReselected: boolean) => {
77
+ async (device: Device, autoReselected: boolean) => {
73
78
  dispatch(clearWaitForDevice());
74
79
  setDeviceListVisible(false);
75
80
  dispatch(selectDevice(device));
76
81
  dispatch(setAutoSelectDevice(device));
77
82
  onDeviceSelected(device, autoReselected);
83
+
84
+ abortController.current?.abort();
85
+ abortController.current = new AbortController();
86
+ const deviceInfo = await NrfutilDeviceLib.deviceInfo(
87
+ device,
88
+ undefined,
89
+ undefined,
90
+ abortController.current
91
+ );
92
+ abortController.current = undefined;
93
+ setSelectedDeviceInfo(deviceInfo);
94
+
78
95
  if (deviceSetupConfig) {
79
- dispatch(
80
- setupDevice(
81
- device,
82
- deviceSetupConfig,
83
- onDeviceIsReady,
84
- doDeselectDevice
85
- )
86
- );
96
+ if (device.serialNumber) {
97
+ dispatch(
98
+ setupDevice(
99
+ device,
100
+ deviceSetupConfig,
101
+ onDeviceIsReady,
102
+ doDeselectDevice,
103
+ deviceInfo
104
+ )
105
+ );
106
+ } else {
107
+ logger.warn(
108
+ `Selected device has no serial number. Device setup is not supported`
109
+ );
110
+ onDeviceIsReady(device);
111
+ }
87
112
  }
88
113
  },
89
114
  [
@@ -145,7 +170,7 @@ export default ({
145
170
  <DeviceList
146
171
  isVisible={deviceListVisible}
147
172
  doSelectDevice={(device, autoReselected) => {
148
- if (device.serialNumber === selectedSN) {
173
+ if (device.id === currentDevice?.id) {
149
174
  setDeviceListVisible(false);
150
175
  return;
151
176
  }
@@ -8,19 +8,18 @@ import React, { FC } from 'react';
8
8
  import { useDispatch } from 'react-redux';
9
9
 
10
10
  import PseudoButton from '../../PseudoButton/PseudoButton';
11
+ import classNames from '../../utils/classNames';
11
12
  import { Device, toggleDeviceFavorited } from '../deviceSlice';
12
13
 
13
- import './favorite.scss';
14
-
15
14
  export const MakeDeviceFavorite: FC<{ device: Device }> = ({ device }) => {
16
15
  const dispatch = useDispatch();
17
16
 
18
17
  const toggleFavorite = () => {
19
- dispatch(toggleDeviceFavorited(device.serialNumber));
18
+ dispatch(toggleDeviceFavorited(device));
20
19
  };
21
20
 
22
21
  return (
23
- <PseudoButton className="make-favorite" onClick={toggleFavorite}>
22
+ <PseudoButton className="tw-mr-[1ex]" onClick={toggleFavorite}>
24
23
  <span
25
24
  className={`mdi star ${
26
25
  device.favorite ? 'mdi-star-off' : 'mdi-star'
@@ -35,15 +34,16 @@ export const FavoriteIndicator: FC<{ device: Device }> = ({ device }) => {
35
34
  const dispatch = useDispatch();
36
35
 
37
36
  const toggleFavorite = () => {
38
- dispatch(toggleDeviceFavorited(device.serialNumber));
37
+ dispatch(toggleDeviceFavorited(device));
39
38
  };
40
39
 
41
- return (
40
+ return device.serialNumber ? (
42
41
  <PseudoButton
43
- className={`mdi ${
44
- device.favorite ? 'mdi-star' : 'mdi-star-outline'
45
- }`}
42
+ className={classNames(
43
+ !device.favorite && 'tw-invisible group-hover:tw-visible',
44
+ `mdi ${device.favorite ? 'mdi-star' : 'mdi-star-outline'}`
45
+ )}
46
46
  onClick={toggleFavorite}
47
47
  />
48
- );
48
+ ) : null;
49
49
  };
@@ -16,9 +16,6 @@
16
16
  .details {
17
17
  width: inherit;
18
18
 
19
- display: flex;
20
- flex-direction: column;
21
-
22
19
  line-height: 1;
23
20
 
24
21
  .name {
@@ -49,14 +46,5 @@
49
46
  text-overflow: ellipsis;
50
47
  }
51
48
  }
52
-
53
- .toggles {
54
- display: flex;
55
- flex-direction: column;
56
- align-items: center;
57
-
58
- width: 44px;
59
- margin-right: 10px;
60
- }
61
49
  }
62
50
  }
@@ -199,7 +199,7 @@ const devicesByPca: { [P in KnownDevicePCA]: DeviceInfo } = {
199
199
 
200
200
  const deviceByPca = (device: Device) =>
201
201
  devicesByPca[
202
- String(device.jlink?.boardVersion).toUpperCase() as KnownDevicePCA
202
+ String(device.devkit?.boardVersion).toUpperCase() as KnownDevicePCA
203
203
  ];
204
204
 
205
205
  const NORDIC_VENDOR_ID = '1915';
@@ -252,7 +252,7 @@ export const displayedDeviceName = (
252
252
  return device.nickname;
253
253
  }
254
254
 
255
- return deviceInfo(device).name || device.jlink?.boardVersion || 'Unknown';
255
+ return deviceInfo(device).name || device.devkit?.boardVersion || 'Unknown';
256
256
  };
257
257
 
258
258
  export const productPageUrl = (device: Device) =>