Skip to content

Commit

Permalink
Made it possible to change baud before flashing
Browse files Browse the repository at this point in the history
  • Loading branch information
breiler committed Nov 3, 2024
1 parent ad80862 commit 3bb0764
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 149 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/components/fields/BooleanField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const BooleanField = ({
</Form.Label>
<Col sm="9">
<Form.Check
type="switch"
aria-label={placeholder}
onChange={(event) =>
setValue(Boolean(event.target.checked))
Expand Down
89 changes: 89 additions & 0 deletions src/components/installermodal/ConfirmPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from "react";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faClose, faSave } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, Col, Modal } from "react-bootstrap";
import { useLocalStorage } from "../../hooks/useLocalStorage";
import {
FirmwareChoice,
GithubRelease,
GithubReleaseManifest
} from "../../services";
import SelectField from "../fields/SelectField";

type Props = {
onCancel: () => void;
onInstall: (baud: number) => Promise<void>;
release: GithubRelease;
manifest: GithubReleaseManifest;
choice: FirmwareChoice;
};

const ConfirmPage = ({ release, choice, onInstall, onCancel }: Props) => {
const [baud, setBaud] = useLocalStorage("baud", "921600");

return (
<>
<Modal.Body>
<h3>Confirm installation</h3>
<p>
This will install the firmware{" "}
<strong>{release.name}</strong> to the controller. It will{" "}
{!choice.erase && <strong>not</strong>} erase the
controller.
</p>

<Col lg={8}>
<SelectField
label="Baud rate"
options={[
{
name: "921600",
value: "921600"
},
{ name: "115200", value: "115200" }
]}
value={baud}
setValue={(value) => setBaud(value)}
></SelectField>

{/*manifest.files &&
Object.keys(manifest.files).map((key) => {
return (
<BooleanField
setValue={(value: boolean) => {
if (value) {
setFiles((files) => [
...files,
key
]);
} else {
setFiles((files) =>
files.filter((s) => s !== key)
);
}
}}
label={"Install " + key}
value={files.includes(key)}
/>
);
})*/}
</Col>
</Modal.Body>
<Modal.Footer>
<Button onClick={onCancel} variant="secondary">
<FontAwesomeIcon icon={faClose as IconDefinition} /> Cancel
</Button>
<Button onClick={() => onInstall(+baud)}>
<FontAwesomeIcon
icon={faSave as IconDefinition}
style={{ marginRight: "8px" }}
/>
Install
</Button>
</Modal.Footer>
</>
);
};

export default ConfirmPage;
209 changes: 152 additions & 57 deletions src/components/installermodal/InstallerModal.tsx
Original file line number Diff line number Diff line change
@@ -1,93 +1,188 @@
import React, { useState } from "react";
import React, { useContext, useState } from "react";
import { Button, Spinner } from "../../components";
import { Modal } from "react-bootstrap";
import { InstallerState } from "../../services";
import {
ControllerStatus,
FirmwareChoice,
GithubRelease,
GithubReleaseManifest,
InstallService,
InstallerState
} from "../../services";
import { Progress } from "../../panels";
import { FlashProgress } from "../../services/FlashService";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faBan } from "@fortawesome/free-solid-svg-icons";
import BootloaderInfo from "../../panels/bootloaderinfo/BootloaderInfo";
import Log from "../log/Log";
import { ControllerServiceContext } from "../../context/ControllerServiceContext";
import ConfirmPage from "./ConfirmPage";

type InstallerModalProps = {
state: InstallerState;
progress: FlashProgress;
errorMessage: string | undefined;
onClose: () => void;
log: string;
onCancel: () => void;
release: GithubRelease;
manifest: GithubReleaseManifest;
choice: FirmwareChoice;
};

const initialProgress: FlashProgress = {
fileIndex: 0,
fileCount: 1,
fileName: "",
fileProgress: 0
};

