module Gargantext.Hooks.Loader where import Gargantext.Prelude import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson) import Data.Argonaut.Core (stringify) import Data.Argonaut.Parser (jsonParser) import Data.Either (Either(..)) import Data.Maybe (Maybe(..), isJust, maybe) import Data.Tuple (fst) import Data.Tuple.Nested ((/\)) import DOM.Simple.Console (log2) import Effect.Aff (Aff) import Effect.Class (liftEffect) import Reactix as R import Web.Storage.Storage as WSS import Gargantext.Components.LoadingSpinner (loadingSpinner) import Gargantext.Utils as GU import Gargantext.Utils.Reactix as R2 useLoader :: forall path st. Eq path => path -> (path -> Aff st) -> (st -> R.Element) -> R.Hooks R.Element useLoader path loader render = do state <- R.useState' Nothing useLoaderEffect path state loader pure $ maybe (loadingSpinner {}) render (fst state) useLoaderEffect :: forall st path. Eq path => path -> R.State (Maybe st) -> (path -> Aff st) -> R.Hooks Unit useLoaderEffect path state@(state' /\ setState) loader = do oPath <- R.useRef path R.useEffect' $ do if (R.readRef oPath == path) && (isJust state') then pure $ pure unit else do R.setRef oPath path R2.affEffect "G.H.Loader.useLoaderEffect" $ do l <- loader path liftEffect $ setState $ const $ Just l useLoaderWithCache :: forall path st. Eq path => DecodeJson st => EncodeJson st => path -> (path -> String) -> (path -> Aff st) -> (st -> R.Element) -> R.Hooks R.Element useLoaderWithCache path keyFunc loader render = do state <- R.useState' Nothing useCachedLoaderEffect path keyFunc state loader pure $ maybe (loadingSpinner {}) render (fst state) useCachedLoaderEffect :: forall path st. Eq path => DecodeJson st => EncodeJson st => path -> (path -> String) -> R.State (Maybe st) -> (path -> Aff st) -> R.Hooks Unit useCachedLoaderEffect path keyFunc state@(state' /\ setState) loader = do oPath <- R.useRef path R.useEffect' $ do if (R.readRef oPath == path) && (isJust state') then pure $ pure unit else do R.setRef oPath path let key = keyFunc path localStorage <- R2.getls mState <- WSS.getItem key localStorage case mState of Nothing -> pure unit Just stStr -> case (parse stStr >>= decode) of Left err -> pure unit Right st -> setState $ const $ Just st R2.affEffect "G.H.Loader.useCachedLoaderEffect" $ do l <- loader path liftEffect $ do let value = stringify $ encodeJson l WSS.setItem key value localStorage setState $ const $ Just l where parse s = GU.mapLeft (log2 "Error parsing serialised sessions:") (jsonParser s) decode j = GU.mapLeft (log2 "Error decoding serialised sessions:") (decodeJson j)