Skip to content

Commit

Permalink
Merge pull request #295 from gbmhunter/develop
Browse files Browse the repository at this point in the history
Release of v4.11.0.
  • Loading branch information
gbmhunter authored Nov 19, 2023
2 parents c05ade5 + 1d445df commit 50169da
Show file tree
Hide file tree
Showing 40 changed files with 158,108 additions and 704 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
"autorun",
"autoscroll",
"chartjs",
"colour",
"colours",
"Consolas",
"DATETIME",
"Kofi",
"microcontroller",
"mred",
"mreset",
Expand All @@ -44,6 +47,7 @@
"scrollback",
"SDMMGN",
"testid",
"validatorjs"
"validatorjs",
"XTAL"
]
}
20 changes: 18 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## Unreleased

## [4.11.0] - 2023-11-19

### Added

- Added ability to filter rows of terminal text.
- Added more unit tests for the terminals.
- Added new performance profile before adding Filtering capability.
- Added input to change the vertical row padding.
- Display settings now persist across app restarts.
- Added responsive buttons to the terminal, the now hide the text when on small screens.

### Fixed

- Improved the modularity of the SingleTerminal class by removing it's dependency on the entire App class. This makes it easier to unit test.

## [4.10.1] - 2023-11-13

### Fixed
Expand Down Expand Up @@ -588,8 +603,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added auto-scroll to TX pane, closes #89.
- Added special delete behaviour for backspace button when in "send on enter" mode, closes #90.

[unreleased]: https://github.com/gbmhunter/NinjaTerm/compare/v4.10.1...HEAD
[4.10.1]: https://github.com/gbmhunter/NinjaTerm/compare/v4.9.0...v4.10.1
[unreleased]: https://github.com/gbmhunter/NinjaTerm/compare/v4.11.0...HEAD
[4.11.0]: https://github.com/gbmhunter/NinjaTerm/compare/v4.10.1...v4.11.0
[4.10.1]: https://github.com/gbmhunter/NinjaTerm/compare/v4.10.0...v4.10.1
[4.10.0]: https://github.com/gbmhunter/NinjaTerm/compare/v4.9.0...v4.10.0
[4.9.0]: https://github.com/gbmhunter/NinjaTerm/compare/v4.8.0...v4.9.0
[4.8.0]: https://github.com/gbmhunter/NinjaTerm/compare/v4.7.0...v4.8.0
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@ In FontCreator, make sure the setting _Tools->Options->Fonts->Exclude unused gly
* `#DC3545` (red): Primary colour, used for logo.
* `#E47F37` (orange): Secondary colour, used for buttons on homepage.

## styled_default is not a function

If you get the error:

```
Grid2.js:7 Uncaught TypeError: styled_default is not a function
at Grid2.js:7:26
```

Comment out the line:

```
include: ['@mui/material/Tooltip', '@emotion/styled', '@mui/material/Unstable_Grid2'],
```

in `vite.config.ts`. This should fix it. You can then uncomment the line again. Toggling this seems to fix this bug, which after reading online might be due to Vite.

## Extensions

* Prettier ESLint: Provides formatting of .tsx files.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ninjaterm",
"version": "4.10.1",
"version": "4.11.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.11.1",
Expand Down
156,974 changes: 156,974 additions & 0 deletions performance-profiles/2023-11-16 - v4.10.1 - Random 80 chars per row, 10rows per sec.json

Large diffs are not rendered by default.

34 changes: 16 additions & 18 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import { Button } from '@mui/material';
import packageDotJson from '../package.json'
// eslint-disable-next-line import/no-cycle
import { Settings, SettingsCategories } from './Settings/Settings';
import Terminal from './Terminal/SingleTerminal/SingleTerminal';
import Snackbar from './Snackbar';
import Graphing from './Graphing/Graphing';
import Logging from './Logging/Logging';
import FakePortsController from './FakePorts/FakePortsController';
import AppStorage from './Storage/AppStorage';
import { PortState } from './Settings/PortConfiguration/PortConfiguration';
import Terminals from './Terminals/Terminals';

