Toestand.purs 2.81 KB
Newer Older
James Laver's avatar
James Laver committed
1 2 3 4
module Gargantext.Utils.Toestand
  ( class Reloadable, reload
  , Reload, newReload, InitReload(..), ready
  , useCursed, useIdentityCursor, useMemberCursor
5
  , write_, modify_
James Laver's avatar
James Laver committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  ) where

import Prelude (class Ord, Unit, bind, identity, pure, unit, void, ($), (+), (>>=))
import Data.Set as Set
import Data.Set (Set)
import Effect (Effect)
import Reactix as R
import Toestand as T

-- | Reload is a simple counter that can be used to force an update.
type Reload = Int

class Reloadable t where
  reload :: t -> Effect Unit

-- | An empty Reload is zero as it has not yet been reloaded.
newReload :: Reload
newReload = 0

instance reloadableCellReload :: Reloadable (T.Cell Int) where
26
  reload cell = modify_ (_ + 1) cell
James Laver's avatar
James Laver committed
27 28

instance reloadableCursorReload :: Reloadable (T.Cursor Int) where
29
  reload cell = modify_ (_ + 1) cell
James Laver's avatar
James Laver committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

instance reloadableInitReloadCell :: Reloadable (c Reload) => Reloadable (T.Cell (InitReload c)) where
  reload cell = do
    val <- T.read cell
    case val of
      Init    -> pure unit
      Ready r -> reload r

instance reloadableInitReloadCursor :: Reloadable (c Reload) => Reloadable (T.Cursor (InitReload c)) where
  reload cell = do
    val <- T.read cell
    case val of
      Init    -> pure unit
      Ready r -> reload r

-- c is a cell or cursor wrapping a Reload
data InitReload (c :: Type -> Type) = Init | Ready (c Reload)

-- | Initialises an InitReload cell with the Reload cell it contains,
-- | if it has not already been initialised.
ready :: forall cell c. T.ReadWrite cell (InitReload c) => T.ReadWrite (c Reload) Reload
      => cell -> (c Reload) -> Effect Unit
ready cell with = do
  val <- T.read cell
  case val of
55
    Init    -> write_ (Ready with) cell
James Laver's avatar
James Laver committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    Ready _ -> pure unit

-- | Turns a Cell into a Cursor.
useIdentityCursor :: forall cell c. T.ReadWrite cell c => cell -> R.Hooks (T.Cursor c)
useIdentityCursor = T.useCursor identity (\a _ -> a)

-- | Creates a cursor directly from a value by creating a cell first.
useCursed :: forall t. t -> R.Hooks (T.Cursor t)
useCursed val = T.useCell val >>= useIdentityCursor

-- | Creates a cursor which presents a Boolean over whether the member
-- | is in the set. Adjusting the value will toggle whether the value
-- | is in the underlying set.
useMemberCursor
  :: forall cell v. Ord v => T.ReadWrite cell (Set v)
  => v -> cell -> R.Hooks (T.Cursor Boolean)
useMemberCursor val cell = T.useCursor (Set.member val) (toggleSet val) cell

-- utility for useMemberCursor
toggleSet :: forall s. Ord s => s -> Boolean -> Set s -> Set s
toggleSet val true  set = Set.insert val set
toggleSet val false set = Set.delete val set
78 79 80 81 82 83

modify_ :: forall cell val. T.ReadWrite cell val => (val -> val) -> cell -> Effect Unit
modify_ f cell = void $ T.modify f cell

write_ :: forall cell val. T.Write cell val => val -> cell -> Effect Unit
write_ val cell = void $ T.write val cell