Skip to content

Commit

Permalink
Make it possible to reload answer headless (without Blockly loaded in…
Browse files Browse the repository at this point in the history
… HTML)
  • Loading branch information
SebastienTainon committed Jun 5, 2024
1 parent acdfe47 commit f04407f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 40 deletions.
82 changes: 46 additions & 36 deletions frontend/stepper/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ let originalFireNow;
let originalSetBackgroundPathVertical_;

export function* loadBlocklyHelperSaga(context: QuickAlgoLibrary) {
let blocklyHelper;

if (!context) { return; }

if (!context) {
return;
}
if (context && context.blocklyHelper && !context.blocklyHelper.fake) {
context.blocklyHelper.unloadLevel();
}
Expand Down Expand Up @@ -73,7 +72,32 @@ export function* loadBlocklyHelperSaga(context: QuickAlgoLibrary) {
};
}

blocklyHelper = window.getBlocklyHelper(context.infos.maxInstructions, context);
context.blocklyHelper = createBlocklyHelper(context);
context.onChange = () => {};

// There is a setTimeout delay in Blockly lib between blockly program loading and Blockly firing events.
// We overload this function to catch the Blockly firing event instant so that we know when the program
// is successfully reloaded and that the events won't trigger an editor content update which would trigger
// a stepper.exit
if ('main' === state.environment) {
window.Blockly.Events.fireNow_ = () => {
originalFireNow();
context.blocklyHelper.reloading = false;
};
}

const groupsCategory = !!(context && context.infos && context.infos.includeBlocks && context.infos.includeBlocks.groupByCategory);
if (groupsCategory && 'tralalere' === options.app) {
overrideBlocklyFlyoutForCategories(isMobile);
} else if (originalSetBackgroundPathVertical_) {
window.Blockly.Flyout.prototype.setBackgroundPathVertical_ = originalSetBackgroundPathVertical_;
}

yield* put(taskIncreaseContextId());
}

export function createBlocklyHelper(context: QuickAlgoLibrary) {
const blocklyHelper = window.getBlocklyHelper(context.infos.maxInstructions, context);
log.getLogger('blockly_runner').debug('[blockly.editor] load blockly helper', context, blocklyHelper);
// Override this function to keep handling the display, and avoiding a call to un-highlight the current block
// during loadPrograms at the start of the program execution
Expand Down Expand Up @@ -101,36 +125,15 @@ export function* loadBlocklyHelperSaga(context: QuickAlgoLibrary) {
blocklyHelper.startingBlock = false;
}

context.blocklyHelper = blocklyHelper;
context.onChange = () => {};

if (!originalFireNow) {
originalFireNow = window.Blockly.Events.fireNow_;
}

// There is a setTimeout delay in Blockly lib between blockly program loading and Blockly firing events.
// We overload this function to catch the Blockly firing event instant so that we know when the program
// is successfully reloaded and that the events won't trigger an editor content update which would trigger
// a stepper.exit
if ('main' === state.environment) {
window.Blockly.Events.fireNow_ = () => {
originalFireNow();
blocklyHelper.reloading = false;
};
}

log.getLogger('blockly_runner').debug('[blockly.editor] load context into blockly editor');
blocklyHelper.loadContext(context);
blocklyHelper.setIncludeBlocks(context.infos.includeBlocks);

const groupsCategory = !!(context && context.infos && context.infos.includeBlocks && context.infos.includeBlocks.groupByCategory);
if (groupsCategory && 'tralalere' === options.app) {
overrideBlocklyFlyoutForCategories(isMobile);
} else if (originalSetBackgroundPathVertical_) {
window.Blockly.Flyout.prototype.setBackgroundPathVertical_ = originalSetBackgroundPathVertical_;
}

yield* put(taskIncreaseContextId());
return blocklyHelper;
}

