From e6bb40ba88d198a9967ae1bf998eafcd15ec5937 Mon Sep 17 00:00:00 2001
From: Benjamin Koch <snowball@c3pb.de>
Date: Thu, 17 Dec 2020 01:40:20 +0100
Subject: [PATCH] Refactor: Implement pipeBlockWithEvents with runSignalBlock

---
 src/QBar/Blocks/Qubes.hs | 48 +++++++++++-----------------------------
 1 file changed, 13 insertions(+), 35 deletions(-)

diff --git a/src/QBar/Blocks/Qubes.hs b/src/QBar/Blocks/Qubes.hs
index 50e67ac..267f814 100644
--- a/src/QBar/Blocks/Qubes.hs
+++ b/src/QBar/Blocks/Qubes.hs
@@ -5,17 +5,13 @@ import QBar.BlockOutput
 import QBar.Core
 import QBar.Qubes.AdminAPI (qubesUsageOfDefaultPool, qubesMonitorProperty, qubesGetProperty, qubesEvents, QubesPropertyInfo (..), qubesListVMs, qubesListVMsP, QubesVMState (..), vmState)
 
-import Control.Concurrent.Async
-import Control.Monad.Reader (runReaderT)
 import qualified Data.ByteString.Lazy as BL
 import qualified Data.Map as M
 import qualified Data.Text.Lazy as T
 import Data.Text.Lazy.Encoding (decodeUtf8With)
 import Data.Text.Encoding.Error (lenientDecode)
 import Pipes as P
-import Pipes.Concurrent as P
-import qualified Pipes.Prelude as P
-import qualified Pipes.Safe as P
+import Pipes.Core as P
 
 diskIcon :: T.Text
 diskIcon = "💾\xFE0E"
@@ -46,45 +42,27 @@ diskUsageQubesBlock = runPollBlock $ forever $ do
       ((unit, factor) : _) -> T.pack (show $ size `div` factor) <> unit
       _ -> T.pack (show size) <> " bytes"
 
-pipeBlockWithEvents :: forall a. Producer a BarIO ExitBlock -> (Either BlockEvent a -> BarIO (Maybe BlockOutput)) -> Block
-pipeBlockWithEvents prod block = do
-  bar <- askBar
-  (output, input) <- liftIO $ spawn $ newest 1
-  exitValue <- forkBarEffect bar $ prod >-> P.map Right >-> forever (toOutput output)
-  fromInput input >-> forever (update output)
-  liftIO $ wait exitValue
+pipeBlockWithEvents :: forall a. Producer a BarIO () -> (Either BlockEvent a -> BarIO (Maybe BlockOutput)) -> Block
+pipeBlockWithEvents prod block = runSignalBlock Nothing (Just produce) sblock
   where
-  forkBarEffect :: MonadIO m => Bar -> Effect BarIO b -> m (Async b)
-  forkBarEffect bar = liftIO . async . flip runReaderT bar . P.runSafeT . runEffect
-
-  forkEffect :: MonadIO m => Effect IO () -> m ()
-  forkEffect = void . liftIO . forkIO . runEffect
-
-  update :: Output (Either (BlockOutput, BlockEvent) a) -> Pipe (Either (BlockOutput, BlockEvent) a) (BlockState, BlockUpdateReason) BarIO ()
-  update output = await >>= \case
-    Right prop -> update' $ Right prop
-    Left (blockOutput, event) -> do
-      let state = Just (blockOutput, Nothing)
-      yield (invalidateBlockState state, EventUpdate)
-      update' $ Left event
-    where
-    update' :: Either BlockEvent a -> P.Pipe b BlockUpdate BarIO ()
-    update' prop = do
-      Just blockOutput <- lift $ block prop
-      pushBlockUpdate' (handleClick blockOutput) blockOutput
-
-    handleClick blockOutput event = do
-      forkEffect $ yield (Left (blockOutput, event)) >-> toOutput output
+    produce :: (a -> IO ()) -> BarIO ()
+    produce yield' = runEffect $ prod >-> forever (await >>= liftIO . yield')
+    sblock :: Signal a -> P.Server (Signal a) (Maybe BlockOutput) BarIO ExitBlock
+    sblock = lift . sblock' >=> respond >=> sblock
+    sblock' :: Signal a -> BarIO (Maybe BlockOutput)
+    sblock' RegularSignal = return Nothing  -- ignore timer
+    sblock' (UserSignal x) = block $ Right x
+    sblock' (EventSignal x) = block $ Left x
 
 qubesMonitorPropertyBlock :: BL.ByteString -> Block
-qubesMonitorPropertyBlock name = pipeBlockWithEvents (qubesMonitorProperty qubesEvents name >> exitBlock) handle
+qubesMonitorPropertyBlock name = pipeBlockWithEvents (qubesMonitorProperty qubesEvents name) handle
   where
     handle = fmap handle' . either (const $ liftIO $ qubesGetProperty name) return
     handle' QubesPropertyInfo {propValue, propIsDefault} = Just $ mkBlockOutput $ normalText $ decode propValue <> (if propIsDefault then " (D)" else "")
     decode = decodeUtf8With lenientDecode
 
 qubesVMCountBlock :: Block
-qubesVMCountBlock = pipeBlockWithEvents (qubesListVMsP >> exitBlock) $ fmap countVMs . either (const $ liftIO $ qubesListVMs) return where
+qubesVMCountBlock = pipeBlockWithEvents qubesListVMsP $ fmap countVMs . either (const $ liftIO $ qubesListVMs) return where
   countVMs = Just . format . M.size . M.filterWithKey isRunningVM
   isRunningVM name x = vmState x == VMRunning && name /= "dom0"
   format n = mkBlockOutput $ normalText $ T.pack (show n) <> " Qube" <> (if n /= 1 then "s" else "")
-- 
GitLab