Skip to content

Commit 8c91be9

Browse files
committed
serial monitor style and perfo
1 parent 483c0a3 commit 8c91be9

File tree

3 files changed

+50
-34
lines changed

3 files changed

+50
-34
lines changed

arduino-ide-extension/src/browser/monitor/monitor-utils.ts

+25-7
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,25 @@ export function messageToLines(
77
): [Line[], number] {
88
const linesToAdd: Line[] = prevLines.length
99
? [prevLines[prevLines.length - 1]]
10-
: [{ message: '' }];
10+
: [{ message: '', lineLen: 0 }];
1111
let charCount = 0;
1212

1313
for (const message of messages) {
14-
charCount += message.length;
14+
const messageLen = message.length;
15+
charCount += messageLen;
1516
const lastLine = linesToAdd[linesToAdd.length - 1];
1617

18+
// if the previous messages ends with "separator" add a new line
1719
if (lastLine.message.charAt(lastLine.message.length - 1) === separator) {
18-
linesToAdd.push({ message, timestamp: new Date() });
20+
linesToAdd.push({
21+
message,
22+
timestamp: new Date(),
23+
lineLen: messageLen,
24+
});
1925
} else {
26+
// concatenate to the last line
2027
linesToAdd[linesToAdd.length - 1].message += message;
28+
linesToAdd[linesToAdd.length - 1].lineLen += messageLen;
2129
if (!linesToAdd[linesToAdd.length - 1].timestamp) {
2230
linesToAdd[linesToAdd.length - 1].timestamp = new Date();
2331
}
@@ -33,16 +41,26 @@ export function truncateLines(
3341
charCount: number
3442
): [Line[], number] {
3543
let charsToDelete = charCount - SerialMonitorOutput.MAX_CHARACTERS;
44+
let lineIndex = 0;
3645
while (charsToDelete > 0) {
37-
const firstLineLength = lines[0]?.message?.length;
46+
const firstLineLength = lines[lineIndex]?.lineLen;
47+
48+
if (charsToDelete >= firstLineLength) {
49+
// every time a full line to delete is found, move the index.
50+
lineIndex++;
51+
charsToDelete -= firstLineLength;
52+
charCount -= firstLineLength;
53+
continue;
54+
}
55+
56+
// delete all previous lines
57+
lines.splice(0, lineIndex);
58+
3859
const newFirstLine = lines[0]?.message?.substring(charsToDelete);
3960
const deletedCharsCount = firstLineLength - newFirstLine.length;
4061
charCount -= deletedCharsCount;
4162
charsToDelete -= deletedCharsCount;
4263
lines[0].message = newFirstLine;
43-
if (!newFirstLine?.length) {
44-
lines.shift();
45-
}
4664
}
4765
return [lines, charCount];
4866
}

arduino-ide-extension/src/browser/monitor/serial-monitor-send-output.tsx

+20-27
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { MonitorConnection } from './monitor-connection';
88
import dateFormat = require('dateformat');
99
import { messageToLines, truncateLines } from './monitor-utils';
1010

11-
export type Line = { message: string; timestamp?: Date };
11+
export type Line = { message: string; timestamp?: Date; lineLen: number };
1212

1313
export class SerialMonitorOutput extends React.Component<
1414
SerialMonitorOutput.Props,
@@ -17,11 +17,12 @@ export class SerialMonitorOutput extends React.Component<
1717
/**
1818
* Do not touch it. It is used to be able to "follow" the serial monitor log.
1919
*/
20-
protected anchor: HTMLElement | null;
2120
protected toDisposeBeforeUnmount = new DisposableCollection();
21+
private listRef: React.RefObject<any>;
2222

2323
constructor(props: Readonly<SerialMonitorOutput.Props>) {
2424
super(props);
25+
this.listRef = React.createRef();
2526
this.state = {
2627
lines: [],
2728
timestamp: this.props.monitorModel.timestamp,
@@ -35,7 +36,7 @@ export class SerialMonitorOutput extends React.Component<
3536
<AutoSizer>
3637
{({ height, width }) => (
3738
<List
38-
className="List"
39+
className="serial-monitor-messages"
3940
height={height}
4041
itemData={
4142
{
@@ -46,22 +47,13 @@ export class SerialMonitorOutput extends React.Component<
4647
itemCount={this.state.lines.length}
4748
itemSize={20}
4849
width={width}
50+
ref={this.listRef}
51+
onItemsRendered={this.scrollToBottom}
4952
>
5053
{Row}
5154
</List>
5255
)}
5356
</AutoSizer>
54-
{/* <div style={{ whiteSpace: 'pre', fontFamily: 'monospace' }}>
55-
{this.state.lines.map((line, i) => (
56-
<MonitorTextLine text={line} key={i} />
57-
))}
58-
</div> */}
59-
<div
60-
style={{ float: 'left', clear: 'both' }}
61-
ref={(element) => {
62-
this.anchor = element;
63-
}}
64-
/>
6557
</React.Fragment>
6658
);
6759
}
@@ -94,25 +86,23 @@ export class SerialMonitorOutput extends React.Component<
9486
const { timestamp } = this.props.monitorModel;
9587
this.setState({ timestamp });
9688
}
89+
if (property === 'autoscroll') {
90+
this.scrollToBottom();
91+
}
9792
}),
9893
]);
9994
}
10095

101-
componentDidUpdate(): void {
102-
this.scrollToBottom();
103-
}
104-
10596
componentWillUnmount(): void {
10697
// TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout?
10798
this.toDisposeBeforeUnmount.dispose();
10899
}
109100

110-
protected scrollToBottom(): void {
111-
if (this.props.monitorModel.autoscroll && this.anchor) {
112-
this.anchor.scrollIntoView();
113-
// this.listRef.current.scrollToItem(this.state.lines.length);
101+
scrollToBottom = ((): void => {
102+
if (this.listRef.current && this.props.monitorModel.autoscroll) {
103+
this.listRef.current.scrollToItem(this.state.lines.length, 'end');
114104
}
115-
}
105+
}).bind(this);
116106
}
117107

118108
const Row = ({
@@ -129,10 +119,13 @@ const Row = ({
129119
`${dateFormat(data.lines[index].timestamp, 'H:M:ss.l')} -> `) ||
130120
'';
131121
return (
132-
<div style={style}>
133-
{timestamp}
134-
{data.lines[index].message}
135-
</div>
122+
(data.lines[index].lineLen && (
123+
<div style={style}>
124+
{timestamp}
125+
{data.lines[index].message}
126+
</div>
127+
)) ||
128+
null
136129
);
137130
};
138131

arduino-ide-extension/src/browser/style/monitor.css

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
flex-direction: column;
1010
}
1111

12+
.serial-monitor-messages {
13+
white-space: 'pre';
14+
font-family: monospace
15+
}
16+
1217
.serial-monitor .head {
1318
display: flex;
1419
padding: 5px;

0 commit comments

Comments
 (0)