scratchfoundation / scratchfoundation/scratch-blocks
Open mutator dialog will cause part of the toolbox not visible
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 2.8k
- Forks
- 1.6k
- Avg merge
- 4h 51m
- Merged PRs (30d)
- 12
Description
Expected Behavior
When open a mutator dialog, toolbox remains visible.
Actual Behavior
When open the if else mutator dialog, part of the toolbox not visible like bellow:
when close the mutator dialog, tool box back to normal
Steps to Reproduce
Steps to reproduce the behavior:
- create a if else block
import * as Blockly from 'scratch-blocks'
import { BlockInterface } from '@/components/ir-program/program-blockly/blockly-lib/blocks/interface'
import { i18n } from '@/i18n'
/**
* 代表逻辑 if-else 的 Block
*/
const logicalIfElseBlock: BlockInterface = {
init() {
this.jsonInit({
type: 'logical_if',
message0: i18n.tc('blockly.block.ifDo'),
args0: [
{
type: 'input_value',
name: 'IF0',
check: 'Boolean'
}
],
message1: '%1',
args1: [
{
type: 'input_statement',
name: 'DO0'
}
],
mutator: 'controls_if_mutator',
category: Blockly.Categories.control,
extensions: ['colours_control', 'shape_statement']
})
},
gbtInfo() {
const info = {
tagName: 'logical',
type: 'if'
}
return info
}
}
/**
* 代表 logical_if 变量中 else-if 语句的代码块。
*/
const mutatorElseIfBlock: BlockInterface = {
init() {
this.jsonInit({
type: 'mutator_if_elseif',
message0: i18n.tc('blockly.block.elseIf'),
category: Blockly.Categories.control,
extensions: ['colours_control', 'shape_statement']
})
},
gbtInfo() {
const info = {
tagName: 'vice_logical',
type: 'elif'
}
return info
}
}
/**
* 代表 logical_if 变量中 else 语句的代码块。
*/
const mutatorElseBlock: BlockInterface = {
init() {
this.jsonInit({
type: 'mutator_if_else',
message0: i18n.tc('blockly.block.else'),
category: Blockly.Categories.control,
extensions: ['colours_control', 'shape_end']
})
},
gbtInfo() {
const info = {
tagName: 'logical',
type: 'else'
}
return info
}
}
/**
* 代表 logical_if 变量中 if 语句的代码块。
*/
const mutatorIfContainerBlock: BlockInterface = {
init() {
this.jsonInit({
type: 'mutator_if_if',
message0: i18n.tc('blockly.block.if'),
nextStatement: false,
category: Blockly.Categories.control,
extensions: ['colours_control', 'shape_hat']
})
},
gbtInfo() {
const info = {
tagName: 'logical_title',
type: 'if_title'
}
return info
}
}
/**
* Mutator 方法
*/
const CONTROLS_IF_MUTATOR_MIXIN = {
elseifCount_: 0,
elseCount_: 0,
/**
* 创建 XML 来表示 else-if 和 else 输入的数量。
*/
mutationToDom(this): Element | null {
if (!this.elseifCount_ && !this.elseCount_) {
return null
}
const container = document.createElement('mutation')
if (this.elseifCount_) {
container.setAttribute('elseif', String(this.elseifCount_))
}
if (this.elseCount_) {
container.setAttribute('else', '1')
}
return container
},
/**
* 解析 XML 以恢复 else-if 和 else 输入。
*/
domToMutation(this, xmlElement: Element) {
this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif') ?? '0', 10)
this.elseCount_ = parseInt(xmlElement.getAttribute('else') ?? '0', 10)
this.updateShape_()
},
/**
* 用该程序块的组件填充变形器对话框。
*
* @param workspace MutatorIcon 的工作区。
* @returns Root block in mutator.
*/
decompose(this, workspace: any) {
const containerBlock = workspace.newBlock('mutator_if_if')
containerBlock.initSvg()
let connection = containerBlock.nextConnection
for (let i = 1; i <= this.elseifCount_; i++) {
const elseifBlock = workspace.newBlock('mutator_if_elseif')
elseifBlock.initSvg()
connection.connect(elseifBlock.previousConnection)
connection = elseifBlock.nextConnection
}
if (this.elseCount_) {
const elseBlock = workspace.newBlock('mutator_if_else')
elseBlock.initSvg()
connection.connect(elseBlock.previousConnection)
}
return containerBlock
},
/**
* 根据变形器对话框的组件重新配置。
*
* @param containerBlock Root block in mutator.
*/
compose(this, containerBlock: any) {
let clauseBlock = containerBlock.nextConnection?.targetBlock()
// 计算组件数量.
this.elseifCount_ = 0
this.elseCount_ = 0
while (clauseBlock) {
// 判断是否为插入标记区块
if (clauseBlock.isInsertionMarker()) {
clauseBlock = clauseBlock.getNextBlock()
continue
}
switch (clauseBlock.type) {
case 'mutator_if_elseif':
this.elseifCount_++
break
case 'mutator_if_else':
this.elseCount_++
break
default:
throw TypeError(`Unknown block type: ${clauseBlock.type}`)
}
clauseBlock = clauseBlock.getNextBlock()
}
this.updateShape_()
},
/**
* 存储指向任何相连子块的指针。
*
* @param containerBlock Root block in mutator.
*/
saveConnections(this: any, containerBlock: any) {
let clauseBlock = containerBlock.nextConnection?.targetBlock()
let i = 1
while (clauseBlock) {
if (clauseBlock.isInsertionMarker()) {
clauseBlock = clauseBlock.getNextBlock()
continue
}
switch (clauseBlock.type) {
case 'mutator_if_elseif': {
const inputIf = this.getInput(`IF${i}`)
const inputDo = this.getInput(`DO${i}`)
clauseBlock.valueConnection_ = inputIf && inputIf.connection.targetConnection
clauseBlock.statementConnection_ = inputDo && inputDo.connection.targetConnection
i++
break
}
case 'mutator_if_else': {
const inputDo = this.getInput('ELSE')
clauseBlock.statementConnection_ = inputDo && inputDo.connection.targetConnection
break
}
default:
throw TypeError(`Unknown block type: ${clauseBlock.type}`)
}
clauseBlock = clauseBlock.getNextBlock()
}
},
/**
* 更新程序块,以获得正确的输入数。
*/
updateShape_(this: any) {
// Delete everything.
while (this.getInput('DummyDo')) {
this.removeInput('DummyDo')
}
if (this.getInput('ELSE')) {
this.removeInput('ELSE')
this.removeInput('DummyElse')
}
for (let i = 1; this.getInput(`IF${i}`); i++) {
this.removeInput(`IF${i}`)
this.removeInput(`DO${i}`)
}
// 重塑
for (let i = 1; i <= this.elseifCount_; i++) {
this.appendValueInput(`IF${i}`).setCheck('Boolean').appendField(i18n.tc('blockly.block.elseIf'))
this.appendDummyInput('DummyDo').appendField(i18n.tc('blockly.block.do'))
this.appendStatementInput(`DO${i}`)
}
if (this.elseCount_) {
this.appendDummyInput('DummyElse').appendField(i18n.tc('blockly.block.else'))
this.appendStatementInput('ELSE')
}
}
}
/**
* 注册变形器
*/
Blockly.Extensions.registerMutator('controls_if_mutator', CONTROLS_IF_MUTATOR_MIXIN, null, [
'mutator_if_elseif',
'mutator_if_else'
])
/**
* 注册 logical_if blocks
*/
const registerBlocks = () => {
Blockly.Blocks.logical_if = logicalIfElseBlock
Blockly.Blocks.mutator_if_else = mutatorElseBlock
Blockly.Blocks.mutator_if_elseif = mutatorElseIfBlock
Blockly.Blocks.mutator_if_if = mutatorIfContainerBlock
}
export default registerBlocks
- Click on 'mutator icon'
- Check the toolbox
System Details
Windows 10 Chrome 126.0.6478.115
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue with the supplied logical_if block registration, then inspect the mutator icon, mutator dialog, and toolbox layout behavior in scratch-blocks. Compare the toolbox before and after opening the dialog in Chrome on Windows. Done means the complete toolbox remains visible while the mutator dialog is open.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100