declare global {
interface String {
Expand Down Expand Up @@ -74,12 +74,6 @@ export class App {

rxData = '';

txRxTerminal: Terminal;

rxTerminal: Terminal;

txTerminal: Terminal;

numBytesReceived: number;

numBytesTransmitted: number;
Expand Down Expand Up @@ -112,6 +106,8 @@ export class App {

shownMainPane: MainPanes;

terminals: Terminals;

graphing: Graphing;

logging: Logging;
Expand Down Expand Up @@ -139,9 +135,7 @@ export class App {

this.snackbar = new Snackbar();

this.txRxTerminal = new Terminal(this, true);
this.rxTerminal = new Terminal(this, false); // Not focusable
this.txTerminal = new Terminal(this, true);
this.terminals = new Terminals(this);

this.numBytesReceived = 0;
this.numBytesTransmitted = 0;
Expand Down Expand Up @@ -477,8 +471,8 @@ export class App {
// console.log('parseRxData() called. rxData=', rxData);
// Send received data to both the single TX/RX terminal
// and the RX terminal
this.txRxTerminal.parseData(rxData);
this.rxTerminal.parseData(rxData);
this.terminals.txRxTerminal.parseData(rxData);
this.terminals.rxTerminal.parseData(rxData);
this.graphing.parseData(rxData);
this.logging.handleRxData(rxData);
this.numBytesReceived += rxData.length;
Expand Down Expand Up @@ -529,10 +523,13 @@ export class App {
* determines what the user has pressed and what data to send out the
* serial port because of it.
*
* This needs to use an arrow function because it's being passed around
* as a callback. Tried to bind to this in constructor, didn't work.
*
* @param event The React keydown event.
* @returns Nothing.
*/
async handleTerminalKeyDown(event: React.KeyboardEvent) {
handleTerminalKeyDown = async (event: React.KeyboardEvent) => {
// console.log('handleTerminalKeyDown() called. event.key=', event.key);

// Capture all key presses and prevent default actions or bubbling.
Expand Down Expand Up @@ -593,15 +590,16 @@ export class App {
const writer = this.port?.writable?.getWriter();

const txDataAsUint8Array = Uint8Array.from(bytesToWrite);
console.log('Sending', txDataAsUint8Array);
await writer?.write(txDataAsUint8Array);

// Allow the serial port to be closed later.
writer?.releaseLock();
this.txTerminal.parseData(txDataAsUint8Array);
this.terminals.txTerminal.parseData(txDataAsUint8Array);
// Check if local TX echo is enabled, and if so, send the data to
// the combined single terminal.
if (this.settings.dataProcessingSettings.localTxEcho) {
this.txRxTerminal.parseData(txDataAsUint8Array);
this.terminals.txRxTerminal.parseData(txDataAsUint8Array);
}

// Also send this data to the logger, it may need it
Expand All @@ -614,9 +612,9 @@ export class App {
}

clearAllData() {
this.txRxTerminal.clearData();
this.txTerminal.clearData();
this.rxTerminal.clearData();
this.terminals.txRxTerminal.clearData();
this.terminals.txTerminal.clearData();
this.terminals.rxTerminal.clearData();
}

setTxRxScrollLock(trueFalse: boolean) {
Expand Down
4 changes: 3 additions & 1 deletion src/AppView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { App, MainPanes } from './App';
import { PortState } from './Settings/PortConfiguration/PortConfiguration';
import './App.css';
import SettingsDialog from './Settings/SettingsView';
import TerminalView from './Terminal/TerminalView';
import TerminalView from './Terminals/TerminalsView';
import GraphView from './Graphing/GraphingView';
import LogoImage from './logo192.png';
import styles from './AppView.module.css'
Expand Down Expand Up @@ -62,6 +62,8 @@ const darkTheme = createTheme({
},
},
},
MuiButtonBase: {
}
},
});

Expand Down
14 changes: 13 additions & 1 deletion src/Components/ApplyableTextField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export default abstract class ApplyableField {
isValid = false;
errorMsg = '';

onApplyChanged: () => void = () => {};

constructor(dispValue: string, schema: ZodType) {
this.schema = schema;
this.dispValue = '';
Expand All @@ -40,6 +42,14 @@ export default abstract class ApplyableField {
}
}

/**
* Sets a callback to be called when a new value is applied, that is also different
* to the previous value. Called once appliedValue has been updated.
*/
setOnApplyChanged(onApply: () => void) {
this.onApplyChanged = onApply;
}

abstract apply(): void;
}

Expand All @@ -58,8 +68,9 @@ export class ApplyableTextField extends ApplyableField {
}

apply() {
if (this.isValid) {
if (this.isValid && this.dispValue !== this.appliedValue) {
this.appliedValue = this.dispValue;
this.onApplyChanged();
}
}
}
Expand All @@ -82,5 +93,6 @@ export class ApplyableNumberField extends ApplyableField {
if (this.isValid) {
this.appliedValue = Number(this.dispValue);
}
this.onApplyChanged();
}
}
4 changes: 2 additions & 2 deletions src/Components/PortStateToButtonProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type PortStateToButtonPropsItem = {

export const portStateToButtonProps: { [key in PortState]: PortStateToButtonPropsItem; } = {
[PortState.CLOSED]: {
text: 'Open Port',
text: 'Open',
color: 'success',
icon: <PlayArrowIcon />,
},
Expand All @@ -21,7 +21,7 @@ export const portStateToButtonProps: { [key in PortState]: PortStateToButtonProp
icon: <StopIcon />,
},
[PortState.OPENED]: {
text: 'Close Port',
text: 'Close',
color: 'error',
icon: <StopIcon />,
},
Expand Down
92 changes: 88 additions & 4 deletions src/FakePorts/FakePortsController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ export default class FakePortsController {
constructor(app: App) {
this.app = app;

// hello world, 0.2lps
// hello world, 0.1lps
//=================================================================================
this.fakePorts.push(
new FakePort(
'hello world, 0.2lps',
'Sends "Hello, world!\\n" every 5 seconds.',
'hello world, 0.1lps',
'Sends "Hello, world!\\n" every 10 seconds.',
() => {
const intervalId = setInterval(() => {
const textToSend = "Hello, world!\n";
Expand All @@ -63,7 +63,33 @@ export default class FakePortsController {
bytesToSend.push(textToSend.charCodeAt(i));
}
app.parseRxData(Uint8Array.from(bytesToSend));
}, 5000);
}, 10000);
return intervalId;
},
(intervalId: NodeJS.Timer | null) => {
// Stop the interval
if (intervalId !== null) {
clearInterval(intervalId);
}
}
)
);

// hello world, 1lps
//=================================================================================
this.fakePorts.push(
new FakePort(
'hello world, 1lps',
'Sends "Hello, world!\\n" every 1 second.',
() => {
const intervalId = setInterval(() => {
const textToSend = "Hello, world!\n";
let bytesToSend = [];
for (let i = 0; i < textToSend.length; i++) {
bytesToSend.push(textToSend.charCodeAt(i));
}
app.parseRxData(Uint8Array.from(bytesToSend));
}, 1000);
return intervalId;
},
(intervalId: NodeJS.Timer | null) => {
Expand Down Expand Up @@ -425,6 +451,64 @@ export default class FakePortsController {
)
);

// mcu modules
//=================================================================================
// This intervalId is a hacky way of allowing for variable intervals
let intervalId: NodeJS.Timer | null = null;
this.fakePorts.push(
new FakePort(
'mcu modules',
'Fake MCU data from different modules.',
() => {
const messages = [
'TEMP: Measured temperature = 21C.',
'TEMP: Measured temperature = 24C.',
'\x1B[31;1mTEMP: ERROR - Temperature (56C) is too high.\x1B[0m',
'\x1B[31;1mGPS: ERROR - GPS signal has been lost.\x1B[0m',
'\x1B[31;1mSLEEP: ERROR - Requested sleep while peripherals still active.\x1B[0m',
'CLOCK: Time is now 14:23:45',
'CLOCK: Time is now 09:12:24',
'CLOCK: Time is now 03:02:54',
'WATCHDOG: Watchdog fed.',
'\x1B[31;1mWATCHDOG: ERROR - Watchdog expired. Resetting micro...\x1B[0m',
'BLU: New device found.',
'BLU: Connecting to new device...',
'BLU: Bluetooth connection refreshed.',
'BLU: Starting advertising...',
'SLEEP: In low power mode.',
'SLEEP: In medium power mode.',
'SLEEP: In high power mode.',
'SLEEP: Sleeping...',
'XTAL: External crystal frequency changed to 20MHz.',
'XTAL: External crystal frequency changed to 40MHz.',
'LED: Status LED set to mode: FLASHING.',
'LED: Status LED set to mode: CONTINUOUS.',
'LED: Status LED set to mode: OFF.',
];

const onTimeoutFn = () => {
const randomIndex = Math.floor(Math.random() * messages.length);
const rxData = new TextEncoder().encode(messages[randomIndex] + '\n');
app.parseRxData(rxData);
if (intervalId !== null) {
clearInterval(intervalId);
}
const randomWaitTime = Math.random()*1000;
intervalId = setInterval(onTimeoutFn, randomWaitTime);
}

intervalId = setInterval(onTimeoutFn, 1000);
return null;
},
(_: NodeJS.Timer | null) => {
// Stop the interval
if (intervalId !== null) {
clearInterval(intervalId);
}
}
)
);

makeAutoObservable(this);
}

Expand Down
Loading

0 comments on commit 50169da

Please sign in to comment.