Skip to content
24 changes: 24 additions & 0 deletions lang/ui.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,10 @@
"defaultMessage": "Training model…",
"description": "Progress title"
},
"continue-makecode-action": {
"defaultMessage": "Continue to MakeCode",
"description": "Continue to MakeCode editor button text"
},
"cookies-action": {
"defaultMessage": "Cookies",
"description": "Action to show dialog to choose website cookie preferences"
Expand Down Expand Up @@ -763,6 +767,26 @@
"defaultMessage": "Home page",
"description": ""
},
"incompatible-device-body-1": {
"defaultMessage": "Continue to MakeCode to edit the program. You can then save the project hex which can be downloaded onto a micro:bit V2.",
"description": "Incompatible device dialog body text"
},
"incompatible-device-body-2": {
"defaultMessage": "Alternatively, <link>save the project hex</link> without using MakeCode.",
"description": "Incompatible device dialog body text"
},
"incompatible-device-body-alt": {
"defaultMessage": "Go back to select a different micro:bit, or <link>save the project hex</link> which can be downloaded onto a micro:bit V2 later.",
"description": "Incompatible device dialog body text"
},
"incompatible-device-heading": {
"defaultMessage": "Incompatible device",
"description": "Incompatible device dialog heading"
},
"incompatible-device-subtitle": {
"defaultMessage": "You are using a micro:bit V1, but machine learning projects need the faster processor on a micro:bit V2. <link>Learn more about micro:bit versions.</link>",
"description": "Incompatible device dialog subtitle"
},
"insufficient-data-body": {
"defaultMessage": "You need at least 3 data samples for 2 actions to train the model.",
"description": "Insufficient data modal content"
Expand Down
10 changes: 10 additions & 0 deletions src/components/DownloadDialogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useDownloadActions } from "../hooks/download-hooks";
import { useStore } from "../store";
import UnplugRadioLinkMicrobitDialog from "./UnplugRadioLinkMicrobitDialog";
import ConnectRadioDataCollectionMicrobitDialog from "./ConnectRadioDataCollectionMicrobitDialog";
import UnsupportedEditorDevice from "./IncompatibleEditorDevice";

const DownloadDialogs = () => {
const actions = useDownloadActions();
Expand Down Expand Up @@ -98,6 +99,15 @@ const DownloadDialogs = () => {
closeIsPrimaryAction={true}
/>
);
case DownloadStep.IncompatibleDevice:
return (
<UnsupportedEditorDevice
isOpen
onClose={actions.close}
onBack={actions.getOnBack()}
stage="flashDevice"
/>
);
}
return <></>;
};
Expand Down
127 changes: 127 additions & 0 deletions src/components/IncompatibleEditorDevice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
Button,
HStack,
Link,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Text,
VStack,
} from "@chakra-ui/react";
import { ReactNode } from "react";
import { FormattedMessage } from "react-intl";
import { useProject } from "../hooks/project-hooks";

interface UnsupportedEditorDeviceProps {
isOpen: boolean;
onClose: () => void;
onNext?: () => void;
onBack?: () => void;
stage: "openEditor" | "flashDevice";
}

const UnsupportedEditorDevice = ({
isOpen,
onClose,
onNext,
onBack,
stage,
}: UnsupportedEditorDeviceProps) => {
const { saveHex } = useProject();
return (
<Modal
closeOnOverlayClick={false}
motionPreset="none"
isOpen={isOpen}
onClose={onClose}
size="3xl"
isCentered
>
<ModalOverlay>
<ModalContent>
<ModalHeader>
<FormattedMessage id="incompatible-device-heading" />
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack width="100%" alignItems="left" gap={5}>
<VStack gap={5} align="stretch">
<Text>
<FormattedMessage
id="incompatible-device-subtitle"
values={{
link: (children) => (
<Link
href="https://support.microbit.org/support/solutions/articles/19000154234-which-version-of-micro-bit-do-i-have-"
color="brand.600"
>
{children}
</Link>
),
}}
/>
</Text>
{stage === "openEditor" ? (
<>
<Text>
<FormattedMessage id="incompatible-device-body-1" />
</Text>
<Text>
<FormattedMessage
id="incompatible-device-body-2"
values={{
link: (chunks: ReactNode) => (
<Button variant="link" onClick={() => saveHex()}>
{chunks}
</Button>
),
}}
/>
</Text>
</>
) : (
<Text>
<FormattedMessage
id="incompatible-device-body-alt"
values={{
link: (chunks: ReactNode) => (
<Button variant="link" onClick={() => saveHex()}>
{chunks}
</Button>
),
}}
/>
</Text>
)}
</VStack>
</VStack>
</ModalBody>
<ModalFooter justifyContent="end">
<HStack gap={5}>
<Button onClick={onBack ?? onClose} variant="secondary" size="lg">
<FormattedMessage
id={onBack ? "back-action" : "cancel-action"}
/>
</Button>
<Button
onClick={onNext ?? onClose}
variant={onNext ? "primary" : "secondary"}
size="lg"
>
<FormattedMessage
id={onNext ? "continue-makecode-action" : "cancel-action"}
/>
</Button>
</HStack>
</ModalFooter>
</ModalContent>
</ModalOverlay>
</Modal>
);
};

