Skip to content

Commit 96cd1cd

Browse files
Stacked serials option
1 parent 88e7585 commit 96cd1cd

11 files changed

Lines changed: 181 additions & 551 deletions

File tree

src/App.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ const logging = deployment.logging;
4141
const device = isMockDeviceMode()
4242
? new MockDeviceConnection()
4343
: createUSBConnection({ logging });
44+
// The connection library starts/stops its serial read loop as "serialdata"
45+
// listeners are added/removed. A remove-all-then-re-add cycle (which React
46+
// StrictMode does on every component mount in dev) races in the library:
47+
// the queued restart sees stale serialState and is silently dropped, leaving
48+
// serial off until a flash restarts it. Keep a permanent no-op listener so
49+
// the count never crosses zero; serial then runs exactly while connected,
50+
// which matches how the serial UI is shown anyway.
51+
device.addEventListener("serialdata", () => {});
4452

4553
const host = createHost(logging);
4654
const fs = new FileSystem(logging, host, fetchMicroPython);

src/messages/ui.en.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@
15621562
"serial-flashed": [
15631563
{
15641564
"type": 0,
1565-
"value": "micro:bit flashed"
1565+
"value": "flashed"
15661566
}
15671567
],
15681568
"serial-help-ctrl-c": [
@@ -1639,6 +1639,12 @@
16391639
"value": "The serial terminal shows errors and other output from the program running on your micro:bit. By default, it shows the most recent error from the program. Expand it to see all the output."
16401640
}
16411641
],
1642+
"serial-help-intro-simulator": [
1643+
{
1644+
"type": 0,
1645+
"value": "The serial terminal shows errors and other output from the program running in the micro:bit simulator. By default, it shows the most recent error from the program. Expand it to see all the output."
1646+
}
1647+
],
16421648
"serial-help-print": [
16431649
{
16441650
"type": 0,
@@ -1694,7 +1700,7 @@
16941700
"serial-ready-to-flash": [
16951701
{
16961702
"type": 0,
1697-
"value": "micro:bit ready to flash"
1703+
"value": "ready to flash"
16981704
}
16991705
],
17001706
"serial-error": [

src/serial/SerialArea.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: MIT
55
*/
66
import { Box, BoxProps, Flex } from "@chakra-ui/react";
7+
import { ComponentType } from "react";
78
import { backgroundColorTerm } from "../deployment/misc";
89
import { ConnectionStatus } from "@microbit/microbit-connection";
910
import { useConnectionStatus } from "../device/device-hooks";
@@ -21,11 +22,13 @@ interface SerialAreaProps extends BoxProps {
2122
showHintsAndTips?: boolean;
2223
tabOutRef: HTMLElement;
2324
/**
24-
* Whether this area is the visible one (shared device/simulator panel).
25-
* When it becomes visible again its terminal is re-fitted so content shows
26-
* without needing a scroll. Defaults to true for standalone use.
25+
* Icon and label identifying which serial source this is, shown in the bar
26+
* so stacked device/simulator areas can be told apart.
2727
*/
28-
active?: boolean;
28+
sourceIcon?: ComponentType;
29+
sourceLabel?: string;
30+
/** When true, the hints and tips dialog refers to the simulator. */
31+
simulator?: boolean;
2932
}
3033

3134
/**
@@ -45,7 +48,9 @@ const SerialArea = ({
4548
hideExpandTextOnTraceback = false,
4649
showHintsAndTips = true,
4750
tabOutRef,
48-
active = true,
51+
sourceIcon,
52+
sourceLabel,
53+
simulator,
4954
...props
5055
}: SerialAreaProps) => {
5156
const status = useConnectionStatus();
@@ -75,6 +80,9 @@ const SerialArea = ({
7580
expandDirection={expandDirection}
7681
hideExpandTextOnTraceback={hideExpandTextOnTraceback}
7782
showHintsAndTips={showHintsAndTips}
83+
sourceIcon={sourceIcon}
84+
sourceLabel={sourceLabel}
85+
simulator={simulator}
7886
/>
7987
<XTerm
8088
visibility={compact ? "hidden" : undefined}
@@ -83,7 +91,6 @@ const SerialArea = ({
8391
mr={1}
8492
fontSizePt={terminalFontSizePt}
8593
tabOutRef={tabOutRef}
86-
active={active}
8794
/>
8895
</Box>
8996
)}

src/serial/SerialBar.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* SPDX-License-Identifier: MIT
55
*/
66
import { BoxProps, HStack, IconButton, useDisclosure } from "@chakra-ui/react";
7-
import { useCallback, useRef } from "react";
7+
import { ComponentType, useCallback, useRef } from "react";
88
import { RiInformationLine } from "react-icons/ri";
99
import { useIntl } from "react-intl";
1010
import CollapsibleButton from "../common/CollapsibleButton";
@@ -26,6 +26,10 @@ interface SerialBarProps extends BoxProps {
2626
expandDirection: "up" | "down";
2727
hideExpandTextOnTraceback: boolean;
2828
showHintsAndTips: boolean;
29+
sourceIcon?: ComponentType;
30+
sourceLabel?: string;
31+
/** When true, the hints and tips dialog refers to the simulator. */
32+
simulator?: boolean;
2933
}
3034

3135
/**
@@ -39,6 +43,9 @@ const SerialBar = ({
3943
hideExpandTextOnTraceback,
4044
showHintsAndTips,
4145
expandDirection,
46+
sourceIcon,
47+
sourceLabel,
48+
simulator,
4249
...props
4350
}: SerialBarProps) => {
4451
const logging = useLogging();
@@ -63,6 +70,7 @@ const SerialBar = ({
6370
isOpen={helpDisclosure.isOpen}
6471
onClose={helpDisclosure.onClose}
6572
finalFocusRef={showHintsAndTips ? undefined : menuButtonRef}
73+
introId={simulator ? "serial-help-intro-simulator" : "serial-help-intro"}
6674
/>
6775
<HStack
6876
justifyContent="space-between"
@@ -81,6 +89,8 @@ const SerialBar = ({
8189
traceback={traceback}
8290
overflow="hidden"
8391
showSyncStatus={showSyncStatus}
92+
sourceIcon={sourceIcon}
93+
sourceLabel={sourceLabel}
8494
/>
8595

8696
<HStack>
@@ -123,10 +133,6 @@ const SerialBar = ({
123133
ref={menuButtonRef}
124134
compact={compact}
125135
onSizeChange={onSizeChange}
126-
// Move it to the menu if not shown more visibly.
127-
onShowHintsAndTips={
128-
!showHintsAndTips ? handleShowHintsAndTips : undefined
129-
}
130136
/>
131137
</HStack>
132138
</HStack>

src/serial/SerialHelp.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ interface SerialHelpDialogProps {
2323
isOpen: boolean;
2424
onClose: () => void;
2525
finalFocusRef?: React.RefObject<HTMLButtonElement>;
26+
/**
27+
* The intro paragraph message id, so the help can refer to the micro:bit or
28+
* the simulator depending on which serial area it was launched from.
29+
*/
30+
introId?: string;
2631
}
2732

2833
const formatValues = {
@@ -37,6 +42,7 @@ export const SerialHelpDialog = ({
3742
isOpen,
3843
onClose,
3944
finalFocusRef = undefined,
45+
introId = "serial-help-intro",
4046
}: SerialHelpDialogProps) => {
4147
return (
4248
<Modal
@@ -54,7 +60,7 @@ export const SerialHelpDialog = ({
5460
<ModalBody>
5561
<VStack spacing={5} alignItems="stretch">
5662
<Text>
57-
<FormattedMessage id="serial-help-intro" />
63+
<FormattedMessage id={introId} />
5864
</Text>
5965
<Text>
6066
<FormattedMessage

src/serial/SerialIndicators.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* SPDX-License-Identifier: MIT
55
*/
66
import { BoxProps, HStack, Icon, Text } from "@chakra-ui/react";
7+
import { ComponentType } from "react";
78
import { GoCheck } from "react-icons/go";
89
import {
910
RiErrorWarningLine,
@@ -18,6 +19,13 @@ interface SerialIndicatorsProps extends BoxProps {
1819
compact?: boolean;
1920
traceback?: Traceback | undefined;
2021
showSyncStatus: boolean;
22+
/**
23+
* Icon and label identifying which serial source this is (device or
24+
* simulator). When given, replaces the generic terminal icon so the two
25+
* stacked serial areas can be told apart.
26+
*/
27+
sourceIcon?: ComponentType;
28+
sourceLabel?: string;
2129
}
2230

2331
const syncMessages = {
@@ -38,6 +46,8 @@ const SerialIndicators = ({
3846
compact,
3947
traceback,
4048
showSyncStatus,
49+
sourceIcon,
50+
sourceLabel,
4151
...props
4252
}: SerialIndicatorsProps) => {
4353
const syncStatus = useSyncStatus();
@@ -47,7 +57,18 @@ const SerialIndicators = ({
4757
(!traceback || (traceback && syncStatus === SyncStatus.OUT_OF_SYNC));
4858
return (
4959
<HStack {...props}>
50-
<Icon m={1} as={RiTerminalBoxLine} fill="white" boxSize={5} />
60+
<Icon m={1} as={sourceIcon ?? RiTerminalBoxLine} fill="white" boxSize={5} />
61+
{sourceLabel && (
62+
<Text
63+
color="white"
64+
fontWeight="medium"
65+
whiteSpace="nowrap"
66+
mr={1}
67+
data-testid="serial-source-label"
68+
>
69+
<FormattedMessage id={sourceLabel} />
70+
</Text>
71+
)}
5172
<HStack spacing={0}>
5273
{compact && traceback && syncStatus === SyncStatus.IN_SYNC && (
5374
<>

0 commit comments

Comments
 (0)