const InstallerModal = ({
state,
progress,
errorMessage,
onClose,
log
onCancel,
release,
manifest,
choice
}: InstallerModalProps) => {
const [showLog, setShowLog] = useState<boolean>(false);
const controllerService = useContext(ControllerServiceContext);
const [state, setState] = useState(InstallerState.SELECT_PACKAGE);
const [progress, setProgress] = useState<FlashProgress>(initialProgress);
const [errorMessage, setErrorMessage] = useState<string | undefined>();
const [log, setLog] = useState("");

const onLogData = (data: string) => {
setLog((l) => l + data);
console.log(data);
};

const onInstall = async (baud: number) => {
try {
await controllerService?.disconnect(false);
} catch (error) {
// never mind
}

let hasErrors = false;
await InstallService.installChoice(
release,
controllerService!.serialPort!,
manifest,
choice,
setProgress,
setState,
onLogData,
baud
).catch((error) => {
setErrorMessage(error);
setState(InstallerState.ERROR);
hasErrors = true;
});

try {
const status = await controllerService?.connect();
if (status !== ControllerStatus.CONNECTED) {
setErrorMessage(
"An error occured while reconnecting, please reboot the controller"
);
setState(InstallerState.ERROR);
}

if (!hasErrors) {
setState(InstallerState.DONE);
}
} catch (error) {
setErrorMessage(error);
setState(InstallerState.ERROR);
}
};

return (
<Modal centered show={true} size="lg">
<Modal.Body>
{(state === InstallerState.DOWNLOADING ||
state === InstallerState.CHECKING_SIGNATURES) && (
<>
<h3>Downloading</h3>
<p>
Downloading package... <Spinner />
</p>
</>
)}
{state === InstallerState.ENTER_FLASH_MODE && (
{state === InstallerState.SELECT_PACKAGE && (
<ConfirmPage
release={release}
choice={choice}
manifest={manifest}
onCancel={onCancel}
onInstall={onInstall}
/>
)}
{(state === InstallerState.DOWNLOADING ||
state === InstallerState.CHECKING_SIGNATURES) && (
<Modal.Body>
<h3>Downloading</h3>
<p>
Downloading package... <Spinner />
</p>
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
)}

{state === InstallerState.ENTER_FLASH_MODE && (
<Modal.Body>
<BootloaderInfo />
)}
{state === InstallerState.FLASHING && (
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
)}

{state === InstallerState.FLASHING && (
<Modal.Body>
<Progress progress={progress} status={state} />
)}
{state === InstallerState.RESTARTING && (
<>
<h3>Restarting</h3>
<p>
Waiting for controller restart... <Spinner />
</p>
</>
)}
{state === InstallerState.DONE && (
<>
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
)}
{state === InstallerState.RESTARTING && (
<Modal.Body>
<h3>Restarting</h3>
<p>
Waiting for controller restart... <Spinner />
</p>
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
)}
{state === InstallerState.DONE && (
<>
<Modal.Body>
<h3>Done</h3>
<p>
The controller has been successfully installed and
is ready to be used.
</p>
</>
)}
{state === InstallerState.ERROR && (
<>
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
<Modal.Footer>
<Button onClick={onClose}>
<>Continue</>
</Button>
</Modal.Footer>
</>
)}
{state === InstallerState.ERROR && (
<>
<Modal.Body>
<h3>Error!</h3>
<div className="alert alert-danger">
<FontAwesomeIcon icon={faBan as IconDefinition} />{" "}
{errorMessage}
</div>
</>
)}
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
{state === InstallerState.DONE && (
<Modal.Footer>
<Button onClick={onClose}>
<>Continue</>
</Button>
</Modal.Footer>
)}
{state === InstallerState.ERROR && (
<Modal.Footer>
<Button onClick={onClose}>
<>Close</>
</Button>
</Modal.Footer>
<Log show={showLog} onShow={setShowLog}>
{log}
</Log>
</Modal.Body>
<Modal.Footer>
<Button onClick={onClose}>
<>Close</>
</Button>
</Modal.Footer>
</>
)}
</Modal>
);
Expand Down
5 changes: 2 additions & 3 deletions src/components/ribbon/Ribbon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from "react";
import React, { ReactNode } from "react";
import "./Ribbon.scss";
import { ReactElement } from "react-markdown/lib/react-markdown";

type Props = { children: ReactElement; variant: string };
type Props = { children: ReactNode; variant?: string };

const Ribbon = ({ children, variant = "danger" }: Props) => {
return (
Expand Down
5 changes: 4 additions & 1 deletion src/hooks/useLocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ function getStorageValue(key, defaultValue) {
return initial || defaultValue;
}

export const useLocalStorage = (key, defaultValue) => {
export const useLocalStorage = (
key,
defaultValue
): [string, (value: string) => void] => {
const [value, setValue] = useState(() => {
return getStorageValue(key, defaultValue);
});
Expand Down
Loading

0 comments on commit 3bb0764

Please sign in to comment.