Skip to content

Commit

Permalink
Merge pull request #46 from crt25/feature/CRT-30_freeze_task_code
Browse files Browse the repository at this point in the history
[CRT-30] Freeze task code
  • Loading branch information
pierluca authored Nov 4, 2024
2 parents 966db66 + 3607285 commit 2139e79
Show file tree
Hide file tree
Showing 27 changed files with 870 additions and 243 deletions.
12 changes: 6 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ out
# yarn
.pnp/
.pnp.*
.yarn/
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
**/.yarn/*
!**/.yarn/patches
!**/.yarn/plugins
!**/.yarn/releases
!**/.yarn/sdks
!**/.yarn/versions

# IDEs
.vs/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/blockly_compressed_vertical.js b/blockly_compressed_vertical.js
index eb84fa7c2a4cdd7d6c91ed729ba06e9cb6717bf1..295444d4a7d1beebfe8a33d4a8fdf9e78a29842e 100644
--- a/blockly_compressed_vertical.js
+++ b/blockly_compressed_vertical.js
@@ -782,7 +782,7 @@ Blockly.InsertionMarkerManager.prototype.initAvailableConnections_=function(){va
Blockly.InsertionMarkerManager.prototype.shouldUpdatePreviews_=function(a,b){var c=a.local,d=a.closest;a=a.radius;if(c&&d){if(c.type==Blockly.OUTPUT_VALUE)return!0;if(this.localConnection_&&this.closestConnection_){if(this.closestConnection_==d)return!1;c=this.localConnection_.x_+b.x-this.closestConnection_.x_;b=this.localConnection_.y_+b.y-this.closestConnection_.y_;b=Math.sqrt(c*c+b*b);return!(d&&a>b-Blockly.CURRENT_CONNECTION_PREFERENCE)}if(this.localConnection_||this.closestConnection_)console.error("Only one of localConnection_ and closestConnection_ was set.");
else return!0}else return!(!this.localConnection_||!this.closestConnection_);console.error("Returning true from shouldUpdatePreviews, but it's not clear why.");return!0};Blockly.InsertionMarkerManager.prototype.getCandidate_=function(a){for(var b=this.getStartRadius_(),c=null,d=null,e=0;e<this.availableConnections_.length;e++){var f=this.availableConnections_[e],g=f.closest(b,a);g.connection&&(c=g.connection,d=f,b=g.radius)}return{closest:c,local:d,radius:b}};
Blockly.InsertionMarkerManager.prototype.getStartRadius_=function(){return this.closestConnection_&&this.localConnection_?Blockly.CONNECTING_SNAP_RADIUS:Blockly.SNAP_RADIUS};Blockly.InsertionMarkerManager.prototype.shouldReplace_=function(){var a=this.closestConnection_,b=this.localConnection_;return b.type==Blockly.OUTPUT_VALUE?!0:b==b.sourceBlock_.getFirstStatementConnection()?!1:!this.topBlock_.nextConnection&&b.type==Blockly.PREVIOUS_STATEMENT&&a.isConnected()?!0:!1};
-Blockly.InsertionMarkerManager.prototype.shouldDelete_=function(a,b){a=a&&!!a.closest&&b!=Blockly.DELETE_AREA_TOOLBOX;return!!b&&!this.topBlock_.getParent()&&this.topBlock_.isDeletable()&&!a};Blockly.InsertionMarkerManager.prototype.maybeShowPreview_=function(a){if(!this.wouldDeleteBlock_){var b=a.closest;a=a.local;b&&b!=this.closestConnection_&&!b.sourceBlock_.isInsertionMarker()&&(this.closestConnection_=b,this.localConnection_=a,this.showPreview_())}};
+Blockly.InsertionMarkerManager.prototype.shouldDelete_=function(a,b){a=a&&!!a.closest&&b!=Blockly.DELETE_AREA_TOOLBOX;return!!b&&!this.topBlock_.getParent()&&this.topBlock_.isDeletable()&&!a};Blockly.InsertionMarkerManager.prototype.maybeShowPreview_=function(a){if(!this.wouldDeleteBlock_ && !(a.closest && a.closest.sourceBlock_.svgGroup_.classList.contains("frozen-block"))){var b=a.closest;a=a.local;b&&b!=this.closestConnection_&&!b.sourceBlock_.isInsertionMarker()&&(this.closestConnection_=b,this.localConnection_=a,this.showPreview_())}};
Blockly.InsertionMarkerManager.prototype.showPreview_=function(){this.shouldReplace_()?this.highlightBlock_():this.connectMarker_()};Blockly.InsertionMarkerManager.prototype.maybeHidePreview_=function(a){a.closest||this.hidePreview_();var b=this.closestConnection_!=a.closest;a=this.localConnection_!=a.local;this.closestConnection_&&this.localConnection_&&(b||a||this.wouldDeleteBlock_)&&this.hidePreview_();this.localConnection_=this.closestConnection_=this.markerConnection_=null};
Blockly.InsertionMarkerManager.prototype.hidePreview_=function(){this.highlightingBlock_?this.unhighlightBlock_():this.markerConnection_&&this.disconnectMarker_()};
Blockly.InsertionMarkerManager.prototype.highlightBlock_=function(){var a=this.closestConnection_,b=this.localConnection_;a.targetBlock()?(this.highlightedBlock_=a.targetBlock(),a.targetBlock().highlightForReplacement(!0)):b.type==Blockly.OUTPUT_VALUE&&(this.highlightedBlock_=a.sourceBlock_,a.sourceBlock_.highlightShapeForInput(a,!0));this.highlightingBlock_=!0};
2 changes: 1 addition & 1 deletion apps/scratch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"redux": "^3.0.0",
"redux-throttle": "^0.1.1",
"scratch-audio": "^1.0.258",
"scratch-blocks": "^1.1.206",
"scratch-blocks": "patch:scratch-blocks@npm%3A1.1.206#~/.yarn/patches/scratch-blocks-npm-1.1.206-87dc9f1fd2.patch",
"scratch-l10n": "^3.18.313",
"scratch-paint": "^2.2.408",
"scratch-render": "^1.1.39",
Expand Down
23 changes: 23 additions & 0 deletions apps/scratch/src/blocks/freeze-task-blocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import VM from "scratch-vm";

export const freezeTaskBlocks = (vm: VM, container: HTMLElement): void => {
// by default freeze the task blocks
const freezeTaskBlocks = !(vm.crtConfig?.canEditTaskBlocks ?? false);

const taskBlockIds = vm.runtime.targets
.flatMap((target) => Object.values(target.blocks._blocks))
.filter((block) => block.isTaskBlock)
.map((block) => block.id);

for (const taskBlockId of taskBlockIds) {
const block = container.querySelector<SVGGElement>(
`svg.blocklySvg .blocklyBlockCanvas g.blocklyDraggable[data-id='${taskBlockId}']`,
);

if (freezeTaskBlocks) {
block?.classList.add("frozen-block");
} else {
block?.classList.remove("frozen-block");
}
}
};
67 changes: 67 additions & 0 deletions apps/scratch/src/components/TaskConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { FormEvent, useCallback, useEffect, useState } from "react";

import VM from "scratch-vm";
import Modal from "./modal/Modal";

const TaskConfig = ({
vm,
isShown,
hideModal,
}: {
vm: VM;
isShown?: boolean;
hideModal: () => void;
}) => {
const [canEditTaskBlocks, setCanEditTaskBlocks] = useState<boolean>(false);

const onSubmit = useCallback(
(e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
e.stopPropagation();

const config = vm.crtConfig;

if (!config) {
console.error("No task config found");
return;
}

config.canEditTaskBlocks = canEditTaskBlocks;

hideModal();
},
[vm, canEditTaskBlocks],
);

useEffect(() => {
// every time the modal is opened, load the latest config values
setCanEditTaskBlocks(vm.crtConfig?.canEditTaskBlocks ?? true);
}, [isShown]);

return (
<Modal isShown={isShown}>
<h1>Task Config</h1>

<form onSubmit={onSubmit} data-testid="task-config-form">
<label>
<span>Can the blocks provided with the task be edited?</span>
<input
type="checkbox"
min="0"
checked={canEditTaskBlocks}
onChange={(e) => setCanEditTaskBlocks(e.target.checked)}
data-testid="can-edit-task-blocks-checkbox"
/>
</label>

<input
type="submit"
value="Save"
data-testid="task-config-form-submit-button"
/>
</form>
</Modal>
);
};

export default TaskConfig;
100 changes: 47 additions & 53 deletions apps/scratch/src/components/block-config/BlockConfig.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { FormEvent, useCallback, useEffect, useState } from "react";
import { ModifyBlockConfigEvent } from "../../events/modify-block-config";

import styles from "./block-config.css";
import VM from "scratch-vm";
import { UpdateBlockToolboxEvent } from "../../events/update-block-toolbox";
import Modal from "../modal/Modal";

const cannotBeUsed = 0;
const infiniteUses = -1;
Expand Down Expand Up @@ -93,65 +93,59 @@ const BlockConfig = ({ vm }: { vm: VM }) => {
[blockId, vm, canBeUsed, hasBlockLimit, blockLimit],
);

if (!blockId) {
return null;
}

return (
<div className={styles.backdrop}>
<div className={styles.modal}>
<h1>
Block Config <small>({blockId})</small>
</h1>

<form onSubmit={onSubmit} data-testid="block-config-form">
<label className={styles.inputLabel}>
<span>Can this block be used?</span>
<Modal isShown={blockId !== null}>
<h1>
Block Config <small>({blockId})</small>
</h1>

<form onSubmit={onSubmit} data-testid="block-config-form">
<label>
<span>Can this block be used?</span>
<input
type="checkbox"
min="0"
checked={canBeUsed}
onChange={(e) => setCanBeUsed(e.target.checked)}
data-testid="can-be-used-checkbox"
/>
</label>

{canBeUsed && (
<label>
<span>
Is there a limit to how many times this block can be used?
</span>
<input
type="checkbox"
min="0"
checked={canBeUsed}
onChange={(e) => setCanBeUsed(e.target.checked)}
data-testid="can-be-used-checkbox"
checked={hasBlockLimit}
onChange={(e) => setHasBlockLimit(e.target.checked)}
data-testid="has-block-limit-checkbox"
/>
</label>
)}

{canBeUsed && (
<label className={styles.inputLabel}>
<span>
Is there a limit to how many times this block can be used?
</span>
<input
type="checkbox"
min="0"
checked={hasBlockLimit}
onChange={(e) => setHasBlockLimit(e.target.checked)}
data-testid="has-block-limit-checkbox"
/>
</label>
)}

{hasBlockLimit && (
<label className={styles.inputLabel}>
<span>How many times can this block be used?</span>
<input
type="number"
min="1"
value={blockLimit}
onChange={(e) => setBlockLimit(e.target.value)}
data-testid="block-limit-input"
/>
</label>
)}

<input
type="submit"
value="Save"
data-testid="block-config-form-submit-button"
/>
</form>
</div>
</div>
{hasBlockLimit && (
<label>
<span>How many times can this block be used?</span>
<input
type="number"
min="1"
value={blockLimit}
onChange={(e) => setBlockLimit(e.target.value)}
data-testid="block-limit-input"
/>
</label>
)}

<input
type="submit"
value="Save"
data-testid="block-config-form-submit-button"
/>
</form>
</Modal>
);
};

