From 90e19eaca6282b6895fd12337739b84e1fa73398 Mon Sep 17 00:00:00 2001 From: sverben <59171289+sverben@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:38:46 +0200 Subject: [PATCH 1/3] feat: add RTC blocks --- package.json | 2 +- src/blocks/blocks.ts | 2 + src/blocks/extensions.ts | 148 +++++++++++- src/blocks/rtc.ts | 409 +++++++++++++++++++++++++++++++++ src/blocks/text.ts | 14 ++ src/generators/arduino.ts | 2 + src/generators/arduino/rtc.ts | 139 +++++++++++ src/generators/arduino/text.ts | 6 + src/msg/translations/en.ts | 23 ++ src/msg/translations/nl.ts | 23 ++ 10 files changed, 765 insertions(+), 3 deletions(-) create mode 100644 src/blocks/rtc.ts create mode 100644 src/generators/arduino/rtc.ts diff --git a/package.json b/package.json index 427e27d..0d2882a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "dist", "media" ], - "version": "3.1.1", + "version": "3.2.0", "description": "Leaphy custom Blockly blocks and arduino code generator", "name": "@leaphy-robotics/leaphy-blocks" } diff --git a/src/blocks/blocks.ts b/src/blocks/blocks.ts index 0ddd453..7035ba4 100644 --- a/src/blocks/blocks.ts +++ b/src/blocks/blocks.ts @@ -7,6 +7,7 @@ import * as leaphyClick from "./leaphy_click"; import * as arduino from "./arduino"; import * as loops from "./alternatives"; import * as mesh from "./mesh"; +import * as rtc from "./rtc"; const blocks = [ ...lists.blocks, @@ -18,6 +19,7 @@ const blocks = [ ...loops.blocks, ...leaphyCommon.blocks, ...mesh.blocks, + ...rtc.blocks, ]; export { blocks }; diff --git a/src/blocks/extensions.ts b/src/blocks/extensions.ts index 1b1afb1..abe21bd 100644 --- a/src/blocks/extensions.ts +++ b/src/blocks/extensions.ts @@ -1,7 +1,16 @@ import * as Blockly from "blockly/core"; import { listManager } from "../categories/lists"; -import { Block, BlockSvg, Connection, Workspace } from "blockly/core"; +import { + Block, + BlockSvg, + Connection, + Menu, + MenuItem, + Workspace, + WorkspaceSvg, +} from "blockly/core"; import { procedureManager } from "../generators/arduino/procedures"; +import { DateItem } from "../generators/arduino/rtc"; const xmlUtils = Blockly.utils.xml; @@ -340,14 +349,149 @@ export default function registerExtensions(blockly: typeof Blockly) { }, }; + function loadFormat(topBlock: BlockSvg, format: DateItem[]) { + let connection = topBlock.getInput("STACK")!.connection!; + connection.targetBlock()?.dispose?.(false); + + format.forEach((item) => { + const block = topBlock.workspace.newBlock( + item.type === "text" ? "fmt_text" : `fmt_${item.item}`, + ); + if (item.type === "text") block.setFieldValue(item.value, "TEXT"); + else block.setFieldValue(item.fmt, "FMT"); + + block.initSvg(); + block.render(); + connection.connect(block.previousConnection); + connection = block.nextConnection; + }); + + topBlock.render(); + } + + const DATE_FORMAT_MUTATOR = { + structure: [] as DateItem[], + + loadExtraState(state: DateItem[]) { + this.structure = state; + }, + saveExtraState() { + return this.structure; + }, + + updateStructure(block: BlockSvg, newStructure: DateItem[]) { + const field = block.getField("FORMAT") as FormatField; + if ( + JSON.stringify(newStructure) !== + JSON.stringify(field.selectedStructure()) + ) { + field.setValue("custom"); + } + + this.structure = newStructure; + }, + + decompose(workspace: WorkspaceSvg) { + const topBlock = workspace.newBlock("fmt_head"); + topBlock.initSvg(); + + const field = topBlock.getField("FORMAT") as FormatField; + field.onRefresh(() => this.compose(topBlock)); + + loadFormat(topBlock, this.structure); + return topBlock; + }, + compose(topBlock: BlockSvg) { + const result: DateItem[] = []; + let block = topBlock.getChildren(true)[0]; + if (!block) return this.updateStructure(topBlock, []); + + while (true) { + if (block.type === "fmt_text") + result.push({ + type: "text", + value: block.getFieldValue("TEXT"), + }); + else + result.push({ + type: "item", + item: block.type.split("fmt_")[1], + fmt: block.getFieldValue("FMT"), + }); + + const newBlock = block.getNextBlock(); + if (!newBlock) break; + block = newBlock; + } + + this.updateStructure(topBlock, result); + }, + }; + + type FormatOption = [string, DateItem[]]; + class FormatField extends blockly.FieldDropdown { + private refreshListeners: (() => void)[] = []; + + constructor(private options: FormatOption[]) { + const values = options.map( + ([option]) => [option, option] as [string, string], + ); + super([...values, ["%{BKY_LEAPHY_TEMPLATE_CUSTOM}", "custom"]]); + } + + protected onItemSelected_(menu: Menu, menuItem: MenuItem) { + const option = this.options.find( + (option) => option[0] === menuItem.getValue(), + ); + if (option && this.sourceBlock_) + loadFormat(this.sourceBlock_ as BlockSvg, option[1]); + if (menuItem.getValue() === "custom" && this.sourceBlock_) + loadFormat(this.sourceBlock_ as BlockSvg, []); + this.sourceBlock_?.getRootBlock()?.compose?.(this.sourceBlock_); + + super.onItemSelected_(menu, menuItem); + this.refreshListeners.forEach((listener) => listener()); + } + + selectedStructure() { + const option = this.options.find( + (option) => option[0] === this.getValue(), + ); + if (option && this.sourceBlock_) return option[1]; + if (this.getValue() === "custom" && this.sourceBlock_) return []; + } + + onRefresh(listener: () => void) { + this.refreshListeners.push(listener); + } + } + + blockly.fieldRegistry.register("field_format", FormatField); blockly.Extensions.register("list_select_extension", LIST_SELECT_EXTENSION); blockly.Extensions.register( "appendStatementInputStack", APPEND_STATEMENT_INPUT_STACK, ); - blockly.Extensions.registerMixin( + blockly.Extensions.registerMutator( "l_controls_if_mutator", CONTROLS_IF_MUTATOR_MIXIN, + undefined, + ["controls_if_elseif", "controls_if_else"], + ); + Blockly.Extensions.registerMutator( + "l_format_date_mutator", + DATE_FORMAT_MUTATOR, + undefined, + [ + "fmt_text", + "fmt_second", + "fmt_minute", + "fmt_hour", + "fmt_weekday", + "fmt_day", + "fmt_month", + "fmt_year", + ], ); blockly.Extensions.register( "procedure_select_extension", diff --git a/src/blocks/rtc.ts b/src/blocks/rtc.ts new file mode 100644 index 0000000..aae0561 --- /dev/null +++ b/src/blocks/rtc.ts @@ -0,0 +1,409 @@ +import { BlockDefinition } from "blockly/core/blocks"; + +const blocks: BlockDefinition = [ + { + type: "leaphy_i2c_rtc_get", + message0: "%{BKY_LEAPHY_RTC_GET}", + args0: [ + { + type: "field_dropdown", + name: "TYPE", + options: [ + ["%{BKY_LEAPHY_SECOND}", "second"], + ["%{BKY_LEAPHY_MINUTE}", "minute"], + ["%{BKY_LEAPHY_HOUR}", "hour"], + ["%{BKY_LEAPHY_WEEKDAY}", "weekday"], + ["%{BKY_LEAPHY_DAY}", "day"], + ["%{BKY_LEAPHY_MONTH}", "month"], + ["%{BKY_LEAPHY_YEAR}", "year"], + ], + }, + ], + style: "leaphy_blocks", + output: "Number", + }, + { + type: "leaphy_i2c_rtc_set", + message0: "%{BKY_LEAPHY_RTC_SET}", + args0: [ + { + type: "input_value", + name: "VALUE", + check: "String", + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "leaphy_i2c_rtc_format", + message0: "%{BKY_LEAPHY_RTC_FORMAT}", + style: "leaphy_blocks", + output: "String", + mutator: "l_format_date_mutator", + }, + + { + type: "fmt_head", + style: "logic_blocks", + message0: "%{BKY_LEAPHY_FORMAT} %1", + args0: [ + { + type: "field_format", + name: "FORMAT", + options: [ + [ + "%{BKY_LEAPHY_TEMPLATE_FULL_NUMERIC}", + [ + { + type: "item", + item: "day", + fmt: "2-digit", + }, + { + type: "text", + value: "/", + }, + { + type: "item", + item: "month", + fmt: "2-digit", + }, + { + type: "text", + value: "/", + }, + { + type: "item", + item: "year", + fmt: "full", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "hour", + fmt: "2-digit", + }, + { + type: "text", + value: ":", + }, + { + type: "item", + item: "minute", + fmt: "2-digit", + }, + { + type: "text", + value: ":", + }, + { + type: "item", + item: "second", + fmt: "2-digit", + }, + ], + ], + [ + "%{BKY_LEAPHY_TEMPLATE_DATE_NUMERIC}", + [ + { + type: "item", + item: "day", + fmt: "numeric", + }, + { + type: "text", + value: "/", + }, + { + type: "item", + item: "month", + fmt: "numeric", + }, + { + type: "text", + value: "/", + }, + { + type: "item", + item: "year", + fmt: "full", + }, + ], + ], + [ + "%{BKY_LEAPHY_TEMPLATE_FULL_TEXT}", + [ + { + type: "item", + item: "weekday", + fmt: "text", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "day", + fmt: "numeric", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "month", + fmt: "text", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "year", + fmt: "full", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "hour", + fmt: "numeric", + }, + { + type: "text", + value: ":", + }, + { + type: "item", + item: "minute", + fmt: "2-digit", + }, + ], + ], + [ + "%{BKY_LEAPHY_TEMPLATE_DATE_TEXT}", + [ + { + type: "item", + item: "weekday", + fmt: "text", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "day", + fmt: "numeric", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "month", + fmt: "text", + }, + { + type: "text", + value: " ", + }, + { + type: "item", + item: "year", + fmt: "full", + }, + ], + ], + [ + "%{BKY_LEAPHY_TEMPLATE_TIME}", + [ + { + type: "item", + item: "hour", + fmt: "2-digit", + }, + { + type: "text", + value: ":", + }, + { + type: "item", + item: "minute", + fmt: "2-digit", + }, + { + type: "text", + value: ":", + }, + { + type: "item", + item: "second", + fmt: "2-digit", + }, + ], + ], + ], + }, + ], + extensions: ["appendStatementInputStack"], + }, + { + type: "fmt_text", + message0: "%{BKY_LEAPHY_TEXT} %1", + args0: [ + { + type: "field_input", + name: "TEXT", + text: ":", + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "text_blocks", + }, + { + type: "fmt_second", + message0: "%{BKY_LEAPHY_SECOND} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_minute", + message0: "%{BKY_LEAPHY_MINUTE} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_hour", + message0: "%{BKY_LEAPHY_HOUR} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_weekday", + message0: "%{BKY_LEAPHY_WEEKDAY} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_TEXT}", "text"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_day", + message0: "%{BKY_LEAPHY_DAY} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_month", + message0: "%{BKY_LEAPHY_MONTH} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_NUMERIC}", "numeric"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ["%{BKY_LEAPHY_TEXT}", "text"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, + { + type: "fmt_year", + message0: "%{BKY_LEAPHY_YEAR} %{BKY_LEAPHY_WITH_FORMAT}", + args0: [ + { + type: "field_dropdown", + name: "FMT", + options: [ + ["%{BKY_LEAPHY_FULL}", "full"], + ["%{BKY_LEAPHY_2_DIGITS}", "2-digit"], + ], + }, + ], + inputsInline: true, + previousStatement: null, + nextStatement: null, + style: "leaphy_blocks", + }, +]; + +export { blocks }; diff --git a/src/blocks/text.ts b/src/blocks/text.ts index c22ebc6..1aa2192 100644 --- a/src/blocks/text.ts +++ b/src/blocks/text.ts @@ -74,6 +74,20 @@ const blocks: BlockDefinition = [ helpUrl: "%{BKY_TEXT_CHARAT_HELPURL}", inputsInline: true, }, + { + type: "text_to_double", + message0: "%{BKY_TEXT_TO_NUMBER}", + args0: [ + { + type: "input_value", + name: "VALUE", + check: "String", + }, + ], + output: "Number", + style: "text_blocks", + inputsInline: true, + }, ]; export { blocks }; diff --git a/src/generators/arduino.ts b/src/generators/arduino.ts index 880f763..4bdc566 100644 --- a/src/generators/arduino.ts +++ b/src/generators/arduino.ts @@ -452,6 +452,7 @@ import * as text from "./arduino/text"; import * as variables from "./arduino/variables"; import * as lists from "./arduino/lists"; import * as mesh from "./arduino/mesh"; +import * as rtc from "./arduino/rtc"; import { listManager } from "../categories/lists"; arduino.default(generator); @@ -468,5 +469,6 @@ text.default(generator); variables.default(generator); lists.default(generator); mesh.default(generator); +rtc.default(generator); export default generator; diff --git a/src/generators/arduino/rtc.ts b/src/generators/arduino/rtc.ts new file mode 100644 index 0000000..410ca55 --- /dev/null +++ b/src/generators/arduino/rtc.ts @@ -0,0 +1,139 @@ +import { Arduino } from "../arduino"; + +interface Text { + type: "text"; + value: string; +} +interface Item { + type: "item"; + item: string; + fmt: string; +} +export type DateItem = Text | Item; + +function getCodeGenerators(arduino: Arduino) { + function addRTCGet(type: string) { + arduino.addInclude("RTC", "#include "); + arduino.addDeclaration("RTC", "DS3231 RTC;"); + + const methods: Record = { + second: "return RTC.getSecond();", + minute: "return RTC.getMinute();", + hour: + "bool h12Flag;\n" + + " bool pmFlag;\n" + + " return RTC.getHour(h12Flag, pmFlag);", + weekday: "return RTC.getDoW();", + day: "return RTC.getDate();", + month: "bool century;\n" + " return RTC.getMonth(century);", + year: "return RTC.getYear() + 2000;", + }; + + const setup = arduino.addI2CSetup(`i2c_rtc`, "Wire.begin();\n"); + const getDeclaration = + `int rtc_get_${type}() {\n` + + ` ${setup}\n` + + ` ${methods[type]}\n` + + `}`; + arduino.addDeclaration(`RTC_GET_${type}`, getDeclaration); + + return `rtc_get_${type}()`; + } + + arduino.forBlock["leaphy_i2c_rtc_get"] = function (block) { + const type = block.getFieldValue("TYPE"); + + return [addRTCGet(type), arduino.ORDER_ATOMIC]; + }; + + arduino.forBlock["leaphy_i2c_rtc_set"] = function (block) { + arduino.addInclude("RTC", "#include "); + arduino.addDeclaration("RTC", "DS3231 RTC;"); + + const setup = arduino.addI2CSetup(`i2c_rtc`, "Wire.begin();\n"); + const getDeclaration = + `void RTCSet(String value) {\n` + + ` ${setup}\n` + + ` RTC.setYear(value.substring(0, 2).toInt());\n` + + ` RTC.setMonth(value.substring(2, 4).toInt());\n` + + ` RTC.setDate(value.substring(4, 6).toInt());\n` + + ` RTC.setDoW(value.substring(6, 7).toInt());\n` + + ` RTC.setHour(value.substring(7, 9).toInt());\n` + + ` RTC.setMinute(value.substring(9, 11).toInt());\n` + + ` RTC.setSecond(value.substring(11, 13).toInt());\n` + + `}`; + arduino.addDeclaration(`RTC_SET`, getDeclaration); + + return `RTCSet(${arduino.valueToCode( + block, + "VALUE", + arduino.ORDER_ATOMIC, + )});\n`; + }; + + arduino.forBlock["leaphy_i2c_rtc_format"] = function (block) { + arduino.addInclude("RTC", "#include "); + arduino.addDeclaration("RTC", "DS3231 RTC;"); + + const PAD_DECLARATION = + "String pad(int original) {\n" + + " if (original >= 10) return String(original);\n\n" + + ' return "0" + String(original);\n' + + "}"; + arduino.addDeclaration("PAD", PAD_DECLARATION); + + function makeID(length: number) { + const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + let result = ""; + + for (let i = 0; i < length; i++) { + result += + characters[Math.floor(Math.random() * characters.length)]; + } + + return result; + } + function getCode(item: DateItem) { + if (item.type === "text") return `"${item.value}"`; + + if (item.item === "year") { + if (item.fmt === "full") return addRTCGet("year"); + if (item.fmt === "2-digit") + return `${addRTCGet("year")} - 2000`; + } + + if (item.fmt === "numeric") return addRTCGet(item.item); + if (item.fmt === "2-digit") return `pad(${addRTCGet(item.item)})`; + if (item.item === "weekday") { + arduino.addDeclaration( + "RTC_WEEKDAYS", + 'String weekdays[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};', + ); + + return `weekdays[${addRTCGet(item.item)} - 1]`; + } + if (item.item === "month") { + arduino.addDeclaration( + "RTC_MONTHS", + 'String months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};', + ); + + return `months[${addRTCGet(item.item)} - 1]`; + } + } + + const id = makeID(5); + const getDeclaration = + `String rtc_format_${id}() {\n` + + ` String result = "";\n` + + block.saveExtraState!() + .map((item: DateItem) => ` result += ${getCode(item)};\n`) + .join("") + + ` return result;\n` + + `}`; + arduino.addDeclaration(`RTC_FORMAT_${id}`, getDeclaration); + + return [`rtc_format_${id}()`, arduino.ORDER_ATOMIC]; + }; +} +export default getCodeGenerators; diff --git a/src/generators/arduino/text.ts b/src/generators/arduino/text.ts index 172cbe3..9027103 100644 --- a/src/generators/arduino/text.ts +++ b/src/generators/arduino/text.ts @@ -29,6 +29,12 @@ function getCodeGenerators(arduino: Arduino) { return [code, arduino.ORDER_ATOMIC]; }; + + arduino.forBlock["text_to_double"] = function (block) { + const value = arduino.valueToCode(block, "VALUE", arduino.ORDER_NONE); + + return [`${value}.toDouble()`, arduino.ORDER_ATOMIC]; + }; } export default getCodeGenerators; diff --git a/src/msg/translations/en.ts b/src/msg/translations/en.ts index 8577278..d1d6e1a 100644 --- a/src/msg/translations/en.ts +++ b/src/msg/translations/en.ts @@ -504,6 +504,7 @@ messages["TEXT_TRIM_OPERATOR_LEFT"] = "trim spaces from left side of"; messages["TEXT_TRIM_OPERATOR_RIGHT"] = "trim spaces from right side of"; messages["TEXT_TRIM_TOOLTIP"] = "Return a copy of the text with spaces removed from one or both ends."; +messages["TEXT_TO_NUMBER"] = "Convert %1 to number"; messages["TODAY"] = "Today"; messages["UNDO"] = "Undo"; messages["UNNAMED_KEY"] = "unnamed"; @@ -590,5 +591,27 @@ messages["LEAPHY_MESH_CALL_PROCEDURE"] = "Call mesh block %1 on %2"; messages["LEAPHY_MESH_CALL_PROCEDURE_ALL"] = "Call mesh block %1 on all %2"; messages["LEAPHY_MESH_ON_CONNECTION"] = "On mesh connection"; messages["LEAPHY_MESH_CLIENT"] = "Sender"; +messages["LEAPHY_RTC_GET"] = "Time get %1"; +messages["LEAPHY_RTC_SET"] = "Set time to %1"; +messages["LEAPHY_RTC_FORMAT"] = "Format time"; +messages["LEAPHY_FORMAT"] = "Format"; +messages["LEAPHY_SECOND"] = "Second"; +messages["LEAPHY_MINUTE"] = "Minute"; +messages["LEAPHY_HOUR"] = "Hour"; +messages["LEAPHY_WEEKDAY"] = "Weekday"; +messages["LEAPHY_DAY"] = "Day of month"; +messages["LEAPHY_MONTH"] = "Month"; +messages["LEAPHY_YEAR"] = "Year"; +messages["LEAPHY_WITH_FORMAT"] = "with format: %1"; +messages["LEAPHY_NUMERIC"] = "Numeric"; +messages["LEAPHY_2_DIGITS"] = "2 Digits"; +messages["LEAPHY_TEXT"] = "Text"; +messages["LEAPHY_FULL"] = "Full"; +messages["LEAPHY_TEMPLATE_FULL_NUMERIC"] = "Full numeric"; +messages["LEAPHY_TEMPLATE_DATE_NUMERIC"] = "Date numeric"; +messages["LEAPHY_TEMPLATE_FULL_TEXT"] = "Full text"; +messages["LEAPHY_TEMPLATE_DATE_TEXT"] = "Date text"; +messages["LEAPHY_TEMPLATE_TIME"] = "Time"; +messages["LEAPHY_TEMPLATE_CUSTOM"] = "Custom"; export default messages; diff --git a/src/msg/translations/nl.ts b/src/msg/translations/nl.ts index 6dbc9bd..2804e7d 100644 --- a/src/msg/translations/nl.ts +++ b/src/msg/translations/nl.ts @@ -642,6 +642,7 @@ messages["TEXT_TRIM_OPERATOR_RIGHT"] = "spaties van de rechterkant verwijderen van"; messages["TEXT_TRIM_TOOLTIP"] = "Geeft een kopie van de tekst met verwijderde spaties van één of beide kanten."; +messages["TEXT_TO_NUMBER"] = "Converteer %1 naar een nummer"; messages["TODAY"] = "Vandaag"; messages["UNDO"] = "Ongedaan maken"; messages["UNNAMED_KEY"] = "zonder naam"; @@ -729,5 +730,27 @@ messages["LEAPHY_MESH_CALL_PROCEDURE"] = "Roep mesh blok %1 aan op %2"; messages["LEAPHY_MESH_CALL_PROCEDURE_ALL"] = "Roep mesh blok %1 aan op alle %2"; messages["LEAPHY_MESH_ON_CONNECTION"] = "Wanneer verbinding wordt gemaakt"; messages["LEAPHY_MESH_CLIENT"] = "Afzender"; +messages["LEAPHY_RTC_GET"] = "Haal %1 op van tijd"; +messages["LEAPHY_RTC_SET"] = "Stel tijd in op %1"; +messages["LEAPHY_RTC_FORMAT"] = "Formatteer tijd"; +messages["LEAPHY_FORMAT"] = "Formaat"; +messages["LEAPHY_SECOND"] = "Seconde"; +messages["LEAPHY_MINUTE"] = "Minuut"; +messages["LEAPHY_HOUR"] = "Uur"; +messages["LEAPHY_WEEKDAY"] = "Weekdag"; +messages["LEAPHY_DAY"] = "Dag van maand"; +messages["LEAPHY_MONTH"] = "Maand"; +messages["LEAPHY_YEAR"] = "Jaar"; +messages["LEAPHY_WITH_FORMAT"] = "in formaat: %1"; +messages["LEAPHY_NUMERIC"] = "Getallen"; +messages["LEAPHY_2_DIGITS"] = "2 Getallen"; +messages["LEAPHY_TEXT"] = "Tekst"; +messages["LEAPHY_FULL"] = "Volledig"; +messages["LEAPHY_TEMPLATE_FULL_NUMERIC"] = "Volledig nummers"; +messages["LEAPHY_TEMPLATE_DATE_NUMERIC"] = "Datum nummers"; +messages["LEAPHY_TEMPLATE_FULL_TEXT"] = "Volledig tekst"; +messages["LEAPHY_TEMPLATE_DATE_TEXT"] = "Datum tekst"; +messages["LEAPHY_TEMPLATE_TIME"] = "Tijd"; +messages["LEAPHY_TEMPLATE_CUSTOM"] = "Aangepast"; export default messages; From 74afd2902ae730217d87b3552ff36d9f4020f63d Mon Sep 17 00:00:00 2001 From: sverben <59171289+sverben@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:43:13 +0200 Subject: [PATCH 2/3] fix: eslint --- src/blocks/extensions.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/blocks/extensions.ts b/src/blocks/extensions.ts index abe21bd..eb230c7 100644 --- a/src/blocks/extensions.ts +++ b/src/blocks/extensions.ts @@ -403,10 +403,10 @@ export default function registerExtensions(blockly: typeof Blockly) { }, compose(topBlock: BlockSvg) { const result: DateItem[] = []; - let block = topBlock.getChildren(true)[0]; + let block: BlockSvg|null = topBlock.getChildren(true)[0]; if (!block) return this.updateStructure(topBlock, []); - while (true) { + while (block) { if (block.type === "fmt_text") result.push({ type: "text", @@ -419,9 +419,7 @@ export default function registerExtensions(blockly: typeof Blockly) { fmt: block.getFieldValue("FMT"), }); - const newBlock = block.getNextBlock(); - if (!newBlock) break; - block = newBlock; + block = block.getNextBlock(); } this.updateStructure(topBlock, result); From 706cf3058d02f813d12225ddc88118fb24b8adc3 Mon Sep 17 00:00:00 2001 From: sverben <59171289+sverben@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:44:06 +0200 Subject: [PATCH 3/3] chore: prettiest --- src/blocks/extensions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blocks/extensions.ts b/src/blocks/extensions.ts index eb230c7..bd9d712 100644 --- a/src/blocks/extensions.ts +++ b/src/blocks/extensions.ts @@ -403,7 +403,7 @@ export default function registerExtensions(blockly: typeof Blockly) { }, compose(topBlock: BlockSvg) { const result: DateItem[] = []; - let block: BlockSvg|null = topBlock.getChildren(true)[0]; + let block: BlockSvg | null = topBlock.getChildren(true)[0]; if (!block) return this.updateStructure(topBlock, []); while (block) {