Repository: chanind/hanzi-writer (ts)

Issue:
The stroke color changes when writing a stroke during a highlight.
First of all, thanks for this amazing tool!
I have run into the issue that when you complete a stroke at the same time a highlight occurs, a visual bug frequently happens. I guess what's happening is that the highlight stays permanently superimposed over the stroke.
Right now I am using the hacky solution of just making the stroke and highlight colors the same so that the bug is invisible, but this has the side effect of making the highlight on complete invisible as well. An additional issue is that the "highlightCompleteColor" setting  seems to have no effect.

Here is an example with a light blue stroke color and white highlight color. The resulting strokes permanently end up in multiple different shades of blue.
![hanzi writer bug](https://user-images.githubusercontent.com/11030459/217314705-b536b6d1-5b95-45a3-a4d4-3b1d80aaa17f.png)


Pull request description:
fix: hide stroke highlight if it gets canceled
Currently, if a stroke highlight animation gets interrupted it just leaves the stroke highlight in whatever state it's in mid-animation. This PR fixes this to force the highlight to disappear when it gets interrupted rather than hanging around looking strange. Thank you to @GnitLores for finding this!

fixes #292

Patch:
diff --git a/src/characterActions.ts b/src/characterActions.ts
index 43dc8f8f..20acc713 100644
--- a/src/characterActions.ts
+++ b/src/characterActions.ts
@@ -84,7 +84,10 @@ export const highlightStroke = (
       },
       { duration },
     ),
-    new Mutation(`character.highlight.strokes.${strokeNum}.opacity`, 0, { duration }),
+    new Mutation(`character.highlight.strokes.${strokeNum}.opacity`, 0, {
+      duration,
+      force: true,
+    }),
   ];
 };
 


Test patch:
diff --git a/src/__tests__/HanziWriter-test.ts b/src/__tests__/HanziWriter-test.ts
index c1be43f4..37e6a25e 100644
--- a/src/__tests__/HanziWriter-test.ts
+++ b/src/__tests__/HanziWriter-test.ts
@@ -708,6 +708,44 @@ describe('HanziWriter', () => {
       expect(onComplete).toHaveBeenCalledTimes(1);
       expect(onComplete).toHaveBeenCalledWith({ canceled: false });
     });
+
+    it("doesn't freeze and leave the highlight showing if another highlight happens before the first finishes", async () => {
+      document.body.innerHTML = '<div id="target"></div>';
+      const writer = HanziWriter.create('target', '人', {
+        showCharacter: true,
+        charDataLoader,
+      });
+      await writer._withDataPromise;
+
+      let stroke1Resolved = false;
+      let stroke1ResolvedVal;
+      const onComplete1 = jest.fn();
+
+      // start highlighting the first stroke
+      writer.highlightStroke(0, { onComplete: onComplete1 }).then((result) => {
+        stroke1Resolved = true;
+        stroke1ResolvedVal = result;
+      });
+
+      await resolvePromises();
+      clock.tick(200);
+      await resolvePromises();
+      expect(writer._renderState!.state.character.highlight.strokes[0].opacity).not.toBe(
+        0,
+      );
+
+      expect(stroke1Resolved).toBe(false);
+
+      // starting another stroke highlight cancels the first one
+      // NOTE: In the future this may not be the case, there's no reason we can't have strokes animate independently
+      writer.highlightStroke(1);
+
+      await resolvePromises();
+      expect(stroke1Resolved).toBe(true);
+      expect(stroke1ResolvedVal).toEqual({ canceled: true });
+
+      expect(writer._renderState!.state.character.highlight.strokes[0].opacity).toBe(0);
+    });
   });
 
   describe('loopCharacterAnimation', () => {