export const overrideBlocklyFlyoutForCategories = (isMobile: boolean) => {
Expand Down Expand Up @@ -192,7 +195,7 @@ export const checkBlocklyCode = function (answer: Document, context: QuickAlgoLi
let blocks;
try {
// This method can fail if Blockly is not loaded in the DOM. In this case it's ok we don't make the check
blocks = getBlocksFromXml(blockly);
blocks = getBlocksFromXml(state, context, blockly);
} catch (e) {
console.error(e);
return;
Expand Down Expand Up @@ -268,7 +271,7 @@ const getBlockCount = function (block, context: QuickAlgoLibrary) {
return 1;
}

export const getBlocklyBlocksUsage = function (answer: Document, context: QuickAlgoLibrary) {
export const getBlocklyBlocksUsage = function (answer: Document, context: QuickAlgoLibrary, state: AppStore) {
// We cannot evaluate blocks as long as the answer has not been loaded into Blockly
// Thus we wait that context.blocklyHelper.programs is filled (by BlocklyEditor)
const blockly = (answer as unknown as BlockDocument)?.content?.blockly;
Expand All @@ -284,7 +287,7 @@ export const getBlocklyBlocksUsage = function (answer: Document, context: QuickA
let blocks;
try {
// This method can fail if Blockly is not loaded in the DOM. In this case it's ok we don't make the check
blocks = getBlocksFromXml(blockly);
blocks = getBlocksFromXml(state, context, blockly);
} catch (e) {
console.error(e);
return {
Expand Down Expand Up @@ -320,13 +323,20 @@ export function blocklyCount(blocks: any[], context: QuickAlgoLibrary): number {
return blocksUsed;
}

const getBlocksFromXml = function (xmlText) {
const xml = window.Blockly.Xml.textToDom(xmlText)
const tmpOptions = new window.Blockly.Options({});
const tmpWorkspace = new window.Blockly.Workspace(tmpOptions);
window.Blockly.Xml.domToWorkspace(xml, tmpWorkspace);
const getBlocksFromXml = function (state: AppStore, context: QuickAlgoLibrary, xmlText: string) {
const xml = window.Blockly.Xml.textToDom(xmlText);

const blocklyHelper = createBlocklyHelper(context);
const language = state.options.language.split('-')[0];
blocklyHelper.load(language, false, 1, {});

if (!window.Blockly.mainWorkspace) {
window.Blockly.mainWorkspace = blocklyHelper.workspace;
}

window.Blockly.Xml.domToWorkspace(xml, blocklyHelper.workspace);

return tmpWorkspace.getAllBlocks();
return blocklyHelper.workspace.getAllBlocks();
};

export const blocklyFindLimited = (blocks, limitedUses, context) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/stepper/platforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface PlatformData {
getSpecificBlocks?: (notionsBag: NotionsBag, includeBlocks?: QuickalgoTaskIncludeBlocks) => Block[],
runner?: typeof AbstractRunner,
checkCode?: (document: Document, context: QuickAlgoLibrary, state: AppStore, disabledValidations: string[]) => void,
getBlocksUsage?: (document: Document, context: QuickAlgoLibrary) => BlocksUsage,
getBlocksUsage?: (document: Document, context: QuickAlgoLibrary, state?: AppStore) => BlocksUsage,
}

const platformBundles = {
Expand Down
2 changes: 1 addition & 1 deletion frontend/task/blocks/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ function* checkSourceSaga() {
blocksUsage.error = e.toString();
}

const currentUsage = getBlocksUsage(answer);
const currentUsage = getBlocksUsage(answer, state);
if (currentUsage) {
const maxInstructions = context.infos.maxInstructions ? context.infos.maxInstructions : Infinity;

Expand Down
4 changes: 2 additions & 2 deletions frontend/task/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function checkCompilingCode(answer: TaskAnswer|null, state: AppStore, dis
}
}

export function getBlocksUsage(answer: TaskAnswer|null) {
export function getBlocksUsage(answer: TaskAnswer|null, state: AppStore) {
const context = quickAlgoLibraries.getContext(null, 'main');
if (!context || !answer) {
return null;
Expand All @@ -161,7 +161,7 @@ export function getBlocksUsage(answer: TaskAnswer|null) {
const {document, platform} = answer;

if (platformsList[platform].getBlocksUsage) {
return platformsList[platform].getBlocksUsage(document, context);
return platformsList[platform].getBlocksUsage(document, context, state);
}

return null;
Expand Down

0 comments on commit f04407f

Please sign in to comment.