Expand Down
2 changes: 2 additions & 0 deletions apps/scratch/src/components/gui/Gui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ const GUIComponent = (props: {
loading={loading}
stageSize={STAGE_SIZE_MODES.large}
vm={vm}
canEditTask={canEditTask}
/>
) : (
<Box
Expand Down Expand Up @@ -350,6 +351,7 @@ const GUIComponent = (props: {
isStageInteractive={canEditTask}
stageSize={stageSize}
vm={vm}
canEditTask={canEditTask}
/>
<Box className={styles.targetWrapper}>
<TargetPane
Expand Down
22 changes: 22 additions & 0 deletions apps/scratch/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import styles from "./modal.css";

const Modal = ({
isShown,
children,
}: {
isShown?: boolean;
children: React.ReactNode;
}) => {
if (!isShown) {
return null;
}

return (
<div className={styles.backdrop}>
<div className={styles.modal}>{children}</div>
</div>
);
};

export default Modal;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
display: flex;
flex-direction: column;
align-items: center;

}

.modal {
Expand All @@ -27,20 +26,33 @@
h1 {
margin-top: 0;
}
}

.input-label {
margin-bottom: 1rem;
display: block;

span {
label {
margin-bottom: 1rem;
display: block;
margin-bottom: 0.5rem;

span {
display: block;
margin-bottom: 0.5rem;
}

input {
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
border: #000 1px solid;
}
}

input {
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
input[type="submit"] {
background: #fff;
border: #000 1px solid;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;

cursor: pointer;

&:hover{
background-color: #ddd;
}
}
}
}
Loading

0 comments on commit 2139e79

Please sign in to comment.