| 
					
				 | 
			
			
				@@ -126,6 +126,8 @@ function withBatchedUpdates< 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const { history } = createHistory(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let didTapTwice: boolean = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let tappedTwiceTimer = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let cursorX = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let cursorY = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let isHoldingSpace: boolean = false; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -214,19 +216,7 @@ export class App extends React.Component<any, AppState> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             width={canvasWidth} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             height={canvasHeight} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ref={(canvas) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              // canvas is null when unmounting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if (canvas !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                this.canvas = canvas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                this.rc = rough.canvas(this.canvas); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                this.canvas.addEventListener("wheel", this.handleWheel, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  passive: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                this.canvas?.removeEventListener("wheel", this.handleWheel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ref={this.handleCanvasRef} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             onContextMenu={this.handleCanvasContextMenu} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             onPointerDown={this.handleCanvasPointerDown} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             onDoubleClick={this.handleCanvasDoubleClick} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -588,6 +578,28 @@ export class App extends React.Component<any, AppState> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private onTapStart = (event: TouchEvent) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!didTapTwice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      didTapTwice = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      clearTimeout(tappedTwiceTimer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      tappedTwiceTimer = window.setTimeout(() => (didTapTwice = false), 300); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // insert text only if we tapped twice with a single finger 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // event.touches.length === 1 will also prevent inserting text when user's zooming 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (didTapTwice && event.touches.length === 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const [touch] = event.touches; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // @ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.handleCanvasDoubleClick({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        clientX: touch.clientX, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        clientY: touch.clientY, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      didTapTwice = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      clearTimeout(tappedTwiceTimer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    event.preventDefault(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   private pasteFromClipboard = withBatchedUpdates( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     async (event: ClipboardEvent | null) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // #686 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2559,6 +2571,22 @@ export class App extends React.Component<any, AppState> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     window.addEventListener("pointerup", onPointerUp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private handleCanvasRef = (canvas: HTMLCanvasElement) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // canvas is null when unmounting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (canvas !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvas = canvas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.rc = rough.canvas(this.canvas); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvas.addEventListener("wheel", this.handleWheel, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        passive: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvas.addEventListener("touchstart", this.onTapStart); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvas?.removeEventListener("wheel", this.handleWheel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvas?.removeEventListener("touchstart", this.onTapStart); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   private handleCanvasContextMenu = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     event: React.PointerEvent<HTMLCanvasElement>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ) => { 
			 |