@nordicsemiconductor/pc-nrfconnect-shared 157.0.0 → 159.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 +49 -0
- package/nrfutil/device/deviceInfo.ts +2 -0
- package/nrfutil/device/getProtectionStatus.ts +1 -7
- package/package.json +1 -1
- package/src/App/App.tsx +2 -0
- package/src/ConfirmBeforeClose/ConfirmCloseDialog.tsx +85 -0
- package/src/ConfirmBeforeClose/confirmBeforeCloseSlice.ts +96 -0
- package/src/Device/deviceSetup.ts +13 -1
- package/src/Device/deviceSlice.ts +1 -12
- package/src/Device/jprogOperations.ts +40 -66
- package/src/Dropdown/Dropdown.tsx +19 -4
- package/src/InlineInput/InlineInput.tsx +3 -0
- package/src/InlineInput/NumberInlineInput.tsx +31 -6
- package/src/NumberInput/NumberInput.tsx +133 -0
- package/src/StateSelector/state-selector.scss +0 -1
- package/src/index.ts +7 -1
- package/src/store.ts +2 -0
- package/typings/generated/nrfutil/device/deviceInfo.d.ts +2 -1
- package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +1 -2
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
- package/typings/generated/src/App/App.d.ts.map +1 -1
- package/typings/generated/src/ConfirmBeforeClose/ConfirmCloseDialog.d.ts +4 -0
- package/typings/generated/src/ConfirmBeforeClose/ConfirmCloseDialog.d.ts.map +1 -0
- package/typings/generated/src/ConfirmBeforeClose/confirmBeforeCloseSlice.d.ts +16 -0
- package/typings/generated/src/ConfirmBeforeClose/confirmBeforeCloseSlice.d.ts.map +1 -0
- package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceSlice.d.ts +2 -3
- 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/Dropdown/Dropdown.d.ts +3 -1
- package/typings/generated/src/Dropdown/Dropdown.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/InlineInput.d.ts +1 -0
- package/typings/generated/src/InlineInput/InlineInput.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +2 -1
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
- package/typings/generated/src/NumberInput/NumberInput.d.ts +23 -0
- package/typings/generated/src/NumberInput/NumberInput.d.ts.map +1 -0
- package/typings/generated/src/index.d.ts +2 -1
- package/typings/generated/src/index.d.ts.map +1 -1
- package/typings/generated/src/store.d.ts +5 -0
- package/typings/generated/src/store.d.ts.map +1 -1
- package/src/NumberInputWithSlider/NumberInputSliderWithUnit.tsx +0 -74
- package/typings/generated/src/NumberInputWithSlider/NumberInputSliderWithUnit.d.ts +0 -14
- package/typings/generated/src/NumberInputWithSlider/NumberInputSliderWithUnit.d.ts.map +0 -1
package/Changelog.md
CHANGED
|
@@ -7,6 +7,55 @@ This project does _not_ adhere to
|
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) but contrary to it
|
|
8
8
|
every new version is a new major version.
|
|
9
9
|
|
|
10
|
+
## 159.0.0 - 2024-02-23
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `minWidth` parameter to `Dropdown` component.
|
|
15
|
+
- `transparentButtonBg` parameter to `Dropdown` component.
|
|
16
|
+
- `NumberInput` component (provides text, input, optional unit, and slider).
|
|
17
|
+
- Common way to queue ongoing pending tasks. If an app is closed, a dialog is
|
|
18
|
+
prompted to alert users before clo sing app. Redux states for this are:
|
|
19
|
+
- `addConfirmBeforeClose`
|
|
20
|
+
- `clearConfirmBeforeClose`
|
|
21
|
+
- `preventAppCloseUntilComplete` can be used to wrap some promise and
|
|
22
|
+
secure app from closing until promise is resolved
|
|
23
|
+
|
|
24
|
+
### Removed
|
|
25
|
+
|
|
26
|
+
- `NumberInputWithSlider` component.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- `StateSelector` no longer has 16px margin on the bottom. Apps are now
|
|
31
|
+
responsible to add the appropriate gap per container
|
|
32
|
+
|
|
33
|
+
### Steps to upgrade
|
|
34
|
+
|
|
35
|
+
- Change all occurrences of `NumberInputWithSlider` to `NumberInput`.
|
|
36
|
+
- Check all use cases of `StateSelector` and that the gap between components
|
|
37
|
+
is correct if not adjust spacing from the app side
|
|
38
|
+
|
|
39
|
+
## 158.0.0 - 2024-02-22
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- `NrfutilDeviceLib.deviceInfo` now has `protectionStatus` property.
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- `DeviceSlice` no longer has readbackProtection state
|
|
48
|
+
- `DeviceSlice` no longer has setReadbackProtection has be removed
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `getReadbackProtection` now returns protection type `ProtectionStatus` from
|
|
53
|
+
nrfutil device common.ts
|
|
54
|
+
|
|
55
|
+
### Steps to upgrade when using this package
|
|
56
|
+
|
|
57
|
+
- Minimum support version of nrfutil device is now 2.1.1
|
|
58
|
+
|
|
10
59
|
## 157.0.0 - 2024-02-06
|
|
11
60
|
|
|
12
61
|
### Removed
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
DeviceCore,
|
|
10
10
|
deviceSingleTaskEndOperation,
|
|
11
11
|
NrfutilDevice,
|
|
12
|
+
ProtectionStatus,
|
|
12
13
|
} from './common';
|
|
13
14
|
|
|
14
15
|
export interface HwInfo {
|
|
@@ -25,6 +26,7 @@ export interface JLinkDeviceInfo {
|
|
|
25
26
|
jlinkObFirmwareVersion: string;
|
|
26
27
|
deviceFamily: string | null;
|
|
27
28
|
deviceVersion?: string | null;
|
|
29
|
+
protectionStatus: ProtectionStatus;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export interface DfuTriggerInfo {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
DeviceCore,
|
|
10
10
|
deviceSingleTaskEndOperation,
|
|
11
11
|
NrfutilDevice,
|
|
12
|
+
ProtectionStatus,
|
|
12
13
|
} from './common';
|
|
13
14
|
|
|
14
15
|
type DeviceFamily =
|
|
@@ -17,13 +18,6 @@ type DeviceFamily =
|
|
|
17
18
|
| 'NRF53_FAMILY'
|
|
18
19
|
| 'NRF91_FAMILY';
|
|
19
20
|
|
|
20
|
-
type ProtectionStatus =
|
|
21
|
-
| 'NRFDL_PROTECTION_STATUS_NONE'
|
|
22
|
-
| 'NRFDL_PROTECTION_STATUS_REGION0'
|
|
23
|
-
| 'NRFDL_PROTECTION_STATUS_REGION0_REGION1'
|
|
24
|
-
| 'NRFDL_PROTECTION_STATUS_SECURE_REGIONS'
|
|
25
|
-
| 'NRFDL_PROTECTION_STATUS_ALL';
|
|
26
|
-
|
|
27
21
|
export interface GetProtectionStatusResult {
|
|
28
22
|
core: DeviceCore;
|
|
29
23
|
deviceFamily?: DeviceFamily;
|
package/package.json
CHANGED
package/src/App/App.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { Reducer } from 'redux';
|
|
|
15
15
|
import { inMain as openWindow } from '../../ipc/openWindow';
|
|
16
16
|
import { setNrfutilLogger } from '../../nrfutil/nrfutilLogger';
|
|
17
17
|
import About from '../About/About';
|
|
18
|
+
import ConfirmCloseDialog from '../ConfirmBeforeClose/ConfirmCloseDialog';
|
|
18
19
|
import BrokenDeviceDialog from '../Device/BrokenDeviceDialog/BrokenDeviceDialog';
|
|
19
20
|
import { setAutoReselect } from '../Device/deviceAutoSelectSlice';
|
|
20
21
|
import {
|
|
@@ -181,6 +182,7 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
|
|
|
181
182
|
|
|
182
183
|
<ErrorDialog />
|
|
183
184
|
<BrokenDeviceDialog />
|
|
185
|
+
<ConfirmCloseDialog />
|
|
184
186
|
{children}
|
|
185
187
|
</div>
|
|
186
188
|
);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useEffect, useState } from 'react';
|
|
8
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
9
|
+
import { getCurrentWindow } from '@electron/remote';
|
|
10
|
+
|
|
11
|
+
import { ConfirmationDialog } from '../Dialog/Dialog';
|
|
12
|
+
import { AppThunk } from '../store';
|
|
13
|
+
import {
|
|
14
|
+
addConfirmBeforeClose,
|
|
15
|
+
clearConfirmBeforeClose,
|
|
16
|
+
ConfirmBeforeCloseApp,
|
|
17
|
+
getNextConfirmDialog,
|
|
18
|
+
getShowConfirmCloseDialog,
|
|
19
|
+
setShowCloseDialog,
|
|
20
|
+
} from './confirmBeforeCloseSlice';
|
|
21
|
+
|
|
22
|
+
export default () => {
|
|
23
|
+
const dispatch = useDispatch();
|
|
24
|
+
const [confirmedDialogs, setConfirmedDialogs] = useState<
|
|
25
|
+
ConfirmBeforeCloseApp[]
|
|
26
|
+
>([]);
|
|
27
|
+
|
|
28
|
+
const showCloseDialog = useSelector(getShowConfirmCloseDialog);
|
|
29
|
+
const nextConfirmDialog = useSelector(getNextConfirmDialog);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!nextConfirmDialog && showCloseDialog) {
|
|
33
|
+
confirmedDialogs.forEach(confirmedDialog => {
|
|
34
|
+
if (confirmedDialog.onClose) confirmedDialog.onClose();
|
|
35
|
+
});
|
|
36
|
+
setConfirmedDialogs([]);
|
|
37
|
+
getCurrentWindow().close();
|
|
38
|
+
}
|
|
39
|
+
}, [nextConfirmDialog, dispatch, showCloseDialog, confirmedDialogs]);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const action = (ev: BeforeUnloadEvent) =>
|
|
43
|
+
dispatch<AppThunk>((_, getState) => {
|
|
44
|
+
const hasToGetExplicitConform =
|
|
45
|
+
getState().confirmBeforeCloseDialog.confirmCloseApp.length >
|
|
46
|
+
0;
|
|
47
|
+
if (hasToGetExplicitConform) {
|
|
48
|
+
dispatch(setShowCloseDialog(true));
|
|
49
|
+
ev.returnValue = true;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
window.addEventListener('beforeunload', action, true);
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
window.removeEventListener('beforeunload', action);
|
|
57
|
+
};
|
|
58
|
+
}, [dispatch]);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ConfirmationDialog
|
|
62
|
+
headerIcon="alert-outline"
|
|
63
|
+
title="Closing nPM PowerUP"
|
|
64
|
+
isVisible={showCloseDialog && !!nextConfirmDialog}
|
|
65
|
+
onConfirm={() => {
|
|
66
|
+
if (nextConfirmDialog) {
|
|
67
|
+
setConfirmedDialogs([
|
|
68
|
+
...confirmedDialogs,
|
|
69
|
+
nextConfirmDialog,
|
|
70
|
+
]);
|
|
71
|
+
dispatch(clearConfirmBeforeClose(nextConfirmDialog.id));
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
onCancel={() => {
|
|
75
|
+
dispatch(setShowCloseDialog(false));
|
|
76
|
+
confirmedDialogs.forEach(confirmedDialog =>
|
|
77
|
+
dispatch(addConfirmBeforeClose(confirmedDialog))
|
|
78
|
+
);
|
|
79
|
+
setConfirmedDialogs([]);
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
82
|
+
{nextConfirmDialog?.message}
|
|
83
|
+
</ConfirmationDialog>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
8
|
+
import { v4 as uuid } from 'uuid';
|
|
9
|
+
|
|
10
|
+
import type { AppThunk, RootState } from '../store';
|
|
11
|
+
|
|
12
|
+
export interface ConfirmBeforeCloseApp {
|
|
13
|
+
id: string;
|
|
14
|
+
message: React.ReactNode;
|
|
15
|
+
onClose?: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ConfirmBeforeCloseState {
|
|
19
|
+
confirmCloseApp: ConfirmBeforeCloseApp[];
|
|
20
|
+
showCloseDialog: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const initialState: ConfirmBeforeCloseState = {
|
|
24
|
+
confirmCloseApp: [],
|
|
25
|
+
showCloseDialog: false,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const slice = createSlice({
|
|
29
|
+
name: 'confirmBeforeCloseDialog',
|
|
30
|
+
initialState,
|
|
31
|
+
reducers: {
|
|
32
|
+
addConfirmBeforeClose(
|
|
33
|
+
state,
|
|
34
|
+
action: PayloadAction<ConfirmBeforeCloseApp>
|
|
35
|
+
) {
|
|
36
|
+
const index = state.confirmCloseApp.findIndex(
|
|
37
|
+
confirmCloseApp => confirmCloseApp.id === action.payload.id
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (index !== -1) {
|
|
41
|
+
state.confirmCloseApp[index] = action.payload;
|
|
42
|
+
} else {
|
|
43
|
+
state.confirmCloseApp = [
|
|
44
|
+
action.payload,
|
|
45
|
+
...state.confirmCloseApp,
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
clearConfirmBeforeClose(state, action: PayloadAction<string>) {
|
|
50
|
+
state.confirmCloseApp = state.confirmCloseApp.filter(
|
|
51
|
+
confirmCloseApp => confirmCloseApp.id !== action.payload
|
|
52
|
+
);
|
|
53
|
+
},
|
|
54
|
+
setShowCloseDialog(state, action: PayloadAction<boolean>) {
|
|
55
|
+
state.showCloseDialog = action.payload;
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const {
|
|
61
|
+
reducer,
|
|
62
|
+
actions: {
|
|
63
|
+
addConfirmBeforeClose,
|
|
64
|
+
setShowCloseDialog,
|
|
65
|
+
clearConfirmBeforeClose,
|
|
66
|
+
},
|
|
67
|
+
} = slice;
|
|
68
|
+
|
|
69
|
+
export const getNextConfirmDialog = (state: RootState) =>
|
|
70
|
+
state.confirmBeforeCloseDialog.confirmCloseApp.length > 0
|
|
71
|
+
? state.confirmBeforeCloseDialog.confirmCloseApp[0]
|
|
72
|
+
: undefined;
|
|
73
|
+
|
|
74
|
+
export const getShowConfirmCloseDialog = (state: RootState) =>
|
|
75
|
+
state.confirmBeforeCloseDialog.showCloseDialog;
|
|
76
|
+
|
|
77
|
+
export const preventAppCloseUntilComplete =
|
|
78
|
+
(
|
|
79
|
+
dialogInfo: Omit<ConfirmBeforeCloseApp, 'id'>,
|
|
80
|
+
promise: Promise<unknown>,
|
|
81
|
+
abortController?: AbortController
|
|
82
|
+
): AppThunk =>
|
|
83
|
+
dispatch => {
|
|
84
|
+
const id = uuid();
|
|
85
|
+
dispatch(
|
|
86
|
+
addConfirmBeforeClose({
|
|
87
|
+
...dialogInfo,
|
|
88
|
+
id,
|
|
89
|
+
onClose: () => {
|
|
90
|
+
dialogInfo.onClose?.();
|
|
91
|
+
abortController?.abort();
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
promise.finally(() => dispatch(clearConfirmBeforeClose(id)));
|
|
96
|
+
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
5
|
*/
|
|
6
6
|
import { DeviceInfo } from '../../nrfutil/device/deviceInfo';
|
|
7
|
+
import { preventAppCloseUntilComplete } from '../ConfirmBeforeClose/confirmBeforeCloseSlice';
|
|
7
8
|
import logger from '../logging';
|
|
8
9
|
import describeError from '../logging/describeError';
|
|
9
10
|
import { AppThunk, RootState } from '../store';
|
|
@@ -151,7 +152,7 @@ export const prepareDevice =
|
|
|
151
152
|
if (!selectedDeviceSetup) {
|
|
152
153
|
onFail('No firmware was selected'); // Should never happen
|
|
153
154
|
} else {
|
|
154
|
-
dispatch(
|
|
155
|
+
const task = dispatch(
|
|
155
156
|
selectedDeviceSetup.programDevice(
|
|
156
157
|
(progress: number, message?: string) => {
|
|
157
158
|
dispatch(setDeviceSetupProgress(progress));
|
|
@@ -164,6 +165,17 @@ export const prepareDevice =
|
|
|
164
165
|
)
|
|
165
166
|
.then(onSuccessWrapper)
|
|
166
167
|
.catch(onFail);
|
|
168
|
+
|
|
169
|
+
dispatch(
|
|
170
|
+
preventAppCloseUntilComplete(
|
|
171
|
+
{
|
|
172
|
+
message: `The device is being programmed.
|
|
173
|
+
Closing application right now might result in some unknown behavior and might also brick the device.
|
|
174
|
+
Are you sure you want to continue?`,
|
|
175
|
+
},
|
|
176
|
+
task
|
|
177
|
+
)
|
|
178
|
+
);
|
|
167
179
|
}
|
|
168
180
|
};
|
|
169
181
|
|
|
@@ -61,14 +61,12 @@ const updateDevice = (
|
|
|
61
61
|
|
|
62
62
|
export interface DeviceState {
|
|
63
63
|
devices: Device[];
|
|
64
|
-
readbackProtection: 'unknown' | 'protected' | 'unprotected';
|
|
65
64
|
selectedDevice?: Device;
|
|
66
65
|
selectedDeviceInfo?: DeviceInfo;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
const initialState: DeviceState = {
|
|
70
69
|
devices: [],
|
|
71
|
-
readbackProtection: 'unknown',
|
|
72
70
|
};
|
|
73
71
|
|
|
74
72
|
const setPersistedData = (device: Device) => {
|
|
@@ -124,7 +122,6 @@ const slice = createSlice({
|
|
|
124
122
|
deselectDevice: state => {
|
|
125
123
|
state.selectedDevice = undefined;
|
|
126
124
|
state.selectedDeviceInfo = undefined;
|
|
127
|
-
state.readbackProtection = 'unknown';
|
|
128
125
|
},
|
|
129
126
|
|
|
130
127
|
addDevice: (state, action: PayloadAction<Device>) => {
|
|
@@ -261,13 +258,6 @@ const slice = createSlice({
|
|
|
261
258
|
action.payload.serialNumber
|
|
262
259
|
);
|
|
263
260
|
},
|
|
264
|
-
|
|
265
|
-
setReadbackProtected: (
|
|
266
|
-
state,
|
|
267
|
-
action: PayloadAction<DeviceState['readbackProtection']>
|
|
268
|
-
) => {
|
|
269
|
-
state.readbackProtection = action.payload;
|
|
270
|
-
},
|
|
271
261
|
},
|
|
272
262
|
});
|
|
273
263
|
|
|
@@ -282,7 +272,6 @@ export const {
|
|
|
282
272
|
removeDevice,
|
|
283
273
|
setDeviceNickname,
|
|
284
274
|
toggleDeviceFavorited,
|
|
285
|
-
setReadbackProtected,
|
|
286
275
|
persistSerialPortOptions,
|
|
287
276
|
},
|
|
288
277
|
} = slice;
|
|
@@ -304,4 +293,4 @@ export const selectedSerialNumber = (state: RootState) =>
|
|
|
304
293
|
state.device.selectedDevice?.serialNumber;
|
|
305
294
|
|
|
306
295
|
export const getReadbackProtection = (state: RootState) =>
|
|
307
|
-
state.device.
|
|
296
|
+
state.device.selectedDeviceInfo?.jlink?.protectionStatus;
|
|
@@ -6,42 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
import NrfutilDeviceLib from '../../nrfutil/device/device';
|
|
8
8
|
import { DeviceInfo } from '../../nrfutil/device/deviceInfo';
|
|
9
|
-
import { FWInfo } from '../../nrfutil/device/getFwInfo';
|
|
10
9
|
import logger from '../logging';
|
|
11
10
|
import type { AppThunk, RootState } from '../store';
|
|
12
11
|
import { DeviceSetup, JprogEntry } from './deviceSetup';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
fwInfo: FWInfo | null;
|
|
19
|
-
readbackProtection: 'unknown' | 'protected' | 'unprotected';
|
|
20
|
-
}> => {
|
|
21
|
-
try {
|
|
22
|
-
logger.info('Checking readback protection on device');
|
|
23
|
-
const info = await NrfutilDeviceLib.getFwInfo(device);
|
|
24
|
-
return {
|
|
25
|
-
fwInfo: info,
|
|
26
|
-
readbackProtection: 'unprotected',
|
|
27
|
-
};
|
|
28
|
-
} catch (e) {
|
|
29
|
-
const error = e as Error;
|
|
30
|
-
if (error.message.includes('NotAvailableBecauseProtection')) {
|
|
31
|
-
logger.warn(
|
|
32
|
-
'Readback protection on device enabled. Unable to verify that the firmware version is correct.'
|
|
33
|
-
);
|
|
34
|
-
return {
|
|
35
|
-
fwInfo: null,
|
|
36
|
-
readbackProtection: 'protected',
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
fwInfo: null,
|
|
41
|
-
readbackProtection: 'unknown',
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
};
|
|
12
|
+
import {
|
|
13
|
+
Device,
|
|
14
|
+
getReadbackProtection,
|
|
15
|
+
setSelectedDeviceInfo,
|
|
16
|
+
} from './deviceSlice';
|
|
45
17
|
|
|
46
18
|
const programDeviceWithFw =
|
|
47
19
|
(
|
|
@@ -52,7 +24,10 @@ const programDeviceWithFw =
|
|
|
52
24
|
async (dispatch, getState) => {
|
|
53
25
|
try {
|
|
54
26
|
const batch = NrfutilDeviceLib.batch();
|
|
55
|
-
if (
|
|
27
|
+
if (
|
|
28
|
+
getReadbackProtection(getState()) !==
|
|
29
|
+
'NRFDL_PROTECTION_STATUS_NONE'
|
|
30
|
+
) {
|
|
56
31
|
batch.recover('Application', {
|
|
57
32
|
onTaskBegin: () =>
|
|
58
33
|
logger.info(`Device protected, recovering device`),
|
|
@@ -94,11 +69,10 @@ const programDeviceWithFw =
|
|
|
94
69
|
|
|
95
70
|
await batch.run(device);
|
|
96
71
|
await NrfutilDeviceLib.reset(device);
|
|
72
|
+
|
|
97
73
|
onProgress(0, 'Updating readback protection');
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
);
|
|
101
|
-
dispatch(setReadbackProtected(readbackProtection));
|
|
74
|
+
const deviceInfo = await NrfutilDeviceLib.deviceInfo(device);
|
|
75
|
+
dispatch(setSelectedDeviceInfo(deviceInfo));
|
|
102
76
|
onProgress(0, 'Connecting to device');
|
|
103
77
|
} catch (programError) {
|
|
104
78
|
if (programError instanceof Error) {
|
|
@@ -150,7 +124,7 @@ export const jprogDeviceSetup = (
|
|
|
150
124
|
programDeviceWithFw(device, firmwareOption, onProgress)
|
|
151
125
|
),
|
|
152
126
|
})),
|
|
153
|
-
isExpectedFirmware: (device, deviceInfo) => dispatch => {
|
|
127
|
+
isExpectedFirmware: (device, deviceInfo) => (dispatch, getState) => {
|
|
154
128
|
const fwVersions = firmwareOptions(device, firmware, deviceInfo);
|
|
155
129
|
if (fwVersions.length === 0) {
|
|
156
130
|
return Promise.resolve({
|
|
@@ -159,40 +133,40 @@ export const jprogDeviceSetup = (
|
|
|
159
133
|
});
|
|
160
134
|
}
|
|
161
135
|
|
|
162
|
-
|
|
163
|
-
(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
imageInfo =>
|
|
169
|
-
typeof imageInfo.version === 'string' &&
|
|
170
|
-
imageInfo.version.includes(version.fwVersion)
|
|
171
|
-
)
|
|
172
|
-
);
|
|
136
|
+
if (
|
|
137
|
+
getReadbackProtection(getState()) !== 'NRFDL_PROTECTION_STATUS_NONE'
|
|
138
|
+
) {
|
|
139
|
+
logger.warn(
|
|
140
|
+
'Readback protection on device enabled. Unable to verify that the firmware version is correct.'
|
|
141
|
+
);
|
|
173
142
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
143
|
+
return Promise.resolve({
|
|
144
|
+
device,
|
|
145
|
+
validFirmware: hideDeviceSetupWhenProtected,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
179
148
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
149
|
+
return NrfutilDeviceLib.getFwInfo(device).then(info => {
|
|
150
|
+
if (info.imageInfoList.length > 0) {
|
|
151
|
+
const fw = fwVersions.find(version =>
|
|
152
|
+
info.imageInfoList.find(
|
|
153
|
+
imageInfo =>
|
|
154
|
+
typeof imageInfo.version === 'string' &&
|
|
155
|
+
imageInfo.version.includes(version.fwVersion)
|
|
156
|
+
)
|
|
157
|
+
);
|
|
189
158
|
|
|
190
159
|
return Promise.resolve({
|
|
191
160
|
device,
|
|
192
|
-
validFirmware:
|
|
161
|
+
validFirmware: fw !== undefined,
|
|
193
162
|
});
|
|
194
163
|
}
|
|
195
|
-
|
|
164
|
+
|
|
165
|
+
return Promise.resolve({
|
|
166
|
+
device,
|
|
167
|
+
validFirmware: false,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
196
170
|
},
|
|
197
171
|
tryToSwitchToApplicationMode: () => () => Promise.resolve(null),
|
|
198
172
|
});
|
|
@@ -22,6 +22,8 @@ export type DropdownProps<T> = {
|
|
|
22
22
|
defaultButtonLabel?: string;
|
|
23
23
|
items: DropdownItem<T>[];
|
|
24
24
|
onSelect: (item: DropdownItem<T>) => void;
|
|
25
|
+
transparentButtonBg?: boolean;
|
|
26
|
+
minWidth?: boolean;
|
|
25
27
|
disabled?: boolean;
|
|
26
28
|
selectedItem: DropdownItem<T>;
|
|
27
29
|
numItemsBeforeScroll?: number;
|
|
@@ -34,6 +36,8 @@ export default <T,>({
|
|
|
34
36
|
defaultButtonLabel = '',
|
|
35
37
|
items,
|
|
36
38
|
onSelect,
|
|
39
|
+
transparentButtonBg = false,
|
|
40
|
+
minWidth = false,
|
|
37
41
|
disabled = false,
|
|
38
42
|
selectedItem,
|
|
39
43
|
numItemsBeforeScroll = 0,
|
|
@@ -48,7 +52,11 @@ export default <T,>({
|
|
|
48
52
|
|
|
49
53
|
return (
|
|
50
54
|
<div
|
|
51
|
-
className={
|
|
55
|
+
className={classNames(
|
|
56
|
+
'tw-preflight tw-relative',
|
|
57
|
+
minWidth ? '' : 'tw-w-full',
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
52
60
|
onBlur={event => {
|
|
53
61
|
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
54
62
|
setIsActive(false);
|
|
@@ -61,7 +69,13 @@ export default <T,>({
|
|
|
61
69
|
<button
|
|
62
70
|
id={id}
|
|
63
71
|
type="button"
|
|
64
|
-
className=
|
|
72
|
+
className={classNames(
|
|
73
|
+
'tw-flex tw-items-center tw-justify-between tw-border-0',
|
|
74
|
+
minWidth ? '' : 'tw-w-full',
|
|
75
|
+
transparentButtonBg
|
|
76
|
+
? 'tw-bg-transparent'
|
|
77
|
+
: 'tw-h-8 tw-bg-gray-700 tw-px-2 tw-text-white'
|
|
78
|
+
)}
|
|
65
79
|
onClick={() => setIsActive(!isActive)}
|
|
66
80
|
disabled={disabled}
|
|
67
81
|
>
|
|
@@ -71,7 +85,7 @@ export default <T,>({
|
|
|
71
85
|
: selectedItem.label}
|
|
72
86
|
</span>
|
|
73
87
|
<span
|
|
74
|
-
className={`mdi mdi-chevron-down tw-text-lg ${classNames(
|
|
88
|
+
className={`mdi mdi-chevron-down tw-text-lg/none ${classNames(
|
|
75
89
|
isActive && 'tw-rotate-180'
|
|
76
90
|
)}`}
|
|
77
91
|
/>
|
|
@@ -93,8 +107,9 @@ export default <T,>({
|
|
|
93
107
|
numItemsBeforeScroll > 0 &&
|
|
94
108
|
items.length > numItemsBeforeScroll
|
|
95
109
|
}
|
|
96
|
-
className={`tw-text-while tw-absolute tw-
|
|
110
|
+
className={`tw-text-while tw-absolute tw-z-10 tw-border-t-2 tw-border-solid tw-border-gray-600 tw-bg-gray-700 tw-p-0 ${classNames(
|
|
97
111
|
styles.content,
|
|
112
|
+
minWidth ? '' : 'tw-right-0 tw-w-full',
|
|
98
113
|
!isActive && 'tw-hidden'
|
|
99
114
|
)}`}
|
|
100
115
|
>
|
|
@@ -57,6 +57,7 @@ interface Props {
|
|
|
57
57
|
onKeyboardIncrementAction?: () => string;
|
|
58
58
|
onKeyboardDecrementAction?: () => string;
|
|
59
59
|
className?: string;
|
|
60
|
+
title?: string;
|
|
60
61
|
textAlignLeft?: boolean;
|
|
61
62
|
onValidityChanged?: (validity: boolean) => void;
|
|
62
63
|
preventDefaultInvalidStyle?: boolean;
|
|
@@ -73,6 +74,7 @@ const InlineInput = React.forwardRef<HTMLInputElement, Props>(
|
|
|
73
74
|
onKeyboardIncrementAction = () => externalValue,
|
|
74
75
|
onKeyboardDecrementAction = () => externalValue,
|
|
75
76
|
className = '',
|
|
77
|
+
title,
|
|
76
78
|
textAlignLeft = false,
|
|
77
79
|
onValidityChanged,
|
|
78
80
|
preventDefaultInvalidStyle,
|
|
@@ -161,6 +163,7 @@ const InlineInput = React.forwardRef<HTMLInputElement, Props>(
|
|
|
161
163
|
<input
|
|
162
164
|
ref={ref}
|
|
163
165
|
type="text"
|
|
166
|
+
title={title}
|
|
164
167
|
className={classNames(
|
|
165
168
|
'inline-input',
|
|
166
169
|
preventDefaultInvalidStyle
|