@nordicsemiconductor/pc-nrfconnect-shared 121.0.0 → 123.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 (174) hide show
  1. package/Changelog.md +85 -0
  2. package/coverage/cobertura-coverage.xml +2276 -1778
  3. package/ipc/launcherConfig.ts +25 -0
  4. package/ipc/openWindow.ts +17 -1
  5. package/ipc/schema/packageJson.ts +26 -22
  6. package/main/index.ts +11 -5
  7. package/mocks/packageJsonMock.ts +1 -1
  8. package/nrfutil/device/__mocks__/device.ts +2 -0
  9. package/nrfutil/device/batch.ts +19 -9
  10. package/nrfutil/device/common.ts +32 -46
  11. package/nrfutil/device/device.ts +2 -0
  12. package/nrfutil/device/deviceInfo.ts +70 -0
  13. package/nrfutil/device/erase.ts +2 -2
  14. package/nrfutil/device/firmwareRead.ts +2 -2
  15. package/nrfutil/device/getCoreInfo.ts +2 -2
  16. package/nrfutil/device/getFwInfo.ts +2 -2
  17. package/nrfutil/device/getProtectionStatus.ts +2 -2
  18. package/nrfutil/device/list.ts +5 -31
  19. package/nrfutil/device/program.ts +4 -4
  20. package/nrfutil/device/recover.ts +2 -2
  21. package/nrfutil/device/reset.ts +2 -2
  22. package/nrfutil/device/setMcuState.ts +2 -5
  23. package/nrfutil/device/setProtectionStatus.ts +2 -2
  24. package/nrfutil/index.ts +1 -1
  25. package/nrfutil/moduleVersion.ts +22 -2
  26. package/nrfutil/sandbox.ts +52 -32
  27. package/nrfutil/sandboxTypes.ts +15 -1
  28. package/package.json +3 -2
  29. package/scripts/check-app-properties.ts +6 -6
  30. package/scripts/esbuild.ts +3 -3
  31. package/scripts/nordic-publish.js +23 -23
  32. package/scripts/nordic-publish.ts +3 -3
  33. package/scripts/release-shared.ts +2 -2
  34. package/src/About/ApplicationCard.tsx +3 -5
  35. package/src/About/DeviceCard.tsx +6 -5
  36. package/src/About/SupportCard.tsx +2 -2
  37. package/src/App/App.test.tsx +7 -0
  38. package/src/App/App.tsx +14 -27
  39. package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +12 -6
  40. package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +1 -1
  41. package/src/Device/DeviceSelector/DeviceList/Device.tsx +7 -5
  42. package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +23 -5
  43. package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +7 -6
  44. package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +26 -30
  45. package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +1 -2
  46. package/src/Device/DeviceSelector/DeviceSelector.test.tsx +17 -37
  47. package/src/Device/DeviceSelector/DeviceSelector.tsx +64 -21
  48. package/src/Device/DeviceSelector/Favorite.tsx +10 -10
  49. package/src/Device/DeviceSelector/basic-device-info.scss +0 -12
  50. package/src/Device/deviceInfo/deviceInfo.ts +2 -2
  51. package/src/Device/deviceLister.ts +111 -59
  52. package/src/Device/deviceSetup.ts +30 -13
  53. package/src/Device/deviceSlice.ts +157 -84
  54. package/src/Device/jprogOperations.ts +56 -27
  55. package/src/Device/sdfuOperations.ts +25 -31
  56. package/src/ErrorBoundary/ErrorBoundary.tsx +7 -13
  57. package/src/Feedback/sendFeedback.ts +2 -4
  58. package/src/InlineInput/NumberInlineInput.tsx +1 -1
  59. package/src/InlineInput/NumberInputWithDropdown.tsx +1 -2
  60. package/src/index.ts +4 -0
  61. package/src/logging/sendInitialLogMessages.ts +15 -13
  62. package/src/utils/appDetails.ts +22 -0
  63. package/src/utils/appDirs.ts +4 -4
  64. package/src/utils/launcherConfig.ts +17 -0
  65. package/src/utils/logLibVersions.ts +1 -1
  66. package/src/utils/packageJson.ts +52 -10
  67. package/src/utils/persistentStore.ts +21 -14
  68. package/src/utils/systemReport.ts +4 -6
  69. package/src/utils/usageData.ts +75 -167
  70. package/src/utils/usageDataCommon.ts +59 -0
  71. package/src/utils/usageDataMain.ts +117 -0
  72. package/src/utils/usageDataRenderer.ts +126 -0
  73. package/src/utils/useHotKey.ts +2 -2
  74. package/typings/generated/ipc/launcherConfig.d.ts +14 -0
  75. package/typings/generated/ipc/launcherConfig.d.ts.map +1 -0
  76. package/typings/generated/ipc/openWindow.d.ts +10 -4
  77. package/typings/generated/ipc/openWindow.d.ts.map +1 -1
  78. package/typings/generated/ipc/schema/packageJson.d.ts +34 -52
  79. package/typings/generated/ipc/schema/packageJson.d.ts.map +1 -1
  80. package/typings/generated/main/index.d.ts +8 -2
  81. package/typings/generated/main/index.d.ts.map +1 -1
  82. package/typings/generated/nrfutil/device/__mocks__/device.d.ts +1 -0
  83. package/typings/generated/nrfutil/device/__mocks__/device.d.ts.map +1 -1
  84. package/typings/generated/nrfutil/device/batch.d.ts +3 -2
  85. package/typings/generated/nrfutil/device/batch.d.ts.map +1 -1
  86. package/typings/generated/nrfutil/device/common.d.ts +7 -34
  87. package/typings/generated/nrfutil/device/common.d.ts.map +1 -1
  88. package/typings/generated/nrfutil/device/device.d.ts +14 -13
  89. package/typings/generated/nrfutil/device/device.d.ts.map +1 -1
  90. package/typings/generated/nrfutil/device/deviceInfo.d.ts +40 -0
  91. package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -0
  92. package/typings/generated/nrfutil/device/erase.d.ts +2 -2
  93. package/typings/generated/nrfutil/device/erase.d.ts.map +1 -1
  94. package/typings/generated/nrfutil/device/firmwareRead.d.ts +2 -2
  95. package/typings/generated/nrfutil/device/firmwareRead.d.ts.map +1 -1
  96. package/typings/generated/nrfutil/device/getCoreInfo.d.ts +2 -2
  97. package/typings/generated/nrfutil/device/getCoreInfo.d.ts.map +1 -1
  98. package/typings/generated/nrfutil/device/getFwInfo.d.ts +2 -2
  99. package/typings/generated/nrfutil/device/getFwInfo.d.ts.map +1 -1
  100. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +2 -2
  101. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
  102. package/typings/generated/nrfutil/device/list.d.ts +3 -3
  103. package/typings/generated/nrfutil/device/list.d.ts.map +1 -1
  104. package/typings/generated/nrfutil/device/program.d.ts +2 -2
  105. package/typings/generated/nrfutil/device/program.d.ts.map +1 -1
  106. package/typings/generated/nrfutil/device/recover.d.ts +2 -2
  107. package/typings/generated/nrfutil/device/recover.d.ts.map +1 -1
  108. package/typings/generated/nrfutil/device/reset.d.ts +2 -2
  109. package/typings/generated/nrfutil/device/reset.d.ts.map +1 -1
  110. package/typings/generated/nrfutil/device/setMcuState.d.ts +2 -2
  111. package/typings/generated/nrfutil/device/setMcuState.d.ts.map +1 -1
  112. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts +2 -2
  113. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts.map +1 -1
  114. package/typings/generated/nrfutil/index.d.ts +2 -1
  115. package/typings/generated/nrfutil/index.d.ts.map +1 -1
  116. package/typings/generated/nrfutil/moduleVersion.d.ts +4 -0
  117. package/typings/generated/nrfutil/moduleVersion.d.ts.map +1 -1
  118. package/typings/generated/nrfutil/sandbox.d.ts +2 -2
  119. package/typings/generated/nrfutil/sandbox.d.ts.map +1 -1
  120. package/typings/generated/nrfutil/sandboxTypes.d.ts +10 -1
  121. package/typings/generated/nrfutil/sandboxTypes.d.ts.map +1 -1
  122. package/typings/generated/src/About/ApplicationCard.d.ts.map +1 -1
  123. package/typings/generated/src/About/DeviceCard.d.ts.map +1 -1
  124. package/typings/generated/src/App/App.d.ts +0 -1
  125. package/typings/generated/src/App/App.d.ts.map +1 -1
  126. package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts.map +1 -1
  127. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +0 -1
  128. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts.map +1 -1
  129. package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts.map +1 -1
  130. package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts.map +1 -1
  131. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +0 -1
  132. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts.map +1 -1
  133. package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts.map +1 -1
  134. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +0 -1
  135. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts.map +1 -1
  136. package/typings/generated/src/Device/deviceLister.d.ts +1 -15
  137. package/typings/generated/src/Device/deviceLister.d.ts.map +1 -1
  138. package/typings/generated/src/Device/deviceSetup.d.ts +7 -6
  139. package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
  140. package/typings/generated/src/Device/deviceSlice.d.ts +16 -15
  141. package/typings/generated/src/Device/deviceSlice.d.ts.map +1 -1
  142. package/typings/generated/src/Device/jprogOperations.d.ts.map +1 -1
  143. package/typings/generated/src/Device/sdfuOperations.d.ts.map +1 -1
  144. package/typings/generated/src/ErrorBoundary/ErrorBoundary.d.ts.map +1 -1
  145. package/typings/generated/src/Feedback/sendFeedback.d.ts.map +1 -1
  146. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +1 -1
  147. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
  148. package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts.map +1 -1
  149. package/typings/generated/src/index.d.ts +3 -1
  150. package/typings/generated/src/index.d.ts.map +1 -1
  151. package/typings/generated/src/logging/sendInitialLogMessages.d.ts.map +1 -1
  152. package/typings/generated/src/utils/appDetails.d.ts +4 -0
  153. package/typings/generated/src/utils/appDetails.d.ts.map +1 -0
  154. package/typings/generated/src/utils/appDirs.d.ts +1 -1
  155. package/typings/generated/src/utils/appDirs.d.ts.map +1 -1
  156. package/typings/generated/src/utils/launcherConfig.d.ts +4 -0
  157. package/typings/generated/src/utils/launcherConfig.d.ts.map +1 -0
  158. package/typings/generated/src/utils/packageJson.d.ts +30 -7
  159. package/typings/generated/src/utils/packageJson.d.ts.map +1 -1
  160. package/typings/generated/src/utils/persistentStore.d.ts +3 -2
  161. package/typings/generated/src/utils/persistentStore.d.ts.map +1 -1
  162. package/typings/generated/src/utils/systemReport.d.ts +1 -1
  163. package/typings/generated/src/utils/systemReport.d.ts.map +1 -1
  164. package/typings/generated/src/utils/usageData.d.ts +8 -65
  165. package/typings/generated/src/utils/usageData.d.ts.map +1 -1
  166. package/typings/generated/src/utils/usageDataCommon.d.ts +27 -0
  167. package/typings/generated/src/utils/usageDataCommon.d.ts.map +1 -0
  168. package/typings/generated/src/utils/usageDataMain.d.ts +10 -0
  169. package/typings/generated/src/utils/usageDataMain.d.ts.map +1 -0
  170. package/typings/generated/src/utils/usageDataRenderer.d.ts +10 -0
  171. package/typings/generated/src/utils/usageDataRenderer.d.ts.map +1 -0
  172. package/src/Device/DeviceSelector/DeviceList/device.scss +0 -28
  173. package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +0 -33
  174. package/src/Device/DeviceSelector/favorite.scss +0 -17
