Repository: chanind/hanzi-writer
Pull request #72 (2018-03-06 02:36:50)

fixing a bug where strokes can be partially opaque when quizzing quickly
This is a regression on #43. Also adding tests on this case.


Patch:
diff --git a/src/RenderState.js b/src/RenderState.js
index aed0f2db..b358fedc 100644
--- a/src/RenderState.js
+++ b/src/RenderState.js
@@ -96,7 +96,7 @@ RenderState.prototype.cancelMutations = function(scopes) {
   this._mutationChains.forEach(chain => {
     chain._scopes.forEach(chainScope => {
       scopes.forEach(scope => {
-        if (chainScope.indexOf(scope) >= 0) {
+        if (chainScope.indexOf(scope) >= 0 || scope.indexOf(chainScope) >= 0) {
           this._cancelMutationChain(chain);
         }
       });
diff --git a/src/characterActions.js b/src/characterActions.js
index a3ea4a27..698d2e80 100644
--- a/src/characterActions.js
+++ b/src/characterActions.js
@@ -76,15 +76,10 @@ const highlightStroke = (charName, stroke, speed) => {
 
 const showStroke = (charName, strokeNum, duration) => {
   return [
-    new Mutation(`character.${charName}`, {
+    new Mutation(`character.${charName}.strokes.${strokeNum}`, {
+      displayPortion: 1,
       opacity: 1,
-      strokes: {
-        [strokeNum]: {
-          displayPortion: 1,
-          opacity: 1,
-        },
-      },
-    }, { duration }),
+    }, { duration, force: true }),
   ];
 };
 
diff --git a/src/quizActions.js b/src/quizActions.js
index 3b2814da..74a155e0 100644
--- a/src/quizActions.js
+++ b/src/quizActions.js
@@ -7,12 +7,12 @@ const startQuiz = (character, fadeDuration) => {
     .concat([
       new Mutation('character.highlight', {
         opacity: 1,
-        strokes: objRepeat({ opacity: 0, force: true }, character.strokes.length),
-      }),
+        strokes: objRepeat({ opacity: 0 }, character.strokes.length),
+      }, { force: true }),
       new Mutation('character.main', {
         opacity: 1,
-        strokes: objRepeat({ opacity: 0, force: true }, character.strokes.length),
-      }),
+        strokes: objRepeat({ opacity: 0 }, character.strokes.length),
+      }, { force: true }),
     ]);
 };
 


Test patch:
diff --git a/src/__tests__/Quiz-test.js b/src/__tests__/Quiz-test.js
index c08fcd97..00caa4cf 100644
--- a/src/__tests__/Quiz-test.js
+++ b/src/__tests__/Quiz-test.js
@@ -495,4 +495,59 @@ describe('Quiz', () => {
       });
     });
   });
+
+  it('doesnt leave strokes partially drawn if the users finishes the quiz really fast', async () => {
+    strokeMatches.mockImplementation(() => true);
+    const renderState = createRenderState();
+    const quiz = new Quiz(char, renderState, new Positioner());
+
+    quiz.startQuiz(Object.assign({}, opts));
+    clock.tick(1000);
+    await resolvePromises();
+
+    quiz.startUserStroke({x: 10, y: 20});
+    quiz.continueUserStroke({x: 11, y: 23});
+    quiz.endUserStroke();
+    clock.tick(100);
+    await resolvePromises();
+
+    quiz.startUserStroke({x: 10, y: 20});
+    quiz.continueUserStroke({x: 11, y: 23});
+    quiz.endUserStroke();
+    clock.tick(100);
+    await resolvePromises();
+
+    clock.tick(1000);
+    await resolvePromises();
+
+    expect(renderState.state.character.main.opacity).toBe(1);
+    expect(renderState.state.character.main.strokes[0].opacity).toBe(1);
+    expect(renderState.state.character.main.strokes[1].opacity).toBe(1);
+  });
+
+  it('sets up character opacities correctly if the users starts drawing during char fading', async () => {
+    strokeMatches.mockImplementation(() => true);
+    const renderState = createRenderState();
+    const quiz = new Quiz(char, renderState, new Positioner());
+
+    quiz.startQuiz(Object.assign({}, opts));
+    clock.tick(20);
+    await resolvePromises();
+
+    quiz.startUserStroke({x: 10, y: 20});
+    quiz.continueUserStroke({x: 12, y: 23});
+    quiz.endUserStroke();
+    clock.tick(100);
+    await resolvePromises();
+    clock.tick(1000);
+    await resolvePromises();
+
+    expect(renderState.state.character.main.opacity).toBe(1);
+    expect(renderState.state.character.main.strokes[0].opacity).toBe(1);
+    expect(renderState.state.character.main.strokes[1].opacity).toBe(0);
+
+    expect(renderState.state.character.highlight.opacity).toBe(1);
+    expect(renderState.state.character.highlight.strokes[0].opacity).toBe(0);
+    expect(renderState.state.character.highlight.strokes[1].opacity).toBe(0);
+  });
 });