@nordicsemiconductor/pc-nrfconnect-shared 120.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.
- package/Changelog.md +48 -0
- package/coverage/cobertura-coverage.xml +1358 -1215
- package/nrfutil/device/__mocks__/device.ts +2 -0
- package/nrfutil/device/batch.ts +18 -2
- package/nrfutil/device/common.ts +17 -38
- package/nrfutil/device/device.ts +2 -0
- package/nrfutil/device/deviceInfo.ts +70 -0
- package/nrfutil/device/erase.ts +2 -2
- package/nrfutil/device/firmwareRead.ts +2 -2
- package/nrfutil/device/getCoreInfo.ts +2 -2
- package/nrfutil/device/getFwInfo.ts +2 -2
- package/nrfutil/device/getProtectionStatus.ts +2 -2
- package/nrfutil/device/list.ts +4 -30
- package/nrfutil/device/program.ts +4 -4
- package/nrfutil/device/recover.ts +2 -2
- package/nrfutil/device/reset.ts +2 -2
- package/nrfutil/device/setMcuState.ts +2 -5
- package/nrfutil/device/setProtectionStatus.ts +2 -2
- package/nrfutil/index.ts +1 -1
- package/nrfutil/moduleVersion.ts +20 -0
- package/nrfutil/sandboxTypes.ts +14 -0
- package/package.json +1 -1
- package/src/About/DeviceCard.tsx +6 -5
- package/src/About/SupportCard.tsx +2 -2
- package/src/App/shared.scss +0 -1
- package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +12 -6
- package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +1 -1
- package/src/Device/DeviceSelector/DeviceList/Device.tsx +7 -5
- package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +23 -5
- package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +7 -6
- package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +26 -30
- package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +1 -2
- package/src/Device/DeviceSelector/DeviceSelector.test.tsx +26 -46
- package/src/Device/DeviceSelector/DeviceSelector.tsx +40 -15
- package/src/Device/DeviceSelector/Favorite.tsx +10 -10
- package/src/Device/DeviceSelector/basic-device-info.scss +0 -12
- package/src/Device/deviceInfo/deviceInfo.ts +2 -2
- package/src/Device/deviceLister.ts +59 -50
- package/src/Device/deviceSetup.ts +28 -10
- package/src/Device/deviceSlice.ts +148 -84
- package/src/Device/jprogOperations.ts +56 -27
- package/src/Device/sdfuOperations.ts +25 -31
- package/src/Dropdown/Dropdown.tsx +2 -2
- package/src/InlineInput/InlineInput.tsx +25 -3
- package/src/InlineInput/NumberInlineInput.tsx +24 -8
- package/src/InlineInput/NumberInputWithDropdown.tsx +131 -0
- package/src/index.ts +3 -0
- package/src/logging/sendInitialLogMessages.ts +13 -9
- package/src/utils/logLibVersions.ts +1 -1
- package/src/utils/systemReport.ts +3 -3
- package/typings/generated/nrfutil/device/__mocks__/device.d.ts +1 -0
- package/typings/generated/nrfutil/device/__mocks__/device.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/batch.d.ts +3 -2
- package/typings/generated/nrfutil/device/batch.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/common.d.ts +6 -33
- package/typings/generated/nrfutil/device/common.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/device.d.ts +13 -12
- package/typings/generated/nrfutil/device/device.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/deviceInfo.d.ts +40 -0
- package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -0
- package/typings/generated/nrfutil/device/erase.d.ts +2 -2
- package/typings/generated/nrfutil/device/erase.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/firmwareRead.d.ts +2 -2
- package/typings/generated/nrfutil/device/firmwareRead.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getCoreInfo.d.ts +2 -2
- package/typings/generated/nrfutil/device/getCoreInfo.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getFwInfo.d.ts +2 -2
- package/typings/generated/nrfutil/device/getFwInfo.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +2 -2
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/list.d.ts +3 -3
- package/typings/generated/nrfutil/device/list.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/program.d.ts +2 -2
- package/typings/generated/nrfutil/device/program.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/recover.d.ts +2 -2
- package/typings/generated/nrfutil/device/recover.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/reset.d.ts +2 -2
- package/typings/generated/nrfutil/device/reset.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/setMcuState.d.ts +2 -2
- package/typings/generated/nrfutil/device/setMcuState.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/setProtectionStatus.d.ts +2 -2
- package/typings/generated/nrfutil/device/setProtectionStatus.d.ts.map +1 -1
- package/typings/generated/nrfutil/index.d.ts +2 -1
- package/typings/generated/nrfutil/index.d.ts.map +1 -1
- package/typings/generated/nrfutil/moduleVersion.d.ts +4 -0
- package/typings/generated/nrfutil/moduleVersion.d.ts.map +1 -1
- package/typings/generated/nrfutil/sandboxTypes.d.ts +9 -0
- package/typings/generated/nrfutil/sandboxTypes.d.ts.map +1 -1
- package/typings/generated/src/About/DeviceCard.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceLister.d.ts +1 -15
- package/typings/generated/src/Device/deviceLister.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceSetup.d.ts +6 -5
- package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceSlice.d.ts +12 -15
- package/typings/generated/src/Device/deviceSlice.d.ts.map +1 -1
- package/typings/generated/src/Device/jprogOperations.d.ts.map +1 -1
- package/typings/generated/src/Device/sdfuOperations.d.ts.map +1 -1
- package/typings/generated/src/Dropdown/Dropdown.d.ts +2 -2
- package/typings/generated/src/Dropdown/Dropdown.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/InlineInput.d.ts +3 -0
- package/typings/generated/src/InlineInput/InlineInput.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +8 -4
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts +19 -0
- package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts.map +1 -0
- package/typings/generated/src/index.d.ts +3 -1
- package/typings/generated/src/index.d.ts.map +1 -1
- package/typings/generated/src/logging/sendInitialLogMessages.d.ts.map +1 -1
- package/typings/generated/src/utils/systemReport.d.ts +1 -1
- package/typings/generated/src/utils/systemReport.d.ts.map +1 -1
- package/src/Device/DeviceSelector/DeviceList/device.scss +0 -28
- package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +0 -33
- 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
|
|
37
|
+
dispatch(resetDeviceNickname(device));
|
|
36
38
|
} else {
|
|
37
|
-
dispatch(setDeviceNickname(device
|
|
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 =
|
|
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="
|
|
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
|
};
|
|
@@ -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={
|
|
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
|
-
'
|
|
56
|
-
moreVisible && '
|
|
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 {
|
|
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
|
-
|
|
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.
|
|
94
|
-
itemKey={device.
|
|
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
|
-
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
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="
|
|
17
|
-
<div className="
|
|
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.
|
|
21
|
+
if (!device.devkit?.boardVersion) {
|
|
24
22
|
return null;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
return
|
|
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
|
-
|
|
32
|
-
if (!hasNickname) {
|
|
33
|
+
if (!device.nickname) {
|
|
33
34
|
return null;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
return (
|
|
37
|
-
<
|
|
38
|
-
{displayedDeviceName(device, { respectNickname: false })}
|
|
39
|
-
</
|
|
38
|
+
<Row>
|
|
39
|
+
<div>{displayedDeviceName(device, { respectNickname: false })}</div>
|
|
40
|
+
</Row>
|
|
40
41
|
);
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
const Serialports = ({ ports }: { ports: SerialPort[] }) =>
|
|
44
|
-
|
|
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
|
-
<
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
);
|
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import {
|
|
9
|
-
fireEvent,
|
|
10
|
-
screen,
|
|
11
|
-
waitFor,
|
|
12
|
-
waitForElementToBeRemoved,
|
|
13
|
-
} from '@testing-library/react';
|
|
8
|
+
import { fireEvent, screen, waitFor } from '@testing-library/react';
|
|
14
9
|
|
|
15
10
|
import render from '../../../test/testrenderer';
|
|
16
11
|
import { addDevice, Device, removeDevice } from '../deviceSlice';
|
|
@@ -19,18 +14,13 @@ import DeviceSelector from './DeviceSelector';
|
|
|
19
14
|
|
|
20
15
|
jest.mock('../../../nrfutil/device/device');
|
|
21
16
|
|
|
17
|
+
const DEVICE_SERIAL_NUMBER = '000000001';
|
|
18
|
+
|
|
22
19
|
const testDevice: Device = {
|
|
23
20
|
id: 1,
|
|
24
|
-
hwInfo: {
|
|
25
|
-
romSize: 123,
|
|
26
|
-
ramSize: 456,
|
|
27
|
-
romPageSize: 789,
|
|
28
|
-
deviceFamily: 'PCATest',
|
|
29
|
-
deviceVersion: 'PCATest',
|
|
30
|
-
},
|
|
31
21
|
broken: null,
|
|
32
22
|
usb: {
|
|
33
|
-
serialNumber:
|
|
23
|
+
serialNumber: DEVICE_SERIAL_NUMBER,
|
|
34
24
|
manufacturer: 'testManufacturer',
|
|
35
25
|
product: 'testProduct',
|
|
36
26
|
osDevicePath: '/some-path',
|
|
@@ -71,26 +61,13 @@ const testDevice: Device = {
|
|
|
71
61
|
vcom: 2,
|
|
72
62
|
},
|
|
73
63
|
],
|
|
74
|
-
boardVersion: 'PCATest',
|
|
75
|
-
serialport: {
|
|
76
|
-
path: 'COM1',
|
|
77
|
-
manufacturer: 'testManufacturer',
|
|
78
|
-
productId: 'testProduct',
|
|
79
|
-
serialNumber: '000000001',
|
|
80
|
-
vendorId: 'testVendor',
|
|
81
|
-
comName: 'COM1',
|
|
82
|
-
vcom: 0,
|
|
83
|
-
},
|
|
84
64
|
favorite: false,
|
|
85
65
|
traits: {
|
|
86
66
|
jlink: true,
|
|
87
67
|
},
|
|
88
|
-
|
|
68
|
+
devkit: {
|
|
89
69
|
boardVersion: 'PCATest',
|
|
90
|
-
serialNumber: 'PCATest',
|
|
91
|
-
jlinkObFirmwareVersion: 'PCATest',
|
|
92
70
|
deviceFamily: 'PCATest',
|
|
93
|
-
deviceVersion: 'PCATest',
|
|
94
71
|
},
|
|
95
72
|
};
|
|
96
73
|
|
|
@@ -156,7 +133,7 @@ describe('DeviceSelector', () => {
|
|
|
156
133
|
/>,
|
|
157
134
|
[addDevice(testDevice)]
|
|
158
135
|
);
|
|
159
|
-
expect(screen.getByText(
|
|
136
|
+
expect(screen.getByText(DEVICE_SERIAL_NUMBER)).toBeInTheDocument();
|
|
160
137
|
});
|
|
161
138
|
|
|
162
139
|
it('should unlist disconnected devices', () => {
|
|
@@ -171,7 +148,7 @@ describe('DeviceSelector', () => {
|
|
|
171
148
|
/>,
|
|
172
149
|
[addDevice(testDevice), removeDevice(testDevice)]
|
|
173
150
|
);
|
|
174
|
-
expect(screen.queryByText(
|
|
151
|
+
expect(screen.queryByText(DEVICE_SERIAL_NUMBER)).toBeNull();
|
|
175
152
|
});
|
|
176
153
|
|
|
177
154
|
it('should show more device info when selecting the expand button', () => {
|
|
@@ -205,8 +182,8 @@ describe('DeviceSelector', () => {
|
|
|
205
182
|
);
|
|
206
183
|
|
|
207
184
|
fireEvent.click(screen.getByText('Select device'));
|
|
208
|
-
fireEvent.click(screen.getByText(
|
|
209
|
-
expect(screen.getAllByText(
|
|
185
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
186
|
+
expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2);
|
|
210
187
|
});
|
|
211
188
|
|
|
212
189
|
it('can deselect selected devices', async () => {
|
|
@@ -222,10 +199,10 @@ describe('DeviceSelector', () => {
|
|
|
222
199
|
[addDevice(testDevice)]
|
|
223
200
|
);
|
|
224
201
|
fireEvent.click(screen.getByText('Select device'));
|
|
225
|
-
fireEvent.click(screen.getByText(
|
|
202
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
226
203
|
await screen.findByTestId('disconnect-device');
|
|
227
204
|
fireEvent.click(screen.getByTestId('disconnect-device'));
|
|
228
|
-
expect(screen.getAllByText(
|
|
205
|
+
expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1);
|
|
229
206
|
expect(screen.getByText('Select device')).toBeInTheDocument();
|
|
230
207
|
});
|
|
231
208
|
|
|
@@ -255,10 +232,10 @@ describe('DeviceSelector', () => {
|
|
|
255
232
|
[addDevice(testDevice)]
|
|
256
233
|
);
|
|
257
234
|
fireEvent.click(screen.getByText('Select device'));
|
|
258
|
-
fireEvent.click(screen.getByText(
|
|
235
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
259
236
|
|
|
260
237
|
expect(screen.queryByText('OK')).toBeNull();
|
|
261
|
-
expect(screen.getAllByText(
|
|
238
|
+
expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2);
|
|
262
239
|
});
|
|
263
240
|
|
|
264
241
|
it('should deselect device when custom devices are disabled and no valid firmware is defined', async () => {
|
|
@@ -288,13 +265,11 @@ describe('DeviceSelector', () => {
|
|
|
288
265
|
);
|
|
289
266
|
|
|
290
267
|
fireEvent.click(screen.getByText('Select device'));
|
|
291
|
-
fireEvent.click(screen.getByText(
|
|
268
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
292
269
|
|
|
293
270
|
expect(screen.queryByText('OK')).toBeNull();
|
|
294
271
|
await waitFor(() => {
|
|
295
|
-
expect(screen.getAllByText(
|
|
296
|
-
1
|
|
297
|
-
);
|
|
272
|
+
expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1);
|
|
298
273
|
});
|
|
299
274
|
await screen.findByText('Select device');
|
|
300
275
|
});
|
|
@@ -314,7 +289,7 @@ describe('DeviceSelector', () => {
|
|
|
314
289
|
);
|
|
315
290
|
|
|
316
291
|
fireEvent.click(screen.getByText('Select device'));
|
|
317
|
-
fireEvent.click(screen.getByText(
|
|
292
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
318
293
|
|
|
319
294
|
await screen.findByText(
|
|
320
295
|
'Device must be programmed, do you want to proceed?'
|
|
@@ -336,15 +311,20 @@ describe('DeviceSelector', () => {
|
|
|
336
311
|
);
|
|
337
312
|
|
|
338
313
|
fireEvent.click(screen.getByText('Select device'));
|
|
339
|
-
fireEvent.click(screen.getByText(
|
|
340
|
-
|
|
314
|
+
fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER));
|
|
315
|
+
|
|
316
|
+
await screen.findByText(
|
|
317
|
+
'Device must be programmed, do you want to proceed?'
|
|
318
|
+
);
|
|
319
|
+
|
|
341
320
|
fireEvent.click(screen.getByText('No'));
|
|
342
321
|
|
|
343
|
-
|
|
322
|
+
expect(
|
|
344
323
|
screen.queryByText(
|
|
345
324
|
'Device must be programmed, do you want to proceed?'
|
|
346
325
|
)
|
|
347
|
-
);
|
|
348
|
-
|
|
326
|
+
).toBeNull();
|
|
327
|
+
|
|
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
|
-
|
|
27
|
+
selectedDevice,
|
|
28
|
+
setSelectedDeviceInfo,
|
|
26
29
|
} from '../deviceSlice';
|
|
27
30
|
import DeviceList from './DeviceList/DeviceList';
|
|
28
31
|
import SelectDevice from './SelectDevice';
|
|
@@ -54,36 +57,58 @@ export default ({
|
|
|
54
57
|
const [deviceListVisible, setDeviceListVisible] = useState(false);
|
|
55
58
|
|
|
56
59
|
const deviceIsSelected = useSelector(deviceIsSelectedSelector);
|
|
57
|
-
const
|
|
60
|
+
const currentDevice = useSelector(selectedDevice);
|
|
58
61
|
const waitingToAutoReconnect = useSelector(getWaitingToAutoReselect);
|
|
59
62
|
const showSelectedDevice = deviceIsSelected || waitingToAutoReconnect;
|
|
60
63
|
|
|
61
64
|
const doDeselectDevice = useCallback(() => {
|
|
62
|
-
onDeviceDeselected();
|
|
63
|
-
dispatch(deselectDevice());
|
|
64
65
|
dispatch(clearWaitForDevice());
|
|
65
66
|
dispatch(setAutoSelectDevice(undefined));
|
|
67
|
+
onDeviceDeselected();
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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.
|
|
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
|
|
18
|
+
dispatch(toggleDeviceFavorited(device));
|
|
20
19
|
};
|
|
21
20
|
|
|
22
21
|
return (
|
|
23
|
-
<PseudoButton className="
|
|
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
|
|
37
|
+
dispatch(toggleDeviceFavorited(device));
|
|
39
38
|
};
|
|
40
39
|
|
|
41
|
-
return (
|
|
40
|
+
return device.serialNumber ? (
|
|
42
41
|
<PseudoButton
|
|
43
|
-
className={
|
|
44
|
-
device.favorite
|
|
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.
|
|
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.
|
|
255
|
+
return deviceInfo(device).name || device.devkit?.boardVersion || 'Unknown';
|
|
256
256
|
};
|
|
257
257
|
|
|
258
258
|
export const productPageUrl = (device: Device) =>
|