@@ -14,7 +14,7 @@ import semver from 'semver';
14
14
  import calculateShasum from 'shasum';
15
15
 
16
16
  import { AppInfo, SourceJson } from '../ipc/MetaFiles';
17
- import { PackageJson } from '../ipc/schema/packageJson';
17
+ import { PackageJsonApp } from '../ipc/schema/packageJson';
18
18
  import checkAppProperties from './check-app-properties';
19
19
 
20
20
  interface LegacyAppInfo {
@@ -41,7 +41,7 @@ interface App {
41
41
  releaseNotesFilename: string;
42
42
  iconFilename: string;
43
43
  isOfficial: boolean;
44
- packageJson: PackageJson;
44
+ packageJson: PackageJsonApp;
45
45
  }
46
46
 
47
47
  const client = new FtpClient();
@@ -113,7 +113,7 @@ const parseOptions = (): Options => {
113
113
  };
114
114
  };
115
115
 
116
- const readPackageJson = (): PackageJson =>
116
+ const readPackageJson = (): PackageJsonApp =>
117
117
  JSON.parse(fs.readFileSync('./package.json', 'utf-8'));
118
118
 
119
119
  const packPackage = () => {
@@ -25,7 +25,7 @@
25
25
  */
26
26
  import { execSync, spawnSync } from 'node:child_process';
27
27
 
28
- import { PackageJson } from '../ipc/schema/packageJson';
28
+ import { PackageJsonApp } from '../ipc/schema/packageJson';
29
29
 
30
30
  const logError = (message: string) => {
31
31
  console.error(message);
@@ -88,7 +88,7 @@ export const packageJsonIsCorrect = (
88
88
  }
89
89
  ) => {
90
90
  const expectedVersionString = `${expectedVersionNumber}.0.0`;
91
- const actualVersionString = parseJson<PackageJson>(packageJson).version;
91
+ const actualVersionString = parseJson<PackageJsonApp>(packageJson).version;
92
92
 
93
93
  return equality(
94
94
  expectedVersionString,
@@ -6,12 +6,10 @@
6
6
 
7
7
  import React, { useEffect, useState } from 'react';
8
8
 
9
- import {
10
- AppDetailsFromLauncher,
11
- inMain as appDetails,
12
- } from '../../ipc/appDetails';
9
+ import { AppDetailsFromLauncher } from '../../ipc/appDetails';
13
10
  import Card from '../Card/Card';
14
11
  import FactoryResetButton from '../FactoryReset/FactoryResetButton';
12
+ import appDetails from '../utils/appDetails';
15
13
  import AboutButton from './AboutButton';
16
14
  import Section from './Section';
17
15
  import ShortcutButton from './ShortcutButton';
@@ -20,7 +18,7 @@ export default () => {
20
18
  const [appInfo, setAppInfo] = useState<AppDetailsFromLauncher>();
21
19
 
22
20
  useEffect(() => {
23
- appDetails.getAppDetails().then(setAppInfo);
21
+ appDetails().then(setAppInfo);
24
22
  }, [setAppInfo]);
25
23
 
26
24
  if (appInfo == null) return null;
@@ -13,7 +13,7 @@ import {
13
13
  deviceInfo,
14
14
  productPageUrl,
15
15
  } from '../Device/deviceInfo/deviceInfo';
16
- import { selectedDevice } from '../Device/deviceSlice';
16
+ import { selectedDevice, selectedDeviceInfo } from '../Device/deviceSlice';
17
17
  import AboutButton from './AboutButton';
18
18
  import Section from './Section';
19
19
 
@@ -27,6 +27,7 @@ const memorySize = (memoryInBytes: number) => {
27
27
 
28
28
  export default () => {
29
29
  const device = useSelector(selectedDevice);
30
+ const info = useSelector(selectedDeviceInfo);
30
31
 
31
32
  if (device == null) {
32
33
  return (
@@ -36,7 +37,7 @@ export default () => {
36
37
  );
37
38
  }
38
39
 
39
- const pca = device.jlink?.boardVersion;
40
+ const pca = device.devkit?.boardVersion;
40
41
  const { name, cores } = deviceInfo(device);
41
42
 
42
43
  return (
@@ -47,13 +48,13 @@ export default () => {
47
48
  <Section title="PCA">{pca || 'Unknown'}</Section>
48
49
  <Section title="Cores">{cores || 'Unknown'}</Section>
49
50
 
50
- {device.hwInfo && (
51
+ {info?.hwInfo && (
51
52
  <>
52
53
  <Section title="RAM">
53
- {memorySize(device.hwInfo.ramSize)}
54
+ {memorySize(info.hwInfo.ramSize)}
54
55
  </Section>
55
56
  <Section title="Flash">
56
- {memorySize(device.hwInfo.romSize)}
57
+ {memorySize(info.hwInfo.romSize)}
57
58
  </Section>
58
59
  </>
59
60
  )}
@@ -12,8 +12,8 @@ import NrfutilDeviceLib from '../../nrfutil/device/device';
12
12
  import Button from '../Button/Button';
13
13
  import Card from '../Card/Card';
14
14
  import {
15
- deviceInfo,
16
15
  getDevices,
16
+ selectedDevice,
17
17
  selectedSerialNumber,
18
18
  } from '../Device/deviceSlice';
19
19
  import { isLoggingVerbose, setIsLoggingVerbose } from '../Log/logSlice';
@@ -28,7 +28,7 @@ export default () => {
28
28
  const devices = useSelector(getDevices);
29
29
  const currentSerialNumber = useSelector(selectedSerialNumber);
30
30
  const verboseLogging = useSelector(isLoggingVerbose);
31
- const currentDevice = useSelector(deviceInfo);
31
+ const currentDevice = useSelector(selectedDevice);
32
32
 
33
33
  return (
34
34
  <Card title="Support">
@@ -7,6 +7,7 @@
7
7
  import React from 'react';
8
8
  import { screen } from '@testing-library/react';
9
9
 
10
+ import packageJsonFromShared from '../../package.json';
10
11
  import render from '../../test/testrenderer';
11
12
  import App, { Pane } from './App';
12
13
 
@@ -17,6 +18,12 @@ jest.mock('../Log/LogViewer', () => ({
17
18
 
18
19
  jest.mock('../logging/index.ts', () => ({
19
20
  initialise: () => {},
21
+ debug: () => {},
22
+ }));
23
+
24
+ jest.mock('../utils/packageJson', () => ({
25
+ isLauncher: () => false,
26
+ packageJson: () => packageJsonFromShared,
20
27
  }));
21
28
 
22
29
  const renderApp = (panes: Pane[]) => {
package/src/App/App.tsx CHANGED
@@ -30,9 +30,8 @@ import LogViewer from '../Log/LogViewer';
30
30
  import logger from '../logging';
31
31
  import NavBar from '../NavBar/NavBar';
32
32
  import classNames from '../utils/classNames';
33
- import packageJson from '../utils/packageJson';
34
33
  import { getPersistedCurrentPane } from '../utils/persistentStore';
35
- import { init as usageDataInit, setUsageLogger } from '../utils/usageData';
34
+ import usageData from '../utils/usageData';
36
35
  import useHotKey from '../utils/useHotKey';
37
36
  import {
38
37
  currentPane as currentPaneSelector,
@@ -49,19 +48,6 @@ import './app.scss';
49
48
  import './shared.scss';
50
49
  import './tailwind.css';
51
50
 
52
- let usageDataAlreadyInitialised = false;
53
- const initialiseUsageData = () => {
54
- if (!usageDataAlreadyInitialised) {
55
- usageDataAlreadyInitialised = true;
56
- try {
57
- usageDataInit(packageJson());
58
- } catch (error) {
59
- // No need to display the error message for the user
60
- console.log(error);
61
- }
62
- }
63
- };
64
-
65
51
  export interface PaneProps {
66
52
  active: boolean;
67
53
  }
@@ -77,7 +63,6 @@ interface ConnectedAppProps {
77
63
  panes: Pane[];
78
64
  sidePanel?: ReactNode;
79
65
  showLogByDefault?: boolean;
80
- reportUsageData?: boolean;
81
66
  documentation?: ReactNode[];
82
67
  feedback?: boolean | FeedbackPaneProps;
83
68
  children?: ReactNode;
@@ -89,25 +74,25 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
89
74
  panes,
90
75
  sidePanel,
91
76
  showLogByDefault = true,
92
- reportUsageData = false,
93
77
  documentation,
94
78
  feedback,
95
79
  children,
96
80
  autoReselectByDefault = false,
97
81
  }) => {
98
- const initialisedLogger = useRef(false);
82
+ const initApp = useRef(false);
99
83
 
100
- if (!initialisedLogger.current) {
84
+ if (!initApp.current) {
101
85
  logger.initialise();
102
86
  setNrfutilLogger(logger);
103
- setUsageLogger(logger);
104
- initialisedLogger.current = true;
87
+ usageData.setLogger(logger);
88
+ initApp.current = true;
105
89
  }
106
90
 
107
91
  usePersistedPane();
108
92
  const isLogVisible = useSelector(isLogVisibleSelector);
109
93
  const currentPane = useSelector(currentPaneSelector);
110
94
  const allPanes = useAllPanes(panes, documentation, feedback);
95
+ const paneName = useRef(allPanes.map(({ name }) => name));
111
96
  const dispatch = useDispatch();
112
97
 
113
98
  useHotKey({
@@ -117,6 +102,14 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
117
102
  action: openWindow.openLauncher,
118
103
  });
119
104
 
105
+ useEffect(() => {
106
+ paneName.current = allPanes.map(({ name }) => name);
107
+ }, [allPanes]);
108
+
109
+ useEffect(() => {
110
+ usageData.sendPageView(paneName.current[currentPane]);
111
+ }, [currentPane]);
112
+
120
113
  useEffect(() => {
121
114
  dispatch(setAutoReselect(autoReselectByDefault));
122
115
  }, [dispatch, autoReselectByDefault]);
@@ -134,12 +127,6 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
134
127
  const isSidePanelVisible =
135
128
  useSelector(isSidePanelVisibleSelector) && currentSidePanel;
136
129
 
137
- useEffect(() => {
138
- if (reportUsageData) {
139
- initialiseUsageData();
140
- }
141
- }, [reportUsageData]);
142
-
143
130
  return (
144
131
  <div className="core19-app">
145
132
  <NavBar deviceSelect={deviceSelect} />
@@ -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-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
  });