From 87f7d825eb192160df730a3abb8f9dd7962bb459 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Apr 2020 14:54:56 -0700 Subject: [PATCH 01/16] first commit --- src/base_circuitpython/base_cp_constants.py | 3 +++ src/clue/adafruit_clue.py | 28 ++++++++++++--------- src/clue/test/test_adafruit_clue.py | 16 ++++++++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/base_circuitpython/base_cp_constants.py b/src/base_circuitpython/base_cp_constants.py index 3736fa333..bd93e5576 100644 --- a/src/base_circuitpython/base_cp_constants.py +++ b/src/base_circuitpython/base_cp_constants.py @@ -26,6 +26,9 @@ class CLUE_STATE: GYRO_X = "gyro_x" GYRO_Y = "gyro_y" GYRO_Z = "gyro_z" + # LEDs + RED_LED = "red_led" + WHITE_LEDS = "white_leds" CPX = "CPX" diff --git a/src/clue/adafruit_clue.py b/src/clue/adafruit_clue.py index 189ab988b..5afb89cd2 100644 --- a/src/clue/adafruit_clue.py +++ b/src/clue/adafruit_clue.py @@ -229,6 +229,10 @@ def __init__(self): self.__state[CONSTANTS.CLUE_STATE.GYRO_X] = 0 self.__state[CONSTANTS.CLUE_STATE.GYRO_Y] = 0 self.__state[CONSTANTS.CLUE_STATE.GYRO_Z] = 0 + # LEDs + self.__state[CONSTANTS.CLUE_STATE.RED_LED] = False + self.__state[CONSTANTS.CLUE_STATE.WHITE_LEDS] = False + self.button_mapping = { CONSTANTS.CLUE_STATE.BUTTON_A: "A", CONSTANTS.CLUE_STATE.BUTTON_B: "B", @@ -519,9 +523,7 @@ def touch_2(self): @property def white_leds(self): - """Not Implemented! - - The red led next to the USB plug labeled LED. + """The red led next to the USB plug labeled LED. .. image :: ../docs/_static/white_leds.jpg :alt: White LEDs This example turns on the white LEDs. @@ -530,18 +532,15 @@ def white_leds(self): from adafruit_clue import clue clue.white_leds = True """ - utils.print_for_unimplemented_functions(Clue.white_leds.__name__) + return self.__state[CONSTANTS.CLUE_STATE.WHITE_LEDS] @white_leds.setter def white_leds(self, value): - """Not Implemented!""" - utils.print_for_unimplemented_functions(Clue.white_leds.__name__) + self.__set_leds(CONSTANTS.CLUE_STATE.WHITE_LEDS, value) @property def red_led(self): - """Not Implemented! - - The red led next to the USB plug labeled LED. + """The red led next to the USB plug labeled LED. .. image :: ../docs/_static/red_led.jpg :alt: Red LED This example turns on the red LED. @@ -550,12 +549,11 @@ def red_led(self): from adafruit_clue import clue clue.red_led = True """ - utils.print_for_unimplemented_functions(Clue.red_led.__name__) + return self.__state[CONSTANTS.CLUE_STATE.RED_LEDS] @red_led.setter def red_led(self, value): - """Not Implemented!""" - utils.print_for_unimplemented_functions(Clue.red_led.__name__) + self.__set_leds(CONSTANTS.CLUE_STATE.RED_LEDS, value) def play_tone(self, frequency, duration): """ Not Implemented! @@ -745,6 +743,12 @@ def __update_button(self, button, value): ) self.__state[button] = value + def __set_leds(self, led, value): + value = bool(value) + self.__state[led] = value + sendable_json = {led: value} + utils.send_to_simulator(sendable_json, CONSTANTS.CLUE) + clue = Clue() # pylint: disable=invalid-name """Object that is automatically created on import. diff --git a/src/clue/test/test_adafruit_clue.py b/src/clue/test/test_adafruit_clue.py index fcd3f7e3e..3f40ae0ef 100644 --- a/src/clue/test/test_adafruit_clue.py +++ b/src/clue/test/test_adafruit_clue.py @@ -175,3 +175,19 @@ def test_sea_level_pressure(self, mock_sea_level_pressure): def test_pixel(self, mock_color): clue.pixel.fill(mock_color) assert clue.pixel[0] == mock_color + + @pytest.mark.parametrize( + "value, expected", + [(True, True), (False, False), (1, True), ("a", True), (0, False), ("", False)], + ) + def test_red_led(self, value, expected): + clue.red_led = value + assert clue.red_led == expected + + @pytest.mark.parametrize( + "value, expected", + [(True, True), (False, False), (1, True), ("a", True), (0, False), ("", False)], + ) + def test_white_leds(self): + clue.white_leds = value + assert clue.white_leds == expected From da2adcbf049e676e78eb167fab8f5ca66c66c865 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Apr 2020 15:02:22 -0700 Subject: [PATCH 02/16] updated broken test --- src/clue/test/test_adafruit_clue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clue/test/test_adafruit_clue.py b/src/clue/test/test_adafruit_clue.py index 3f40ae0ef..fd33efe71 100644 --- a/src/clue/test/test_adafruit_clue.py +++ b/src/clue/test/test_adafruit_clue.py @@ -188,6 +188,6 @@ def test_red_led(self, value, expected): "value, expected", [(True, True), (False, False), (1, True), ("a", True), (0, False), ("", False)], ) - def test_white_leds(self): + def test_white_leds(self, value, expected): clue.white_leds = value assert clue.white_leds == expected From 03a83b86ebd4b87cd82d0e5e37771e67ba01b4f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 6 Apr 2020 15:17:26 -0700 Subject: [PATCH 03/16] Fixed spelling error for red_led --- src/clue/adafruit_clue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clue/adafruit_clue.py b/src/clue/adafruit_clue.py index 5afb89cd2..7394dd555 100644 --- a/src/clue/adafruit_clue.py +++ b/src/clue/adafruit_clue.py @@ -549,11 +549,11 @@ def red_led(self): from adafruit_clue import clue clue.red_led = True """ - return self.__state[CONSTANTS.CLUE_STATE.RED_LEDS] + return self.__state[CONSTANTS.CLUE_STATE.RED_LED] @red_led.setter def red_led(self, value): - self.__set_leds(CONSTANTS.CLUE_STATE.RED_LEDS, value) + self.__set_leds(CONSTANTS.CLUE_STATE.RED_LED, value) def play_tone(self, frequency, duration): """ Not Implemented! From 60d580cbaf6727ee2b5c56d1fd514891244610bd Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Mon, 6 Apr 2020 15:48:51 -0700 Subject: [PATCH 04/16] Add white leds to refs --- src/view/components/clue/ClueSimulator.tsx | 8 ++++++-- src/view/components/clue/Clue_svg.tsx | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 3fd03cfc2..0f7372070 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -17,6 +17,8 @@ export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, neopixel: [0, 0, 0], + red_led: false, + white_led: false, }; interface IState { @@ -32,6 +34,8 @@ interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; neopixel: number[]; + red_led: boolean; + white_led: boolean; } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -70,11 +74,11 @@ export class ClueSimulator extends React.Component { displayMessage: message.state.display_base64, }, }); - } else if (message.state.pixels) { + } else if (message.state.leds) { this.setState({ clue: { ...this.state.clue, - neopixel: message.state.pixels, + neopixel: message.state.leds.pixel, }, }); } diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index f5963309f..c6c2b1bfb 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -14,7 +14,14 @@ interface IProps { } export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); - private neopixel: React.RefObject = React.createRef(); + private ledsRefs = { + neopixel: React.createRef(), + red_led: React.createRef(), + white_leds: [ + React.createRef(), + React.createRef(), + ], + }; private pixelStopGradient: React.RefObject< SVGStopElement > = React.createRef(); @@ -927,12 +934,14 @@ export class ClueSvg extends React.Component { { Neopixel - + ); @@ -1058,8 +1072,8 @@ export class ClueSvg extends React.Component { (255 - neopixel[1]) * CONSTANTS.LED_TINT_FACTOR},${neopixel[2] + (255 - neopixel[2]) * CONSTANTS.LED_TINT_FACTOR})`; - if (this.neopixel.current) { - this.neopixel.current.setAttribute("fill", rgbColor); + if (this.ledsRefs.neopixel.current) { + this.ledsRefs.neopixel.current.setAttribute("fill", rgbColor); } if (this.pixelStopGradient.current) { if (neopixel === DEFAULT_CLUE_STATE.neopixel) { From a756cb699535c917cd15c06c2e631c261407643e Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Mon, 6 Apr 2020 17:20:05 -0700 Subject: [PATCH 05/16] wip white leds --- src/view/components/clue/Clue_svg.tsx | 14 ++++++++++++++ src/view/constants.ts | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index c6c2b1bfb..0a2decb1f 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -11,6 +11,7 @@ export interface IRefObject { interface IProps { displayImage: string; neopixel: number[]; + whiteLedStatus: boolean; } export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); @@ -1090,4 +1091,17 @@ export class ClueSvg extends React.Component { this.pixelStopGradient.current.setAttribute("stop-color", rgbColor); } } + private updateLeds() { + // update white led + if (this.props.whiteLedStatus) { + this.ledsRefs.white_leds.map( + (ledRef: React.RefObject) => { + if (ledRef.current) { + ledRef.current.setAttribute("fill", "white"); + } + } + ); + } else { + } + } } diff --git a/src/view/constants.ts b/src/view/constants.ts index 5969a8275..2a74c8a2a 100644 --- a/src/view/constants.ts +++ b/src/view/constants.ts @@ -57,6 +57,10 @@ export const BUTTON_STYLING_CLASSES = { DEFAULT: "sim-button-outer", KEYPRESSED: "sim-button-key-press", }; +export const CLUE_LEDS_COLORS = { + WHITE_LEDS_OFF: "", + WHITE_LEDS_ON: "", +}; export enum DEVICE_LIST_KEY { CPX = "CPX", MICROBIT = "micro:bit", From 693165f8e24fbaafea122253dc1ca5d287de9551 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Tue, 7 Apr 2020 11:11:01 -0700 Subject: [PATCH 06/16] Add colors for leds on and off --- src/view/components/clue/Clue_svg.tsx | 25 +++++++++++++++---------- src/view/constants.ts | 4 ++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 0a2decb1f..bdd4d1d7a 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -4,7 +4,7 @@ import * as React from "react"; import "../../styles/SimulatorSvg.css"; import { DEFAULT_CLUE_STATE } from "./ClueSimulator"; -import CONSTANTS from "../../constants"; +import CONSTANTS, { CLUE_LEDS_COLORS } from "../../constants"; export interface IRefObject { [key: string]: React.RefObject; } @@ -1093,15 +1093,20 @@ export class ClueSvg extends React.Component { } private updateLeds() { // update white led - if (this.props.whiteLedStatus) { - this.ledsRefs.white_leds.map( - (ledRef: React.RefObject) => { - if (ledRef.current) { - ledRef.current.setAttribute("fill", "white"); - } + this.ledsRefs.white_leds.map( + (ledRef: React.RefObject) => { + if (ledRef.current && this.props.whiteLedStatus) { + ledRef.current.setAttribute( + "fill", + CLUE_LEDS_COLORS.WHITE_LEDS_ON + ); + } else if (ledRef.current) { + ledRef.current.setAttribute( + "fill", + CLUE_LEDS_COLORS.WHITE_LEDS_OFF + ); } - ); - } else { - } + } + ); } } diff --git a/src/view/constants.ts b/src/view/constants.ts index 2a74c8a2a..132d3493a 100644 --- a/src/view/constants.ts +++ b/src/view/constants.ts @@ -58,8 +58,8 @@ export const BUTTON_STYLING_CLASSES = { KEYPRESSED: "sim-button-key-press", }; export const CLUE_LEDS_COLORS = { - WHITE_LEDS_OFF: "", - WHITE_LEDS_ON: "", + WHITE_LEDS_OFF: "#ffde00", + WHITE_LEDS_ON: "white", }; export enum DEVICE_LIST_KEY { CPX = "CPX", From ebbb5ba3a1a4929a0aea40cb0367d74086dd44e7 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Tue, 7 Apr 2020 12:48:16 -0700 Subject: [PATCH 07/16] Modify white led color according to state --- src/view/components/clue/ClueImage.tsx | 8 +++- src/view/components/clue/ClueSimulator.tsx | 26 ++++++++----- src/view/components/clue/Clue_svg.tsx | 44 +++++++++++++--------- src/view/styles/SimulatorSvg.css | 4 +- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/view/components/clue/ClueImage.tsx b/src/view/components/clue/ClueImage.tsx index 402572c95..fcb2cf0bd 100644 --- a/src/view/components/clue/ClueImage.tsx +++ b/src/view/components/clue/ClueImage.tsx @@ -16,7 +16,11 @@ interface EventTriggers { interface IProps { eventTriggers: EventTriggers; displayMessage: string; - neopixel: number[]; + leds: { + neopixel: number[]; + redLed: boolean; + whiteLed: boolean; + }; } const BUTTON_CLASSNAME = { @@ -85,7 +89,7 @@ export class ClueImage extends React.Component { ); } diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 0f7372070..51441ccd6 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -16,9 +16,11 @@ import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, - neopixel: [0, 0, 0], - red_led: false, - white_led: false, + leds: { + neopixel: [0, 0, 0], + redLed: false, + whiteLed: false, + }, }; interface IState { @@ -33,9 +35,12 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; - neopixel: number[]; - red_led: boolean; - white_led: boolean; + + leds: { + neopixel: number[]; + redLed: boolean; + whiteLed: boolean; + }; } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -74,11 +79,14 @@ export class ClueSimulator extends React.Component { displayMessage: message.state.display_base64, }, }); - } else if (message.state.leds) { + } else if (message.state.pixels) { this.setState({ clue: { ...this.state.clue, - neopixel: message.state.leds.pixel, + leds: { + ...this.state.clue.leds, + neopixel: message.state.leds.pixel, + }, }, }); } @@ -143,7 +151,7 @@ export class ClueSimulator extends React.Component { onKeyEvent: this.onKeyEvent, }} displayMessage={this.state.clue.displayMessage} - neopixel={this.state.clue.neopixel} + leds={this.state.clue.leds} /> ; } interface IProps { displayImage: string; - neopixel: number[]; - whiteLedStatus: boolean; + leds: { + neopixel: number[]; + redLed: boolean; + whiteLed: boolean; + }; } export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); private ledsRefs = { neopixel: React.createRef(), - red_led: React.createRef(), - white_leds: [ + redLed: React.createRef(), + whiteLeds: [ React.createRef(), React.createRef(), ], @@ -46,12 +48,10 @@ export class ClueSvg extends React.Component { return this.displayRef; } componentDidMount() { - this.updateDisplay(); - this.updateNeopixel(); + this.updateSvg(); } componentDidUpdate() { - this.updateDisplay(); - this.updateNeopixel(); + this.updateSvg(); } render() { @@ -935,16 +935,14 @@ export class ClueSvg extends React.Component { { ); } + private updateSvg() { + this.updateDisplay(); + this.updateNeopixel(); + this.updateLeds(); + } private updateDisplay() { if (this.displayRef.current && this.props.displayImage) { @@ -1067,7 +1070,7 @@ export class ClueSvg extends React.Component { } private updateNeopixel() { - const { neopixel } = this.props; + const { neopixel } = this.props.leds; const rgbColor = `rgb(${neopixel[0] + (255 - neopixel[0]) * CONSTANTS.LED_TINT_FACTOR}, ${neopixel[1] + @@ -1078,7 +1081,7 @@ export class ClueSvg extends React.Component { this.ledsRefs.neopixel.current.setAttribute("fill", rgbColor); } if (this.pixelStopGradient.current) { - if (neopixel === DEFAULT_CLUE_STATE.neopixel) { + if (neopixel === DEFAULT_CLUE_STATE.leds.neopixel) { this.pixelStopGradient.current.setAttribute( "stop-opacity", "0" @@ -1094,14 +1097,19 @@ export class ClueSvg extends React.Component { } private updateLeds() { // update white led - this.ledsRefs.white_leds.map( + const { whiteLed } = this.props.leds; + + this.ledsRefs.whiteLeds.map( (ledRef: React.RefObject) => { - if (ledRef.current && this.props.whiteLedStatus) { + if (ledRef.current && whiteLed) { + console.log("lightup whiteleds"); ledRef.current.setAttribute( "fill", CLUE_LEDS_COLORS.WHITE_LEDS_ON ); } else if (ledRef.current) { + console.log("off whiteleds"); + ledRef.current.setAttribute( "fill", CLUE_LEDS_COLORS.WHITE_LEDS_OFF diff --git a/src/view/styles/SimulatorSvg.css b/src/view/styles/SimulatorSvg.css index 9e9deb4fb..8e748798e 100644 --- a/src/view/styles/SimulatorSvg.css +++ b/src/view/styles/SimulatorSvg.css @@ -281,9 +281,7 @@ sim-button { .cls-14 { stroke-width: 0.25px; } -.cls-16 { - fill: #ffde00; -} + .cls-17 { stroke-width: 2.02px; } From 665a3b2670153b47d4ed6e4974501d18c6c2e468 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Tue, 7 Apr 2020 18:05:53 -0700 Subject: [PATCH 08/16] Functioning red and white leds --- src/view/components/clue/ClueSimulator.tsx | 60 ++++++--- src/view/components/clue/Clue_svg.tsx | 122 ++++++++++++++---- .../clue/__snapshots__/Clue.spec.tsx.snap | 77 ++++++++++- src/view/components/cpx/Svg_utils.tsx | 19 +++ src/view/constants.ts | 2 + 5 files changed, 230 insertions(+), 50 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 51441ccd6..810392dd8 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -72,24 +72,7 @@ export class ClueSimulator extends React.Component { console.log( `message received ${JSON.stringify(message.state)}` ); - if (message.state.display_base64) { - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); - } else if (message.state.pixels) { - this.setState({ - clue: { - ...this.state.clue, - leds: { - ...this.state.clue.leds, - neopixel: message.state.leds.pixel, - }, - }, - }); - } + this.handleStateChangeMessage(message); break; case "activate-play": @@ -283,4 +266,45 @@ export class ClueSimulator extends React.Component { this.refreshSimulatorClick(); } } + protected handleStateChangeMessage(message: any) { + if (message.state.display_base64 != null) { + this.setState({ + clue: { + ...this.state.clue, + displayMessage: message.state.display_base64, + }, + }); + } else if (message.state.pixels != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + neopixel: message.state.pixels, + }, + }, + }); + } else if (message.state.white_leds != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + whiteLed: message.state.white_leds, + }, + }, + }); + console.log(`whiteled ${message.state.white_leds}`); + } else if (message.state.red_led != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + redLed: message.state.red_led, + }, + }, + }); + } + } } diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 390931787..ba1b73071 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -5,6 +5,7 @@ import * as React from "react"; import "../../styles/SimulatorSvg.css"; import { DEFAULT_CLUE_STATE } from "./ClueSimulator"; import { CONSTANTS, CLUE_LEDS_COLORS } from "../../constants"; +import svg from "../cpx/Svg_utils"; export interface IRefObject { [key: string]: React.RefObject; } @@ -20,15 +21,17 @@ export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); private ledsRefs = { neopixel: React.createRef(), - redLed: React.createRef(), + redLed: React.createRef(), whiteLeds: [ React.createRef(), React.createRef(), ], }; - private pixelStopGradient: React.RefObject< - SVGStopElement - > = React.createRef(); + private gradientRefs = { + neopixel: React.createRef(), + whiteLed: React.createRef(), + redLed: React.createRef(), + }; private buttonRefs: IRefObject = { BTN_A: React.createRef(), @@ -68,7 +71,7 @@ export class ClueSvg extends React.Component { > { offset="0%" stopColor="rgb(0,0,0)" stopOpacity="1" - ref={this.pixelStopGradient} + ref={this.gradientRefs.neopixel} + /> + + + + + + + + { transform="translate(-49.27 -48.48)" /> + { A+B + + + @@ -1040,10 +1093,20 @@ export class ClueSvg extends React.Component { rx="18.28" /> + + Red LED + + + Neopixel - + { if (this.ledsRefs.neopixel.current) { this.ledsRefs.neopixel.current.setAttribute("fill", rgbColor); } - if (this.pixelStopGradient.current) { + if (this.gradientRefs.neopixel.current) { if (neopixel === DEFAULT_CLUE_STATE.leds.neopixel) { - this.pixelStopGradient.current.setAttribute( + this.gradientRefs.neopixel.current.setAttribute( "stop-opacity", "0" ); } else { - this.pixelStopGradient.current.setAttribute( + this.gradientRefs.neopixel.current.setAttribute( "stop-opacity", "1" ); } - this.pixelStopGradient.current.setAttribute("stop-color", rgbColor); + this.gradientRefs.neopixel.current.setAttribute( + "stop-color", + rgbColor + ); } } private updateLeds() { // update white led - const { whiteLed } = this.props.leds; + const { whiteLed, redLed } = this.props.leds; this.ledsRefs.whiteLeds.map( (ledRef: React.RefObject) => { - if (ledRef.current && whiteLed) { - console.log("lightup whiteleds"); - ledRef.current.setAttribute( - "fill", - CLUE_LEDS_COLORS.WHITE_LEDS_ON - ); - } else if (ledRef.current) { - console.log("off whiteleds"); - - ledRef.current.setAttribute( - "fill", - CLUE_LEDS_COLORS.WHITE_LEDS_OFF + if (ledRef.current && this.gradientRefs.whiteLed.current) { + svg.setLed( + whiteLed, + CLUE_LEDS_COLORS.WHITE_LEDS_OFF, + CLUE_LEDS_COLORS.WHITE_LEDS_ON, + ledRef.current, + this.gradientRefs.whiteLed.current ); } } ); + if (this.ledsRefs.redLed.current && this.gradientRefs.redLed.current) { + svg.setLed( + redLed, + CLUE_LEDS_COLORS.RED_LED_OFF, + CLUE_LEDS_COLORS.RED_LED_ON, + this.ledsRefs.redLed.current, + this.gradientRefs.redLed.current + ); + } } } diff --git a/src/view/components/clue/__snapshots__/Clue.spec.tsx.snap b/src/view/components/clue/__snapshots__/Clue.spec.tsx.snap index 15dcfbd9b..81252c33b 100644 --- a/src/view/components/clue/__snapshots__/Clue.spec.tsx.snap +++ b/src/view/components/clue/__snapshots__/Clue.spec.tsx.snap @@ -30,7 +30,7 @@ Array [ cy="50%" fx="50%" fy="50%" - id="grad1" + id="gradNeopixel" r="70%" > + + + + + + + + A+B + + + + Red LED + + + Date: Wed, 8 Apr 2020 11:25:23 -0700 Subject: [PATCH 09/16] Remove logs --- src/view/components/clue/ClueSimulator.tsx | 1 - src/view/components/cpx/Svg_utils.tsx | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 810392dd8..7392e92e6 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -294,7 +294,6 @@ export class ClueSimulator extends React.Component { }, }, }); - console.log(`whiteled ${message.state.white_leds}`); } else if (message.state.red_led != null) { this.setState({ clue: { diff --git a/src/view/components/cpx/Svg_utils.tsx b/src/view/components/cpx/Svg_utils.tsx index 9d2b3d9da..29dab77de 100644 --- a/src/view/components/cpx/Svg_utils.tsx +++ b/src/view/components/cpx/Svg_utils.tsx @@ -86,12 +86,9 @@ namespace svg { gradientStopElement: SVGStopElement ) { if (ledStatus) { - console.log("turn on"); ledElement.setAttribute("fill", onColor); gradientStopElement.setAttribute("stop-opacity", "1"); } else { - console.log("turn on"); - ledElement.setAttribute("fill", offColor); gradientStopElement.setAttribute("stop-opacity", "0"); } From 700d5af5b6954899b79d0dc64ec335f7d08a1247 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 14:49:14 -0700 Subject: [PATCH 10/16] Fix merge conflicts --- src/view/components/clue/ClueSimulator.tsx | 301 +-------------------- 1 file changed, 9 insertions(+), 292 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 474d19e8f..72bb419a4 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -1,4 +1,3 @@ -<<<<<<< HEAD import * as React from "react"; import { AB_BUTTONS_KEYS, @@ -214,7 +213,9 @@ export class ClueSimulator extends React.Component { }; protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { event.stopPropagation(); - if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER) && this.context === VIEW_STATE.RUNNING + if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER) && + this.context === VIEW_STATE.RUNNING ) { this.handleButtonClick(key, active); if (this.imageRef.current) { @@ -236,7 +237,8 @@ export class ClueSimulator extends React.Component { } } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) && this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) && + this.context === VIEW_STATE.RUNNING ) { this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); if (this.imageRef.current) { @@ -246,7 +248,8 @@ export class ClueSimulator extends React.Component { ); } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) && this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) && + this.context === VIEW_STATE.RUNNING ) { this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); if (this.imageRef.current) { @@ -256,7 +259,8 @@ export class ClueSimulator extends React.Component { ); } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) && this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) && + this.context === VIEW_STATE.RUNNING ) { this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); if (this.imageRef.current) { @@ -313,290 +317,3 @@ export class ClueSimulator extends React.Component { } } ClueSimulator.contextType = ViewStateContext; - -======= -import * as React from "react"; -import { - AB_BUTTONS_KEYS, - // DEVICE_LIST_KEY, - CONSTANTS, - DEFAULT_IMG_CLUE, - DEVICE_LIST_KEY, - VIEW_STATE, - WEBVIEW_MESSAGES, -} from "../../constants"; -import { ViewStateContext } from "../../context"; -import "../../styles/Simulator.css"; -import PlayLogo from "../../svgs/play_svg"; -import StopLogo from "../../svgs/stop_svg"; -import { sendMessage } from "../../utils/MessageUtils"; -import ActionBar from "../simulator/ActionBar"; -import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; - -export const DEFAULT_CLUE_STATE: IClueState = { - buttons: { button_a: false, button_b: false }, - displayMessage: DEFAULT_IMG_CLUE, - neopixel: [0, 0, 0], -}; - -interface IState { - active_editors: string[]; - running_file?: string; - play_button: boolean; - selected_file: string; - clue: IClueState; - currently_selected_file: string; -} - -interface IClueState { - buttons: { button_a: boolean; button_b: boolean }; - displayMessage: string; - neopixel: number[]; -} -export class ClueSimulator extends React.Component { - private imageRef: React.RefObject = React.createRef(); - constructor() { - super({}); - this.state = { - clue: DEFAULT_CLUE_STATE, - play_button: false, - selected_file: "", - active_editors: [], - running_file: undefined, - currently_selected_file: "", - }; - this.onKeyEvent = this.onKeyEvent.bind(this); - } - handleMessage = (event: any): void => { - const message = event.data; - if (message.active_device !== DEVICE_LIST_KEY.CLUE) { - return; - } - switch (message.command) { - case "reset-state": - this.setState({ - clue: DEFAULT_CLUE_STATE, - play_button: false, - }); - break; - case "set-state": - console.log( - `message received ${JSON.stringify(message.state)}` - ); - if (message.state.display_base64) { - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); - } else if (message.state.pixels) { - this.setState({ - clue: { - ...this.state.clue, - neopixel: message.state.pixels, - }, - }); - } - - break; - case "activate-play": - const newRunningFile = this.state.currently_selected_file; - this.setState({ - play_button: !this.state.play_button, - running_file: newRunningFile, - clue: { - ...this.state.clue, - displayMessage: DEFAULT_IMG_CLUE, - }, - }); - break; - case "visible-editors": - this.setState({ - active_editors: message.state.activePythonEditors, - }); - break; - case "current-file": - if (this.state.play_button) { - this.setState({ - currently_selected_file: message.state.running_file, - }); - } else { - this.setState({ - running_file: message.state.running_file, - currently_selected_file: message.state.running_file, - }); - } - - break; - } - }; - componentDidMount() { - window.addEventListener("message", this.handleMessage); - } - componentWillUnmount() { - window.removeEventListener("message", this.handleMessage); - } - - render() { - const playStopImage = this.state.play_button ? StopLogo : PlayLogo; - const playStopLabel = this.state.play_button ? "stop" : "play"; - return ( -
-
- {this.state.running_file && this.state.play_button - ? CONSTANTS.CURRENTLY_RUNNING(this.state.running_file) - : CONSTANTS.FILES_PLACEHOLDER} -
- -
- -
- -
- ); - } - protected togglePlayClick = () => { - const button = - window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) || - window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON); - if (button) { - button.focus(); - } - sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, { - selected_file: this.state.selected_file, - state: !this.state.play_button, - }); - }; - protected onSelectFile(event: React.FocusEvent) { - this.setState({ - selected_file: event.currentTarget.value, - }); - } - protected refreshSimulatorClick = () => { - const button = window.document.getElementById( - CONSTANTS.ID_NAME.REFRESH_BUTTON - ); - if (button) { - button.focus(); - } - sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true); - }; - protected handleButtonClick = (key: string, isActive: boolean) => { - let newButtonState = this.state.clue.buttons; - switch (key) { - case AB_BUTTONS_KEYS.BTN_A: - newButtonState.button_a = isActive; - break; - case AB_BUTTONS_KEYS.BTN_B: - newButtonState.button_b = isActive; - break; - case AB_BUTTONS_KEYS.BTN_AB: - newButtonState = { - button_a: isActive, - button_b: isActive, - }; - break; - } - sendMessage(WEBVIEW_MESSAGES.BUTTON_PRESS, newButtonState); - this.setState({ - clue: { - ...this.state.clue, - buttons: newButtonState, - }, - }); - }; - protected onMouseUp = (event: Event, key: string) => { - event.preventDefault(); - this.handleButtonClick(key, false); - }; - protected onMouseDown = (event: Event, key: string) => { - event.preventDefault(); - this.handleButtonClick(key, true); - }; - protected onMouseLeave = (event: Event, key: string) => { - event.preventDefault(); - console.log(`To implement onMouseLeave ${key}`); - }; - protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { - event.stopPropagation(); - if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER) && - this.context === VIEW_STATE.RUNNING - ) { - this.handleButtonClick(key, active); - if (this.imageRef.current) { - if (key === BUTTONS_KEYS.BTN_A) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_A, - active - ); - } else if (key === BUTTONS_KEYS.BTN_B) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_B, - active - ); - } else if (key === BUTTONS_KEYS.BTN_AB) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_AB, - active - ); - } - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) && - this.context === VIEW_STATE.RUNNING - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_A, - active - ); - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) && - this.context === VIEW_STATE.RUNNING - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_B, - active - ); - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) && - this.context === VIEW_STATE.RUNNING - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_AB, - active - ); - } - } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) { - this.togglePlayClick(); - } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) { - this.refreshSimulatorClick(); - } - } -} -ClueSimulator.contextType = ViewStateContext; ->>>>>>> origin/dev From 57cac4a7ab93f4ffd09467b4ac718a3bbe07921d Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 14:56:52 -0700 Subject: [PATCH 11/16] Format py --- src/clue/adafruit_clue.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/clue/adafruit_clue.py b/src/clue/adafruit_clue.py index 50090c141..a44794c98 100644 --- a/src/clue/adafruit_clue.py +++ b/src/clue/adafruit_clue.py @@ -140,23 +140,20 @@ def __init__( self._lines = [] for num in range(1): - self._lines.append(self.add_text_line( - color=colors[num % len(colors)])) + self._lines.append(self.add_text_line(color=colors[num % len(colors)])) def __getitem__(self, item): """Fetch the Nth text line Group""" if len(self._lines) - 1 < item: for _ in range(item - (len(self._lines) - 1)): self._lines.append( - self.add_text_line( - color=self._colors[item % len(self._colors)]) + self.add_text_line(color=self._colors[item % len(self._colors)]) ) return self._lines[item] def add_text_line(self, color=0xFFFFFF): """Adds a line on the display of the specified color and returns the label object.""" - text_label = self._label.Label( - self._font, text="", max_glyphs=45, color=color) + text_label = self._label.Label(self._font, text="", max_glyphs=45, color=color) text_label.x = 0 text_label.y = self._y self._y = text_label.y + 13 * self.text_scale From 6cf83b4c58b37192bce381db7cf44f7df47e38eb Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 16:38:21 -0700 Subject: [PATCH 12/16] Rebase change for cluesimulator.tsx --- src/view/components/clue/ClueSimulator.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 72bb419a4..54462758a 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -38,7 +38,6 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; - leds: { neopixel: number[]; redLed: boolean; From 409fce6c4998359c679e4ba2744e177444cacfcb Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 16:44:04 -0700 Subject: [PATCH 13/16] Reset file to dev version --- src/view/components/clue/ClueSimulator.tsx | 87 ++++++---------------- 1 file changed, 22 insertions(+), 65 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 54462758a..f48112a0a 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -6,7 +6,6 @@ import { DEFAULT_IMG_CLUE, DEVICE_LIST_KEY, WEBVIEW_MESSAGES, - VIEW_STATE, } from "../../constants"; import PlayLogo from "../../svgs/play_svg"; import StopLogo from "../../svgs/stop_svg"; @@ -14,16 +13,11 @@ import { sendMessage } from "../../utils/MessageUtils"; import ActionBar from "../simulator/ActionBar"; import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; import "../../styles/Simulator.css"; -import { ViewStateContext } from "../../context"; export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, - leds: { - neopixel: [0, 0, 0], - redLed: false, - whiteLed: false, - }, + neopixel: [0, 0, 0], }; interface IState { @@ -38,11 +32,7 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; - leds: { - neopixel: number[]; - redLed: boolean; - whiteLed: boolean; - }; + neopixel: number[]; } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -74,7 +64,21 @@ export class ClueSimulator extends React.Component { console.log( `message received ${JSON.stringify(message.state)}` ); - this.handleStateChangeMessage(message); + if (message.state.display_base64) { + this.setState({ + clue: { + ...this.state.clue, + displayMessage: message.state.display_base64, + }, + }); + } else if (message.state.pixels) { + this.setState({ + clue: { + ...this.state.clue, + neopixel: message.state.pixels, + }, + }); + } break; case "activate-play": @@ -136,7 +140,7 @@ export class ClueSimulator extends React.Component { onKeyEvent: this.onKeyEvent, }} displayMessage={this.state.clue.displayMessage} - leds={this.state.clue.leds} + neopixel={this.state.clue.neopixel} /> { }; protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { event.stopPropagation(); - if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER) && - this.context === VIEW_STATE.RUNNING - ) { + if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER)) { this.handleButtonClick(key, active); if (this.imageRef.current) { if (key === BUTTONS_KEYS.BTN_A) { @@ -236,8 +237,7 @@ export class ClueSimulator extends React.Component { } } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) && - this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) ) { this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); if (this.imageRef.current) { @@ -247,8 +247,7 @@ export class ClueSimulator extends React.Component { ); } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) && - this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) ) { this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); if (this.imageRef.current) { @@ -258,8 +257,7 @@ export class ClueSimulator extends React.Component { ); } } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) && - this.context === VIEW_STATE.RUNNING + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) ) { this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); if (this.imageRef.current) { @@ -274,45 +272,4 @@ export class ClueSimulator extends React.Component { this.refreshSimulatorClick(); } } - protected handleStateChangeMessage(message: any) { - if (message.state.display_base64 != null) { - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); - } else if (message.state.pixels != null) { - this.setState({ - clue: { - ...this.state.clue, - leds: { - ...this.state.clue.leds, - neopixel: message.state.pixels, - }, - }, - }); - } else if (message.state.white_leds != null) { - this.setState({ - clue: { - ...this.state.clue, - leds: { - ...this.state.clue.leds, - whiteLed: message.state.white_leds, - }, - }, - }); - } else if (message.state.red_led != null) { - this.setState({ - clue: { - ...this.state.clue, - leds: { - ...this.state.clue.leds, - redLed: message.state.red_led, - }, - }, - }); - } - } } -ClueSimulator.contextType = ViewStateContext; From 334ae92562fb78064840218f4f58f17a143ee629 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 16:47:19 -0700 Subject: [PATCH 14/16] Restore cluesimulator.tsx with dev version --- src/view/components/clue/ClueSimulator.tsx | 559 +++++++++++---------- 1 file changed, 284 insertions(+), 275 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index f48112a0a..61542d3a4 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -1,275 +1,284 @@ -import * as React from "react"; -import { - AB_BUTTONS_KEYS, - // DEVICE_LIST_KEY, - CONSTANTS, - DEFAULT_IMG_CLUE, - DEVICE_LIST_KEY, - WEBVIEW_MESSAGES, -} from "../../constants"; -import PlayLogo from "../../svgs/play_svg"; -import StopLogo from "../../svgs/stop_svg"; -import { sendMessage } from "../../utils/MessageUtils"; -import ActionBar from "../simulator/ActionBar"; -import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; -import "../../styles/Simulator.css"; - -export const DEFAULT_CLUE_STATE: IClueState = { - buttons: { button_a: false, button_b: false }, - displayMessage: DEFAULT_IMG_CLUE, - neopixel: [0, 0, 0], -}; - -interface IState { - active_editors: string[]; - running_file?: string; - play_button: boolean; - selected_file: string; - clue: IClueState; - currently_selected_file: string; -} - -interface IClueState { - buttons: { button_a: boolean; button_b: boolean }; - displayMessage: string; - neopixel: number[]; -} -export class ClueSimulator extends React.Component { - private imageRef: React.RefObject = React.createRef(); - constructor() { - super({}); - this.state = { - clue: DEFAULT_CLUE_STATE, - play_button: false, - selected_file: "", - active_editors: [], - running_file: undefined, - currently_selected_file: "", - }; - this.onKeyEvent = this.onKeyEvent.bind(this); - } - handleMessage = (event: any): void => { - const message = event.data; - if (message.active_device !== DEVICE_LIST_KEY.CLUE) { - return; - } - switch (message.command) { - case "reset-state": - this.setState({ - clue: DEFAULT_CLUE_STATE, - play_button: false, - }); - break; - case "set-state": - console.log( - `message received ${JSON.stringify(message.state)}` - ); - if (message.state.display_base64) { - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); - } else if (message.state.pixels) { - this.setState({ - clue: { - ...this.state.clue, - neopixel: message.state.pixels, - }, - }); - } - - break; - case "activate-play": - const newRunningFile = this.state.currently_selected_file; - this.setState({ - play_button: !this.state.play_button, - running_file: newRunningFile, - clue: { - ...this.state.clue, - displayMessage: DEFAULT_IMG_CLUE, - }, - }); - break; - case "visible-editors": - this.setState({ - active_editors: message.state.activePythonEditors, - }); - break; - case "current-file": - if (this.state.play_button) { - this.setState({ - currently_selected_file: message.state.running_file, - }); - } else { - this.setState({ - running_file: message.state.running_file, - currently_selected_file: message.state.running_file, - }); - } - - break; - } - }; - componentDidMount() { - window.addEventListener("message", this.handleMessage); - } - componentWillUnmount() { - window.removeEventListener("message", this.handleMessage); - } - - render() { - const playStopImage = this.state.play_button ? StopLogo : PlayLogo; - const playStopLabel = this.state.play_button ? "stop" : "play"; - return ( -
-
- {this.state.running_file && this.state.play_button - ? CONSTANTS.CURRENTLY_RUNNING(this.state.running_file) - : CONSTANTS.FILES_PLACEHOLDER} -
- -
- -
- -
- ); - } - protected togglePlayClick = () => { - const button = - window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) || - window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON); - if (button) { - button.focus(); - } - sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, { - selected_file: this.state.selected_file, - state: !this.state.play_button, - }); - }; - protected onSelectFile(event: React.FocusEvent) { - this.setState({ - selected_file: event.currentTarget.value, - }); - } - protected refreshSimulatorClick = () => { - const button = window.document.getElementById( - CONSTANTS.ID_NAME.REFRESH_BUTTON - ); - if (button) { - button.focus(); - } - sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true); - }; - protected handleButtonClick = (key: string, isActive: boolean) => { - let newButtonState = this.state.clue.buttons; - switch (key) { - case AB_BUTTONS_KEYS.BTN_A: - newButtonState.button_a = isActive; - break; - case AB_BUTTONS_KEYS.BTN_B: - newButtonState.button_b = isActive; - break; - case AB_BUTTONS_KEYS.BTN_AB: - newButtonState = { - button_a: isActive, - button_b: isActive, - }; - break; - } - sendMessage(WEBVIEW_MESSAGES.BUTTON_PRESS, newButtonState); - this.setState({ - clue: { - ...this.state.clue, - buttons: newButtonState, - }, - }); - }; - protected onMouseUp = (event: Event, key: string) => { - event.preventDefault(); - this.handleButtonClick(key, false); - }; - protected onMouseDown = (event: Event, key: string) => { - event.preventDefault(); - this.handleButtonClick(key, true); - }; - protected onMouseLeave = (event: Event, key: string) => { - event.preventDefault(); - console.log(`To implement onMouseLeave ${key}`); - }; - protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { - event.stopPropagation(); - if ([event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER)) { - this.handleButtonClick(key, active); - if (this.imageRef.current) { - if (key === BUTTONS_KEYS.BTN_A) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_A, - active - ); - } else if (key === BUTTONS_KEYS.BTN_B) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_B, - active - ); - } else if (key === BUTTONS_KEYS.BTN_AB) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_AB, - active - ); - } - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_A, - active - ); - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_B, - active - ); - } - } else if ( - [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) - ) { - this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); - if (this.imageRef.current) { - this.imageRef.current.updateButtonAttributes( - BUTTONS_KEYS.BTN_AB, - active - ); - } - } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) { - this.togglePlayClick(); - } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) { - this.refreshSimulatorClick(); - } - } -} +import * as React from "react"; +import { + AB_BUTTONS_KEYS, + // DEVICE_LIST_KEY, + CONSTANTS, + DEFAULT_IMG_CLUE, + DEVICE_LIST_KEY, + VIEW_STATE, + WEBVIEW_MESSAGES, +} from "../../constants"; +import { ViewStateContext } from "../../context"; +import "../../styles/Simulator.css"; +import PlayLogo from "../../svgs/play_svg"; +import StopLogo from "../../svgs/stop_svg"; +import { sendMessage } from "../../utils/MessageUtils"; +import ActionBar from "../simulator/ActionBar"; +import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; + +export const DEFAULT_CLUE_STATE: IClueState = { + buttons: { button_a: false, button_b: false }, + displayMessage: DEFAULT_IMG_CLUE, + neopixel: [0, 0, 0], +}; + +interface IState { + active_editors: string[]; + running_file?: string; + play_button: boolean; + selected_file: string; + clue: IClueState; + currently_selected_file: string; +} + +interface IClueState { + buttons: { button_a: boolean; button_b: boolean }; + displayMessage: string; + neopixel: number[]; +} +export class ClueSimulator extends React.Component { + private imageRef: React.RefObject = React.createRef(); + constructor() { + super({}); + this.state = { + clue: DEFAULT_CLUE_STATE, + play_button: false, + selected_file: "", + active_editors: [], + running_file: undefined, + currently_selected_file: "", + }; + this.onKeyEvent = this.onKeyEvent.bind(this); + } + handleMessage = (event: any): void => { + const message = event.data; + if (message.active_device !== DEVICE_LIST_KEY.CLUE) { + return; + } + switch (message.command) { + case "reset-state": + this.setState({ + clue: DEFAULT_CLUE_STATE, + play_button: false, + }); + break; + case "set-state": + console.log( + `message received ${JSON.stringify(message.state)}` + ); + if (message.state.display_base64) { + this.setState({ + clue: { + ...this.state.clue, + displayMessage: message.state.display_base64, + }, + }); + } else if (message.state.pixels) { + this.setState({ + clue: { + ...this.state.clue, + neopixel: message.state.pixels, + }, + }); + } + + break; + case "activate-play": + const newRunningFile = this.state.currently_selected_file; + this.setState({ + play_button: !this.state.play_button, + running_file: newRunningFile, + clue: { + ...this.state.clue, + displayMessage: DEFAULT_IMG_CLUE, + }, + }); + break; + case "visible-editors": + this.setState({ + active_editors: message.state.activePythonEditors, + }); + break; + case "current-file": + if (this.state.play_button) { + this.setState({ + currently_selected_file: message.state.running_file, + }); + } else { + this.setState({ + running_file: message.state.running_file, + currently_selected_file: message.state.running_file, + }); + } + + break; + } + }; + componentDidMount() { + window.addEventListener("message", this.handleMessage); + } + componentWillUnmount() { + window.removeEventListener("message", this.handleMessage); + } + + render() { + const playStopImage = this.state.play_button ? StopLogo : PlayLogo; + const playStopLabel = this.state.play_button ? "stop" : "play"; + return ( +
+
+ {this.state.running_file && this.state.play_button + ? CONSTANTS.CURRENTLY_RUNNING(this.state.running_file) + : CONSTANTS.FILES_PLACEHOLDER} +
+ +
+ +
+ +
+ ); + } + protected togglePlayClick = () => { + const button = + window.document.getElementById(CONSTANTS.ID_NAME.PLAY_BUTTON) || + window.document.getElementById(CONSTANTS.ID_NAME.STOP_BUTTON); + if (button) { + button.focus(); + } + sendMessage(WEBVIEW_MESSAGES.TOGGLE_PLAY_STOP, { + selected_file: this.state.selected_file, + state: !this.state.play_button, + }); + }; + protected onSelectFile(event: React.FocusEvent) { + this.setState({ + selected_file: event.currentTarget.value, + }); + } + protected refreshSimulatorClick = () => { + const button = window.document.getElementById( + CONSTANTS.ID_NAME.REFRESH_BUTTON + ); + if (button) { + button.focus(); + } + sendMessage(WEBVIEW_MESSAGES.REFRESH_SIMULATOR, true); + }; + protected handleButtonClick = (key: string, isActive: boolean) => { + let newButtonState = this.state.clue.buttons; + switch (key) { + case AB_BUTTONS_KEYS.BTN_A: + newButtonState.button_a = isActive; + break; + case AB_BUTTONS_KEYS.BTN_B: + newButtonState.button_b = isActive; + break; + case AB_BUTTONS_KEYS.BTN_AB: + newButtonState = { + button_a: isActive, + button_b: isActive, + }; + break; + } + sendMessage(WEBVIEW_MESSAGES.BUTTON_PRESS, newButtonState); + this.setState({ + clue: { + ...this.state.clue, + buttons: newButtonState, + }, + }); + }; + protected onMouseUp = (event: Event, key: string) => { + event.preventDefault(); + this.handleButtonClick(key, false); + }; + protected onMouseDown = (event: Event, key: string) => { + event.preventDefault(); + this.handleButtonClick(key, true); + }; + protected onMouseLeave = (event: Event, key: string) => { + event.preventDefault(); + console.log(`To implement onMouseLeave ${key}`); + }; + protected onKeyEvent(event: KeyboardEvent, active: boolean, key: string) { + event.stopPropagation(); + if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.ENTER) && + this.context === VIEW_STATE.RUNNING + ) { + this.handleButtonClick(key, active); + if (this.imageRef.current) { + if (key === BUTTONS_KEYS.BTN_A) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_A, + active + ); + } else if (key === BUTTONS_KEYS.BTN_B) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_B, + active + ); + } else if (key === BUTTONS_KEYS.BTN_AB) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_AB, + active + ); + } + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.A) && + this.context === VIEW_STATE.RUNNING + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_A, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_A, + active + ); + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.B) && + this.context === VIEW_STATE.RUNNING + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_B, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_B, + active + ); + } + } else if ( + [event.code, event.key].includes(CONSTANTS.KEYBOARD_KEYS.C) && + this.context === VIEW_STATE.RUNNING + ) { + this.handleButtonClick(BUTTONS_KEYS.BTN_AB, active); + if (this.imageRef.current) { + this.imageRef.current.updateButtonAttributes( + BUTTONS_KEYS.BTN_AB, + active + ); + } + } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_F) { + this.togglePlayClick(); + } else if (event.key === CONSTANTS.KEYBOARD_KEYS.CAPITAL_R) { + this.refreshSimulatorClick(); + } + } +} +ClueSimulator.contextType = ViewStateContext; From 725bb6f7c389df1b410c4beccb6fb71cf332423d Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 16:58:26 -0700 Subject: [PATCH 15/16] Make changes for cluesimulator.tsx --- src/view/components/clue/ClueSimulator.tsx | 78 +++++++++++++++------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 61542d3a4..f7f6327a5 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -1,25 +1,29 @@ import * as React from "react"; import { AB_BUTTONS_KEYS, - // DEVICE_LIST_KEY, CONSTANTS, DEFAULT_IMG_CLUE, DEVICE_LIST_KEY, VIEW_STATE, WEBVIEW_MESSAGES, } from "../../constants"; -import { ViewStateContext } from "../../context"; import "../../styles/Simulator.css"; import PlayLogo from "../../svgs/play_svg"; import StopLogo from "../../svgs/stop_svg"; import { sendMessage } from "../../utils/MessageUtils"; import ActionBar from "../simulator/ActionBar"; import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; +import "../../styles/Simulator.css"; +import { ViewStateContext } from "../../context"; export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, - neopixel: [0, 0, 0], + leds: { + neopixel: [0, 0, 0], + redLed: false, + whiteLed: false, + }, }; interface IState { @@ -34,7 +38,11 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; - neopixel: number[]; + leds: { + neopixel: number[]; + redLed: boolean; + whiteLed: boolean; + }; } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -63,25 +71,7 @@ export class ClueSimulator extends React.Component { }); break; case "set-state": - console.log( - `message received ${JSON.stringify(message.state)}` - ); - if (message.state.display_base64) { - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); - } else if (message.state.pixels) { - this.setState({ - clue: { - ...this.state.clue, - neopixel: message.state.pixels, - }, - }); - } - + this.handleStateChangeMessage(message); break; case "activate-play": const newRunningFile = this.state.currently_selected_file; @@ -142,7 +132,7 @@ export class ClueSimulator extends React.Component { onKeyEvent: this.onKeyEvent, }} displayMessage={this.state.clue.displayMessage} - neopixel={this.state.clue.neopixel} + leds={this.state.clue.leds} /> { this.refreshSimulatorClick(); } } + protected handleStateChangeMessage(message: any) { + if (message.state.display_base64 != null) { + this.setState({ + clue: { + ...this.state.clue, + displayMessage: message.state.display_base64, + }, + }); + } else if (message.state.pixels != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + neopixel: message.state.pixels, + }, + }, + }); + } else if (message.state.white_leds != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + whiteLed: message.state.white_leds, + }, + }, + }); + } else if (message.state.red_led != null) { + this.setState({ + clue: { + ...this.state.clue, + leds: { + ...this.state.clue.leds, + redLed: message.state.red_led, + }, + }, + }); + } + } } ClueSimulator.contextType = ViewStateContext; From 2f238a2d7399d47dcec38f427cc8272ad9e89254 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Wed, 8 Apr 2020 17:13:25 -0700 Subject: [PATCH 16/16] Updated led variables --- src/view/components/clue/ClueImage.tsx | 4 ++-- src/view/components/clue/ClueSimulator.tsx | 12 ++++++------ src/view/components/clue/Clue_svg.tsx | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/view/components/clue/ClueImage.tsx b/src/view/components/clue/ClueImage.tsx index bc9329b0c..0ad426c96 100644 --- a/src/view/components/clue/ClueImage.tsx +++ b/src/view/components/clue/ClueImage.tsx @@ -18,8 +18,8 @@ interface IProps { displayMessage: string; leds: { neopixel: number[]; - redLed: boolean; - whiteLed: boolean; + isRedLedOn: boolean; + isWhiteLedOn: boolean; }; } diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index f7f6327a5..f0225d2e9 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -21,8 +21,8 @@ export const DEFAULT_CLUE_STATE: IClueState = { displayMessage: DEFAULT_IMG_CLUE, leds: { neopixel: [0, 0, 0], - redLed: false, - whiteLed: false, + isRedLedOn: false, + isWhiteLedOn: false, }, }; @@ -40,8 +40,8 @@ interface IClueState { displayMessage: string; leds: { neopixel: number[]; - redLed: boolean; - whiteLed: boolean; + isRedLedOn: boolean; + isWhiteLedOn: boolean; }; } export class ClueSimulator extends React.Component { @@ -294,7 +294,7 @@ export class ClueSimulator extends React.Component { ...this.state.clue, leds: { ...this.state.clue.leds, - whiteLed: message.state.white_leds, + isWhiteLedOn: message.state.white_leds, }, }, }); @@ -304,7 +304,7 @@ export class ClueSimulator extends React.Component { ...this.state.clue, leds: { ...this.state.clue.leds, - redLed: message.state.red_led, + isRedLedOn: message.state.red_led, }, }, }); diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index b0c43d317..f5bfe5b92 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -13,8 +13,8 @@ interface IProps { displayImage: string; leds: { neopixel: number[]; - redLed: boolean; - whiteLed: boolean; + isRedLedOn: boolean; + isWhiteLedOn: boolean; }; } export class ClueSvg extends React.Component { @@ -1163,13 +1163,13 @@ export class ClueSvg extends React.Component { } private updateLeds() { // update white led - const { whiteLed, redLed } = this.props.leds; + const { isWhiteLedOn, isRedLedOn } = this.props.leds; this.ledsRefs.whiteLeds.map( (ledRef: React.RefObject) => { if (ledRef.current && this.gradientRefs.whiteLed.current) { svg.setLed( - whiteLed, + isWhiteLedOn, CLUE_LEDS_COLORS.WHITE_LEDS_OFF, CLUE_LEDS_COLORS.WHITE_LEDS_ON, ledRef.current, @@ -1180,7 +1180,7 @@ export class ClueSvg extends React.Component { ); if (this.ledsRefs.redLed.current && this.gradientRefs.redLed.current) { svg.setLed( - redLed, + isRedLedOn, CLUE_LEDS_COLORS.RED_LED_OFF, CLUE_LEDS_COLORS.RED_LED_ON, this.ledsRefs.redLed.current,