Skip to content

Commit

Permalink
Fix: When using the toolbox-search, auto select the found dropdown item
Browse files Browse the repository at this point in the history
Fixes: google#1940

Uses the Block State as suggested here:
google#2004 (comment)
Fixes: bug that didn't indexed the last trigram from a word
  • Loading branch information
constantinIliescu committed Feb 23, 2024
1 parent bd3cba1 commit 3cc4822
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 32 deletions.
6 changes: 6 additions & 0 deletions plugins/toolbox-search/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.2.7](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@1.2.6...@blockly/toolbox-search@1.2.7) (2024-02-23)
### Bug Fixes
* Improved search for drop down
* Improved unit tests
* Last trigram from a word was never indexed

## [1.2.6](https://github.com/google/blockly-samples/compare/@blockly/toolbox-search@1.2.5...@blockly/toolbox-search@1.2.6) (2024-02-08)

**Note:** Version bump only for package @blockly/toolbox-search
Expand Down
68 changes: 48 additions & 20 deletions plugins/toolbox-search/src/block_searcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,44 @@ export class BlockSearcher {
const blockCreationWorkspace = new Blockly.Workspace();
blockTypes.forEach((blockType) => {
const block = blockCreationWorkspace.newBlock(blockType);
this.indexBlockText(blockType.replaceAll('_', ' '), blockType);
block.inputList.forEach((input) => {
input.fieldRow.forEach((field) => {
this.indexDropdownOption(field, blockType);
this.indexBlockText(field.getText(), blockType);
const blockState = Blockly.serialization.blocks.save(block);
if (blockState != null) {
this.indexBlockText(blockType.replaceAll('_', ' '), blockState);
block.inputList.forEach((input) => {
input.fieldRow.forEach((field) => {
this.indexDropdownOption(field, blockState);
this.indexBlockText(field.getText(), blockState);
});
});
});
}
});
}

/**
* Check if the field is a dropdown, and index every text in the option
*
* @param field We need to check the type of field
* @param blockType The block type to associate the trigrams with.
* @param blockState The block state to associate the trigrams with.
*/
private indexDropdownOption(field: Blockly.Field, blockType: string) {
private indexDropdownOption(
field: Blockly.Field,
blockState: Blockly.serialization.blocks.State,
) {
if (field instanceof Blockly.FieldDropdown) {
field.getOptions(true).forEach((option) => {
const state = {...blockState};
state.fields = {...blockState.fields};
if (typeof option[0] === 'string') {
this.indexBlockText(option[0], blockType);
if (state.fields == undefined) {
state.fields = {};
}
if (field.name) {
state.fields[field.name] = option[1];
}
this.indexBlockText(option[0], state);
this.indexBlockText(option[1], state);
} else if ('alt' in option[0]) {
this.indexBlockText(option[0].alt, blockType);
this.indexBlockText(option[0].alt, state);
}
});
}
Expand All @@ -59,10 +74,10 @@ export class BlockSearcher {
* Filters the available blocks based on the current query string.
*
* @param query The text to use to match blocks against.
* @returns A list of block types matching the query.
* @returns A list of block states matching the query.
*/
blockTypesMatching(query: string): string[] {
return [
blockTypesMatching(query: string): Blockly.serialization.blocks.State[] {
const result = [
...this.generateTrigrams(query)
.map((trigram) => {
return this.trigramsToBlocks.get(trigram) ?? new Set<string>();
Expand All @@ -72,20 +87,33 @@ export class BlockSearcher {
})
.values(),
];
const resultState = result.map((item) => JSON.parse(item));
return resultState;
}

private addBlockTrigram(trigram: string, blockState: string) {
const blockSet = this.trigramsToBlocks.get(trigram) ?? new Set<string>();
blockSet.add(blockState);
this.trigramsToBlocks.set(trigram, blockSet);
}

/**
* Generates trigrams for the given text and associates them with the given
* block type.
* block state.
*
* @param text The text to generate trigrams of.
* @param blockType The block type to associate the trigrams with.
* @param blockState The block state to associate the trigrams with.
*/
private indexBlockText(text: string, blockType: string) {
private indexBlockText(
text: string,
blockState: Blockly.serialization.blocks.State,
) {
blockState.id = undefined;
blockState.extraState = undefined;
blockState.data = undefined;
const stateString = JSON.stringify(blockState);
this.generateTrigrams(text).forEach((trigram) => {
const blockSet = this.trigramsToBlocks.get(trigram) ?? new Set<string>();
blockSet.add(blockType);
this.trigramsToBlocks.set(trigram, blockSet);
this.addBlockTrigram(trigram, stateString);
});
}

Expand All @@ -101,7 +129,7 @@ export class BlockSearcher {
if (normalizedInput.length <= 3) return [normalizedInput];

const trigrams: string[] = [];
for (let start = 0; start < normalizedInput.length - 3; start++) {
for (let start = 0; start <= normalizedInput.length - 3; start++) {
trigrams.push(normalizedInput.substring(start, start + 3));
}

Expand Down
19 changes: 13 additions & 6 deletions plugins/toolbox-search/src/toolbox_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* in its flyout.
*/
import * as Blockly from 'blockly/core';
import {block} from '../node_modules/blockly/core/tooltip';
import {BlockSearcher} from './block_searcher';

/* eslint-disable @typescript-eslint/naming-convention */
Expand Down Expand Up @@ -171,13 +172,19 @@ export class ToolboxSearchCategory extends Blockly.ToolboxCategory {
*/
private matchBlocks() {
const query = this.searchField?.value || '';

this.flyoutItems_ = query
? this.blockSearcher.blockTypesMatching(query).map((blockType) => {
return {
kind: 'block',
type: blockType,
};
? this.blockSearcher.blockTypesMatching(query).map((blockState) => {
if (blockState.fields) {
return {
kind: 'block',
type: blockState.type,
fields: blockState.fields,
};
} else
return {
kind: 'block',
type: blockState.type,
};
})
: [];

Expand Down
Loading

0 comments on commit 3cc4822

Please sign in to comment.