Merge pull request #771 from paulkaplan/ask-with-say

Allow ask to use say bubble via events
This commit is contained in:
Paul Kaplan 2017-11-10 10:24:07 -05:00 committed by GitHub
commit ba5b3093f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 8 deletions

View file

@ -23,10 +23,14 @@ class Scratch3LooksBlocks {
this._onTargetMoved = this._onTargetMoved.bind(this); this._onTargetMoved = this._onTargetMoved.bind(this);
this._onResetBubbles = this._onResetBubbles.bind(this); this._onResetBubbles = this._onResetBubbles.bind(this);
this._onTargetWillExit = this._onTargetWillExit.bind(this); this._onTargetWillExit = this._onTargetWillExit.bind(this);
this._updateBubble = this._updateBubble.bind(this);
// Reset all bubbles on start/stop // Reset all bubbles on start/stop
this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles); this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles);
this.runtime.on('targetWasRemoved', this._onTargetWillExit); this.runtime.on('targetWasRemoved', this._onTargetWillExit);
// Enable other blocks to use bubbles like ask/answer
this.runtime.on('SAY', this._updateBubble);
} }
/** /**

View file

@ -53,19 +53,31 @@ class Scratch3SensingBlocks {
this._answer = answer; this._answer = answer;
const questionObj = this._questionList.shift(); const questionObj = this._questionList.shift();
if (questionObj) { if (questionObj) {
const resolve = questionObj[1]; const [_question, resolve, target, wasVisible] = questionObj;
// If the target was visible when asked, hide the say bubble.
if (wasVisible) {
this.runtime.emit('SAY', target, 'say', '');
}
resolve(); resolve();
this._askNextQuestion(); this._askNextQuestion();
} }
} }
_enqueueAsk (question, resolve) { _enqueueAsk (question, resolve, target, wasVisible) {
this._questionList.push([question, resolve]); this._questionList.push([question, resolve, target, wasVisible]);
} }
_askNextQuestion () { _askNextQuestion () {
if (this._questionList.length > 0) { if (this._questionList.length > 0) {
this.runtime.emit('QUESTION', this._questionList[0][0]); const [question, _resolve, target, wasVisible] = this._questionList[0];
// If the target is visible, emit a blank question and use the
// say event to trigger a bubble.
if (wasVisible) {
this.runtime.emit('SAY', target, 'say', question);
this.runtime.emit('QUESTION', '');
} else {
this.runtime.emit('QUESTION', question);
}
} }
} }
@ -74,10 +86,11 @@ class Scratch3SensingBlocks {
this.runtime.emit('QUESTION', null); this.runtime.emit('QUESTION', null);
} }
askAndWait (args) { askAndWait (args, util) {
const _target = util.target;
return new Promise(resolve => { return new Promise(resolve => {
const isQuestionAsked = this._questionList.length > 0; const isQuestionAsked = this._questionList.length > 0;
this._enqueueAsk(args.QUESTION, resolve); this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible);
if (!isQuestionAsked) { if (!isQuestionAsked) {
this._askNextQuestion(); this._askNextQuestion();
} }

View file

@ -9,9 +9,10 @@ test('getPrimitives', t => {
t.end(); t.end();
}); });
test('ask and answer', t => { test('ask and answer with a hidden target', t => {
const rt = new Runtime(); const rt = new Runtime();
const s = new Sensing(rt); const s = new Sensing(rt);
const util = {target: {visible: false}};
const expectedQuestion = 'a question'; const expectedQuestion = 'a question';
const expectedAnswer = 'the answer'; const expectedAnswer = 'the answer';
@ -24,7 +25,7 @@ test('ask and answer', t => {
}); });
// (1) Emit the question. // (1) Emit the question.
const promise = s.askAndWait({QUESTION: expectedQuestion}); const promise = s.askAndWait({QUESTION: expectedQuestion}, util);
// (3) Ask block resolves after the answer is emitted. // (3) Ask block resolves after the answer is emitted.
promise.then(() => { promise.then(() => {
@ -32,3 +33,35 @@ test('ask and answer', t => {
t.end(); t.end();
}); });
}); });
test('ask and answer with a visible target', t => {
const rt = new Runtime();
const s = new Sensing(rt);
const util = {target: {visible: true}};
const expectedQuestion = 'a question';
const expectedAnswer = 'the answer';
rt.removeAllListeners('SAY'); // Prevent say blocks from executing
rt.addListener('SAY', (target, type, question) => {
// Should emit SAY with the question
t.strictEqual(question, expectedQuestion);
});
rt.addListener('QUESTION', question => {
// Question should be blank for a visible target
t.strictEqual(question, '');
// Remove the say listener and add a new one to assert bubble is cleared
// by setting say to empty string after answer is received.
rt.removeAllListeners('SAY');
rt.addListener('SAY', (target, type, text) => {
t.strictEqual(text, '');
t.end();
});
rt.emit('ANSWER', expectedAnswer);
});
s.askAndWait({QUESTION: expectedQuestion}, util);
});