From 3db0957e169df0927ff6909dc63824715abf0bba Mon Sep 17 00:00:00 2001
From: Przemek Kaminski <pk@intrepidus.pl>
Date: Mon, 18 Nov 2019 08:51:48 +0100
Subject: [PATCH] [Graph] prevent edges flickering when forceAtlas is running

---
 .../Components/GraphExplorer/Controls.purs    |  4 +--
 .../GraphExplorer/ToggleButton.purs           |  7 +---
 .../Components/GraphExplorer/Types.purs       |  1 +
 src/Gargantext/Hooks/Sigmax.purs              | 36 ++++++++++++++++---
 4 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/src/Gargantext/Components/GraphExplorer/Controls.purs b/src/Gargantext/Components/GraphExplorer/Controls.purs
index 37750c32..8d26743c 100644
--- a/src/Gargantext/Components/GraphExplorer/Controls.purs
+++ b/src/Gargantext/Components/GraphExplorer/Controls.purs
@@ -13,7 +13,7 @@ module Gargantext.Components.GraphExplorer.Controls
 
 import Data.Maybe (Maybe(..))
 import DOM.Simple.Console (log, log2)
-import Data.Tuple.Nested ((/\))
+import Data.Tuple.Nested ((/\), get1)
 import Effect (Effect)
 import Effect.Timer (clearTimeout, setTimeout)
 import Prelude
@@ -81,7 +81,7 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
       --mFAPauseRef <- R.useRef Nothing
 
       --R.useEffect $ handleForceAtlasPause props.sigmaRef localControls.pauseForceAtlas mFAPauseRef
-      R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef localControls.pauseForceAtlas
+      R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef localControls.pauseForceAtlas $ get1 localControls.showEdges
 
       R.useEffectOnce' $ do
         timeoutId <- setTimeout 2000 $ do
diff --git a/src/Gargantext/Components/GraphExplorer/ToggleButton.purs b/src/Gargantext/Components/GraphExplorer/ToggleButton.purs
index 0eb70f2f..03f03140 100644
--- a/src/Gargantext/Components/GraphExplorer/ToggleButton.purs
+++ b/src/Gargantext/Components/GraphExplorer/ToggleButton.purs
@@ -63,12 +63,7 @@ edgesToggleButton sigmaRef state =
       let sigma = R.readRef sigmaRef
       let (toggled /\ setToggled) = state
       Sigmax.dependOnSigma sigma "[edgesToggleButton] sigma: Nothing" $ \s -> do
-        let settings = {
-              drawEdges: not toggled
-            , drawEdgeLabels: not toggled
-            , hideEdgesOnMove: toggled
-          }
-        Sigma.setSettings s settings
+        Sigmax.setEdges s $ not toggled
       setToggled not
     }
 
diff --git a/src/Gargantext/Components/GraphExplorer/Types.purs b/src/Gargantext/Components/GraphExplorer/Types.purs
index fd737e2a..ee2118ad 100644
--- a/src/Gargantext/Components/GraphExplorer/Types.purs
+++ b/src/Gargantext/Components/GraphExplorer/Types.purs
@@ -6,6 +6,7 @@ import Data.Array ((!!), length)
 import Data.Maybe (Maybe(..), fromJust)
 import Data.Newtype (class Newtype)
 import Partial.Unsafe (unsafePartial)
+import Reactix as R
 
 newtype Node = Node
   { id_ :: String
diff --git a/src/Gargantext/Hooks/Sigmax.purs b/src/Gargantext/Hooks/Sigmax.purs
index 82d42624..cf189eb0 100644
--- a/src/Gargantext/Hooks/Sigmax.purs
+++ b/src/Gargantext/Hooks/Sigmax.purs
@@ -20,7 +20,7 @@ import FFI.Simple (delay)
 import Gargantext.Hooks.Sigmax.Sigma as Sigma
 import Gargantext.Hooks.Sigmax.Types (Graph(..))
 import Gargantext.Utils.Reactix as R2
-import Prelude (Unit, bind, const, discard, flip, pure, unit, ($), (*>), (<$), (<$>), (<<<), (<>), (>>=))
+import Prelude (Unit, bind, const, discard, flip, pure, unit, ($), (*>), (<$), (<$>), (<<<), (<>), (>>=), not)
 import Reactix as R
 
 type Sigma =
@@ -272,14 +272,18 @@ useForceAtlas2Eff sigma settings = effect
     effect = dependOnSigma sigma sigmaNotFoundMsg withSigma
     withSigma sig = do
       --log2 startingMsg sigma
+      setEdges sig false
       Sigma.startForceAtlas2 sig settings
       --cleanupFirst sigma (Sigma.killForceAtlas2 sig)
     startingMsg = "[useForceAtlas2Eff] Starting ForceAtlas2"
     sigmaNotFoundMsg = "[useForceAtlas2Eff] Sigma not found, not initialising"
 
+-- | Effect for handling pausing FA via state changes.  We need this because
+-- | pausing can be done not only via buttons but also from the initial
+-- | setTimer.
 --handleForceAtlasPause sigmaRef (toggled /\ setToggled) mFAPauseRef = do
-handleForceAtlas2Pause :: R.Ref Sigma -> R.State Boolean -> Effect Unit
-handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) = do
+handleForceAtlas2Pause :: R.Ref Sigma -> R.State Boolean -> Boolean -> Effect Unit
+handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) showEdges = do
   let sigma = R.readRef sigmaRef
   dependOnSigma sigma "[handleForceAtlas2Pause] sigma: Nothing" $ \s -> do
     --log2 "[handleForceAtlas2Pause] mSigma: Just " s
@@ -287,8 +291,14 @@ handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) = do
     isFARunning <- Sigma.isForceAtlas2Running s
     --log2 "[handleForceAtlas2Pause] isFARunning: " isFARunning
     case Tuple toggled isFARunning of
-      Tuple true false -> Sigma.restartForceAtlas2 s
-      Tuple false true -> Sigma.stopForceAtlas2 s
+      Tuple true false -> do
+        -- hide edges during forceAtlas rendering, this prevents flickering
+        Sigma.restartForceAtlas2 s
+        setEdges s false
+      Tuple false true -> do
+        -- restore edges state
+        Sigma.stopForceAtlas2 s
+        setEdges s showEdges
       _ -> pure unit
     -- handle case when user pressed pause/start fa button before timeout fired
     --case R.readRef mFAPauseRef of
@@ -296,3 +306,19 @@ handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) = do
     --  Just timeoutId -> do
     --    R.setRef mFAPauseRef Nothing
     --    clearTimeout timeoutId
+
+setEdges :: Sigma.Sigma -> Boolean -> Effect Unit
+setEdges sigma val = do
+  let settings = {
+        drawEdges: val
+      , drawEdgeLabels: val
+      , hideEdgesOnMove: not val
+    }
+  -- prevent showing edges (via show edges button) when FA is running (flickering)
+  isFARunning <- Sigma.isForceAtlas2Running sigma
+  case Tuple val isFARunning of
+    Tuple false true ->
+      Sigma.setSettings sigma settings
+    Tuple true false ->
+      Sigma.setSettings sigma settings
+    _ -> pure unit
-- 
2.21.0