export default UnsupportedEditorDevice;
4 changes: 2 additions & 2 deletions src/components/ManualFlashingDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ const ManualFlashingDialog = ({
id="connectMB.transferHex.manualDownload"
values={{
link: (chunks: ReactNode) => (
<Text as="button" color="brand.600" onClick={handleDownload}>
<Button variant="link" onClick={handleDownload}>
{chunks}
</Text>
</Button>
),
}}
/>
Expand Down
29 changes: 27 additions & 2 deletions src/components/TestingModelGridView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import {
MenuList,
Portal,
VStack,
useDisclosure,
} from "@chakra-ui/react";
import { MakeCodeRenderBlocksProvider } from "@microbit/makecode-embed/react";
import React from "react";
import React, { useCallback } from "react";
import { RiArrowRightLine, RiDeleteBin2Line } from "react-icons/ri";
import { FormattedMessage, useIntl } from "react-intl";
import { useConnectActions } from "../connect-actions-hooks";
import { usePrediction } from "../hooks/ml-hooks";
import { useProject } from "../hooks/project-hooks";
import { mlSettings } from "../ml";
Expand All @@ -26,6 +28,7 @@ import CodeViewCard from "./CodeViewCard";
import CodeViewGridItem from "./CodeViewGridItem";
import GestureNameGridItem from "./GestureNameGridItem";
import HeadingGrid from "./HeadingGrid";
import UnsupportedEditorDevice from "./IncompatibleEditorDevice";
import LiveGraphPanel from "./LiveGraphPanel";
import MoreMenuButton from "./MoreMenuButton";

Expand Down Expand Up @@ -59,12 +62,34 @@ const TestingModelGridView = () => {
const gestures = useStore((s) => s.gestures);
const setRequiredConfidence = useStore((s) => s.setRequiredConfidence);
const { openEditor, project, resetProject, projectEdited } = useProject();
const { getDataCollectionBoardVersion } = useConnectActions();

const [{ languageId }] = useSettings();
const makeCodeLang = getMakeCodeLang(languageId);

const { isOpen, onOpen, onClose } = useDisclosure();

const continueToEditor = useCallback(async () => {
await openEditor();
onClose();
}, [onClose, openEditor]);

const maybeOpenEditor = useCallback(() => {
// Open editor if device is not a V1, otherwise show warning dialog.
if (getDataCollectionBoardVersion() === "V1") {
return onOpen();
}
void openEditor();
}, [getDataCollectionBoardVersion, onOpen, openEditor]);

return (
<>
<UnsupportedEditorDevice
isOpen={isOpen}
onClose={onClose}
onNext={continueToEditor}
stage="openEditor"
/>
<MakeCodeRenderBlocksProvider
key={makeCodeLang}
options={{
Expand Down Expand Up @@ -154,7 +179,7 @@ const TestingModelGridView = () => {
<ButtonGroup isAttached>
<Button
variant="primary"
onClick={openEditor}
onClick={maybeOpenEditor}
className={tourElClassname.editInMakeCodeButton}
>
<FormattedMessage id="edit-in-makecode-action" />
Expand Down
22 changes: 18 additions & 4 deletions src/connect-actions-hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
BoardVersion,
MicrobitRadioBridgeConnection,
MicrobitWebBluetoothConnection,
MicrobitWebUSBConnection,
Expand All @@ -19,6 +20,7 @@ interface ConnectContextValue {
usb: MicrobitWebUSBConnection;
bluetooth: MicrobitWebBluetoothConnection;
radioBridge: MicrobitRadioBridgeConnection;
radioRemoteBoardVersion: React.MutableRefObject<BoardVersion | undefined>;
}

const ConnectContext = createContext<ConnectContextValue | null>(null);
Expand Down Expand Up @@ -50,8 +52,12 @@ export const ConnectProvider = ({ children }: ConnectProviderProps) => {
}
}, [bluetooth, isInitialized, radioBridge, usb]);

const radioRemoteBoardVersion = useRef<BoardVersion | undefined>();

return (
<ConnectContext.Provider value={{ usb, bluetooth, radioBridge }}>
<ConnectContext.Provider
value={{ usb, bluetooth, radioBridge, radioRemoteBoardVersion }}
>
{isInitialized ? children : <></>}
</ConnectContext.Provider>
);
Expand All @@ -62,12 +68,20 @@ export const useConnectActions = (): ConnectActions => {
if (!connectContextValue) {
throw new Error("Missing provider");
}
const { usb, bluetooth, radioBridge } = connectContextValue;
const { usb, bluetooth, radioBridge, radioRemoteBoardVersion } =
connectContextValue;
const logging = useLogging();

const connectActions = useMemo(
() => new ConnectActions(logging, usb, bluetooth, radioBridge),
[bluetooth, logging, radioBridge, usb]
() =>
new ConnectActions(
logging,
usb,
bluetooth,
radioBridge,
radioRemoteBoardVersion
),
[bluetooth, logging, radioBridge, radioRemoteBoardVersion, usb]
);

return connectActions;
Expand Down
Loading
Loading