Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5473892
Upgrade to Blockly 12.0.1-beta.1 and plugin 0.0.8
microbit-matt-hillsdon May 15, 2025
912f78c
Fix error clicking on comments
microbit-matt-hillsdon May 23, 2025
a81e70e
Call Blockly.hideChaff when focusing the workspace
microbit-robert May 23, 2025
2a93b53
Upgrade to latest plugin release
microbit-matt-hillsdon May 25, 2025
8698407
Fix melody field navigation
microbit-matt-hillsdon May 25, 2025
48ff5d5
Fix keyboard controls help for new plugin version
microbit-matt-hillsdon May 25, 2025
17a313d
Fix logged error in initCopyPaste
microbit-matt-hillsdon May 26, 2025
a12faec
Fix mouse and keyboard interaction with the showLeds block
microbit-robert May 27, 2025
f6a2825
Return ephemeral focus when the showLeds node is blurred
microbit-robert May 27, 2025
41d3a05
CSS tweaks for Safari + image fields
microbit-matt-hillsdon May 27, 2025
b71503b
Fix more focus outlines.
microbit-matt-hillsdon May 27, 2025
2296f81
Fix show leds outline on Safari/Firefox.
microbit-matt-hillsdon May 28, 2025
333489d
Fix missing passive focus styling.
microbit-matt-hillsdon May 28, 2025
500b811
Fix passive focus case that also needs to be more specific.
microbit-matt-hillsdon May 28, 2025
75cd0e7
Merge branch 'master' into blockly-12
microbit-matt-hillsdon May 28, 2025
7159c20
Correct disabled reason to use new constant
microbit-matt-hillsdon May 29, 2025
853f4ea
Fix addConnectionHighlight issues
microbit-matt-hillsdon May 29, 2025
d1faa09
Merge branch 'master' into blockly-12
microbit-matt-hillsdon May 29, 2025
c583db3
Fix closing chaff when clicking on toolbox
microbit-matt-hillsdon May 29, 2025
e8fdae0
Merge branch 'blockly-12' of github.com:microbit-matt-hillsdon/pxt in…
microbit-matt-hillsdon May 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"built/tests/blocksrunner.js",
"built/tests/blockssetup.js",
"scripts/patchUglifyify.js",
"scripts/patchBlocklyFieldColour.js",
"docfiles",
"theme",
"common-docs",
Expand All @@ -62,9 +61,9 @@
"npm": ">=8.0.0"
},
"dependencies": {
"@blockly/field-colour": "5.0.12",
"@blockly/keyboard-experiment": "0.0.7",
"@blockly/plugin-workspace-search": "9.1.0",
"@blockly/field-colour": "6.0.0",
"@blockly/keyboard-experiment": "0.0.9",
"@blockly/plugin-workspace-search": "10.0.0",
"@crowdin/crowdin-api-client": "^1.33.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"@microsoft/applicationinsights-web": "^2.8.11",
Expand All @@ -73,7 +72,7 @@
"@zip.js/zip.js": "2.4.20",
"adm-zip": "^0.5.12",
"axios": "^1.6.8",
"blockly": "12.0.0-beta.4",
"blockly": "12.0.1-beta.1",
"browserify": "17.0.0",
"chai": "^3.5.0",
"chalk": "^4.1.2",
Expand Down Expand Up @@ -160,10 +159,10 @@
"source-map": "0.4.4"
},
"@blockly/field-colour": {
"blockly": "^12.0.0-beta.4"
"blockly": "^12.0.1-beta.1"
},
"@blockly/plugin-workspace-search": {
"blockly": "^12.0.0-beta.4"
"blockly": "^12.0.1-beta.1"
}
},
"scripts": {
Expand All @@ -183,6 +182,6 @@
"update": "gulp update",
"watch-streamer": "cd docs/static/streamer && tsc -t es6 --watch",
"prepare": "node ./scripts/npm-prepare.js",
"postinstall": "node ./scripts/patchUglifyify.js && node ./scripts/patchBlocklyFieldColour.js"
"postinstall": "node ./scripts/patchUglifyify.js"
}
}
32 changes: 15 additions & 17 deletions pxtblocks/copyPaste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,31 @@ export function initCopyPaste() {
function registerCopy() {
const copyShortcut: Blockly.ShortcutRegistry.KeyboardShortcut = {
name: Blockly.ShortcutItems.names.COPY,
preconditionFn(workspace) {
return oldCopy.preconditionFn(workspace);
preconditionFn(workspace, scope) {
return oldCopy.preconditionFn(workspace, scope);
},
callback: copy,
// the registered shortcut from blockly isn't an array, it's some sort
// of serialized object so we have to convert it back to an array
keyCodes: [oldCopy.keyCodes[0], oldCopy.keyCodes[1], oldCopy.keyCodes[2]],
keyCodes: oldCopy.keyCodes,
};
Blockly.ShortcutRegistry.registry.register(copyShortcut);
}

function registerCut() {
const cutShortcut: Blockly.ShortcutRegistry.KeyboardShortcut = {
name: Blockly.ShortcutItems.names.CUT,
preconditionFn(workspace) {
return oldCut.preconditionFn(workspace);
preconditionFn(workspace, scope) {
return oldCut.preconditionFn(workspace, scope);
},
callback(workspace, e, shortcut) {
callback(workspace, e, shortcut, scope) {
const handler = getCopyPasteHandlers()?.cut;

if (handler) {
return handler(workspace, e);
}

return oldCut.callback(workspace, e, shortcut);
return oldCut.callback(workspace, e, shortcut, scope);
},
keyCodes: [oldCut.keyCodes[0], oldCut.keyCodes[1], oldCut.keyCodes[2]],
keyCodes: oldCut.keyCodes,
};

Blockly.ShortcutRegistry.registry.register(cutShortcut);
Expand All @@ -65,11 +63,11 @@ function registerCut() {
function registerPaste() {
const pasteShortcut: Blockly.ShortcutRegistry.KeyboardShortcut = {
name: Blockly.ShortcutItems.names.PASTE,
preconditionFn(workspace) {
return oldPaste.preconditionFn(workspace);
preconditionFn(workspace, scope) {
return oldPaste.preconditionFn(workspace, scope);
},
callback: paste,
keyCodes: [oldPaste.keyCodes[0], oldPaste.keyCodes[1], oldPaste.keyCodes[2]],
keyCodes: oldPaste.keyCodes,
};

Blockly.ShortcutRegistry.registry.register(pasteShortcut);
Expand Down Expand Up @@ -168,22 +166,22 @@ function registerPasteContextMenu() {
Blockly.ContextMenuRegistry.registry.register(pasteOption);
}

const copy = (workspace: Blockly.WorkspaceSvg, e: Event, shortcut?: Blockly.ShortcutRegistry.KeyboardShortcut) => {
const copy = (workspace: Blockly.WorkspaceSvg, e: Event, shortcut?: Blockly.ShortcutRegistry.KeyboardShortcut, scope?: Blockly.ContextMenuRegistry.Scope) => {
const handler = getCopyPasteHandlers()?.copy;

if (handler) {
return handler(workspace, e);
}

return oldCopy.callback(workspace, e, shortcut);
return oldCopy.callback(workspace, e, shortcut, scope);
}

const paste = (workspace: Blockly.WorkspaceSvg, e: Event, shortcut?: Blockly.ShortcutRegistry.KeyboardShortcut) => {
const paste = (workspace: Blockly.WorkspaceSvg, e: Event, shortcut?: Blockly.ShortcutRegistry.KeyboardShortcut, scope?: Blockly.ContextMenuRegistry.Scope) => {
const handler = getCopyPasteHandlers()?.paste;

if (handler) {
return handler(workspace, e);
}

return oldPaste.callback(workspace, e, shortcut);
return oldPaste.callback(workspace, e, shortcut, scope);
}
42 changes: 33 additions & 9 deletions pxtblocks/fields/field_ledmatrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export class FieldLedMatrix extends FieldMatrix implements FieldCustom {
this.scale = 0.85;
else if (Math.max(this.numMatrixCols, this.numMatrixRows) > 10)
this.scale = 0.9;

this.size_.height = this.scale * Number(this.numMatrixRows) * (FieldLedMatrix.CELL_WIDTH + FieldLedMatrix.CELL_VERTICAL_MARGIN) + FieldLedMatrix.CELL_VERTICAL_MARGIN * 2 + FieldLedMatrix.BOTTOM_MARGIN + this.getXAxisHeight()
this.size_.width = this.scale * Number(this.numMatrixCols) * (FieldLedMatrix.CELL_WIDTH + FieldLedMatrix.CELL_HORIZONTAL_MARGIN) + FieldLedMatrix.CELL_HORIZONTAL_MARGIN + this.getYAxisWidth();
}

protected getCellToggled(x: number, y: number): boolean {
Expand All @@ -94,8 +97,12 @@ export class FieldLedMatrix extends FieldMatrix implements FieldCustom {
showEditor_() {
this.selected = [0, 0];
this.focusCell(0, 0);
this.matrixSvg.focus();
this.attachEventHandlersToMatrix();
this.returnEphemeralFocusFn = Blockly.getFocusManager().takeEphemeralFocus(this.matrixSvg);
this.addKeyboardFocusHandlers();
}

onNodeBlur() {
this.returnEphemeralFocus();
}

private initMatrix() {
Expand Down Expand Up @@ -146,7 +153,10 @@ export class FieldLedMatrix extends FieldMatrix implements FieldCustom {
}
}

this.fieldGroup_.replaceChild(this.matrixSvg, this.fieldGroup_.firstChild);
this.fieldGroup_.classList.add("blocklyFieldLedMatrixGroup");
this.fieldGroup_.append(this.matrixSvg);

this.attachEventHandlersToMatrix();
}
}

Expand Down Expand Up @@ -217,9 +227,7 @@ export class FieldLedMatrix extends FieldMatrix implements FieldCustom {

ev.stopPropagation();
ev.preventDefault();
// Clear event listeners and selection used for keyboard navigation.
this.removeKeyboardFocusHandlers();
this.clearCellSelection();
this.returnEphemeralFocus();
}, false));
}

Expand Down Expand Up @@ -291,9 +299,6 @@ export class FieldLedMatrix extends FieldMatrix implements FieldCustom {
this.initMatrix();
}

// The height and width must be set by the render function
this.size_.height = this.scale * Number(this.numMatrixRows) * (FieldLedMatrix.CELL_WIDTH + FieldLedMatrix.CELL_VERTICAL_MARGIN) + FieldLedMatrix.CELL_VERTICAL_MARGIN * 2 + FieldLedMatrix.BOTTOM_MARGIN + this.getXAxisHeight()
this.size_.width = this.scale * Number(this.numMatrixCols) * (FieldLedMatrix.CELL_WIDTH + FieldLedMatrix.CELL_HORIZONTAL_MARGIN) + FieldLedMatrix.CELL_HORIZONTAL_MARGIN + this.getYAxisWidth();
}

// The return value of this function is inserted in the code
Expand Down Expand Up @@ -373,3 +378,22 @@ function removeQuotes(str: string) {
}
return str;
}

// Override the hover stroke which doesn't make sense here.
// Restate the keyboard nav stroke more specifically than the field hover override.
Blockly.Css.register(`
.pxt-renderer.classic-theme .blocklyDraggable:not(.blocklyDisabled) .blocklyFieldLedMatrixGroup.blocklyEditableField:not(.blocklyEditing):hover>rect {
stroke: none;
}
.pxt-renderer.classic-theme .blocklyDraggable:not(.blocklyDisabled) .blocklyFieldLedMatrixGroup.blocklyActiveFocus.blocklyEditableField:not(.blocklyEditing):hover>rect {
stroke: var(--blockly-active-node-color);
stroke-width: var(--blockly-selection-width);
}
.pxt-renderer.classic-theme .blocklyDraggable:not(.blocklyDisabled) .blocklyFieldLedMatrixGroup.blocklyPassiveFocus.blocklyEditableField:not(.blocklyEditing):hover>rect {
stroke: var(--blockly-active-node-color);
stroke-dasharray: 5px 3px;
stroke-width: var(--blockly-selection-width);
}
.blocklyFieldLedMatrixGroup > .blocklyFieldRect {
fill: none !important;
}`);
17 changes: 16 additions & 1 deletion pxtblocks/fields/field_matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export abstract class FieldMatrix extends Blockly.Field {
protected abstract numMatrixCols: number;
protected abstract numMatrixRows: number;
protected abstract clearSelectionOnBlur: boolean;
protected returnEphemeralFocusFn: Blockly.ReturnEphemeralFocus | undefined = undefined;

protected createMatrixDisplay({
cellWidth,
Expand Down Expand Up @@ -157,6 +158,7 @@ export abstract class FieldMatrix extends Blockly.Field {
}
case "Escape": {
(this.sourceBlock_.workspace as Blockly.WorkspaceSvg).markFocused();
this.returnEphemeralFocus();
return;
}
default: {
Expand Down Expand Up @@ -208,11 +210,15 @@ export abstract class FieldMatrix extends Blockly.Field {
this.cells.forEach(cell => cell.forEach(cell => cell.nextElementSibling.firstElementChild.classList.remove("focusedTwoTone", "focused")));
}

protected attachEventHandlersToMatrix() {
protected addKeyboardFocusHandlers() {
if (this.sourceBlock_.isInFlyout) return;

this.addKeyDownHandler();
this.addBlurHandler();
}

protected attachEventHandlersToMatrix() {
if (this.sourceBlock_.isInFlyout) return;

for (let x = 0; x < this.numMatrixCols; ++x) {
for (let y = 0; y < this.numMatrixRows; ++y) {
Expand All @@ -221,12 +227,21 @@ export abstract class FieldMatrix extends Blockly.Field {
}
}

protected returnEphemeralFocus() {
if (this.returnEphemeralFocusFn) {
this.returnEphemeralFocusFn();
this.returnEphemeralFocusFn = undefined;
}
}

protected removeKeyboardFocusHandlers() {
if (this.keyDownBinding) {
Blockly.browserEvents.unbind(this.keyDownBinding)
this.keyDownBinding = undefined;
}
if (this.blurBinding) {
Blockly.browserEvents.unbind(this.blurBinding)
this.blurBinding = undefined;
}
}

Expand Down
13 changes: 11 additions & 2 deletions pxtblocks/fields/field_melodySandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export class FieldCustomMelody<U extends FieldCustomOptions> extends FieldMatrix
this.gallery = new pxtmelody.MelodyGallery();
this.renderEditor(contentDiv);

this.addKeyboardFocusHandlers();
this.attachEventHandlersToMatrix();
this.matrixFocusBind = Blockly.browserEvents.bind(this.matrixSvg, 'focus', this, this.handleMatrixFocus.bind(this));
this.tabKeyBind = Blockly.browserEvents.bind(contentDiv, 'keydown', this, this.handleTabKey.bind(this));
Expand Down Expand Up @@ -157,6 +158,7 @@ export class FieldCustomMelody<U extends FieldCustomOptions> extends FieldMatrix
if (!this.invalidString) {
this.size_.width = FieldCustomMelody.MUSIC_ICON_WIDTH + (FieldCustomMelody.COLOR_BLOCK_WIDTH + FieldCustomMelody.COLOR_BLOCK_SPACING) * this.numMatrixCols;
}
this.size_.height = 34;
this.sourceBlock_.setColour("#ffffff");
}

Expand Down Expand Up @@ -236,10 +238,13 @@ export class FieldCustomMelody<U extends FieldCustomOptions> extends FieldMatrix
this.gallery.stopMelody();
}
if (this.matrixFocusBind) {
Blockly.browserEvents.unbind(this.matrixFocusBind)
Blockly.browserEvents.unbind(this.matrixFocusBind);
this.matrixFocusBind = undefined;
}
if (this.tabKeyBind) {
Blockly.browserEvents.unbind(this.tabKeyBind)
Blockly.browserEvents.unbind(this.tabKeyBind);
this.tabKeyBind = undefined;

}
this.clearCellSelection();
this.removeKeyboardFocusHandlers();
Expand Down Expand Up @@ -712,6 +717,10 @@ export class FieldCustomMelody<U extends FieldCustomOptions> extends FieldMatrix
this.gallery.hide();
this.lastFocusableElement = this.doneButton;
}

isFullBlockField(): boolean {
return true;
}
}

export interface ButtonGroup {
Expand Down
2 changes: 1 addition & 1 deletion pxtblocks/fields/field_note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export class FieldNote extends Blockly.FieldNumber implements FieldCustom {
}

Blockly.DropDownDiv.setColour(this.primaryColour, this.borderColour);
Blockly.DropDownDiv.showPositionedByBlock(this, this.sourceBlock_ as Blockly.BlockSvg, () => this.onHide());
Blockly.DropDownDiv.showPositionedByBlock(this, this.sourceBlock_ as Blockly.BlockSvg, () => this.onHide(), undefined, false);


this.htmlInput_.addEventListener("keydown", this.keyHandler);
Expand Down
14 changes: 7 additions & 7 deletions pxtblocks/fields/field_textdropdown.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference path="../../built/pxtlib.d.ts" />

import * as Blockly from "blockly";
import { clearDropDownDiv, FieldCustom, FieldCustomOptions } from "./field_utils";
import { clearDropDownDiv, FieldCustom, FieldCustomOptions, isImageProperties } from "./field_utils";

export interface FieldTextDropdownOptions extends FieldCustomOptions {
values?: string;
Expand Down Expand Up @@ -140,11 +140,11 @@ export class BaseFieldTextDropdown extends Blockly.FieldTextInput {
for (let i = 0; i < options.length; i++) {
const [label, value] = options[i];
const content = (() => {
if (typeof label === 'object') {
if (isImageProperties(label)) {
// Convert ImageProperties to an HTMLImageElement.
const image = new Image(label['width'], label['height']);
image.src = label['src'];
image.alt = label['alt'] || '';
const image = new Image(label.width, label.height);
image.src = label.src;
image.alt = label.alt;
return image;
}
return label;
Expand Down Expand Up @@ -189,7 +189,7 @@ export class BaseFieldTextDropdown extends Blockly.FieldTextInput {

this.dropDownOpen_ = true;

Blockly.DropDownDiv.showPositionedByField(this, this.dropdownDispose_.bind(this));
Blockly.DropDownDiv.showPositionedByField(this, this.dropdownDispose_.bind(this), undefined, false);

this.dropdownKeydownHandler = this.dropdownKeydownListener.bind(this);
this.menu_.getElement().addEventListener('keydown', this.dropdownKeydownHandler);
Expand Down Expand Up @@ -308,7 +308,7 @@ function validateOptions(options: Blockly.MenuOption[]) {
} else if (
tuple[0] &&
typeof tuple[0] !== 'string' &&
typeof tuple[0].src !== 'string'
!isImageProperties(tuple[0])
) {
foundError = true;
pxt.error(
Expand Down
21 changes: 21 additions & 0 deletions pxtblocks/fields/field_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,4 +699,25 @@ function inflateJRes(jres: pxt.Map<pxt.JRes | string>): pxt.Map<pxt.JRes> {
export function clearDropDownDiv() {
Blockly.DropDownDiv.clearContent();
Blockly.DropDownDiv.getContentDiv().style.height = "";
}

/**
* Returns whether or not an object conforms to the ImageProperties interface.
*
* @param obj The object to test.
* @returns True if the object conforms to ImageProperties, otherwise false.
*/
export function isImageProperties(obj: any): obj is Blockly.ImageProperties {
return (
obj &&
typeof obj === 'object' &&
'src' in obj &&
typeof obj.src === 'string' &&
'alt' in obj &&
typeof obj.alt === 'string' &&
'width' in obj &&
typeof obj.width === 'number' &&
'height' in obj &&
typeof obj.height === 'number'
);
}
Loading