module Gargantext.Components.App (app) where import Gargantext.Prelude import Data.Sequence as Seq import Data.Tuple.Nested ((/\)) import Gargantext.AsyncTasks as GAT import Gargantext.Components.App.Store as AppStore import Gargantext.Components.Notifications as Notifications import Gargantext.Components.Notifications.Types as NotificationsT import Gargantext.Components.Router (router) import Gargantext.Config as Config import Gargantext.Hooks (useHashRouter) import Gargantext.Hooks.FirstEffect (useFirstEffect') import Gargantext.Router as Router import Gargantext.Sessions as Sessions import Gargantext.Types (CacheParams, defaultCacheParams) import Gargantext.Utils (getter, host) import Gargantext.Utils.Reactix as R2 import Reactix as R import Reactix.Utils as RU import Record as Record import Toestand as T here :: R2.Here here = R2.here "Gargantext.Components.App" app :: R2.Leaf () app = R2.leaf appCpt appCpt :: R.Component () appCpt = here.component "container" cpt where cpt _ _ = do -- | States -- | cache' /\ cache <- R2.useBox' (defaultCacheParams :: CacheParams) -- | Hooks -- | -- load Local Storage cache (if exists) useFirstEffect' $ do R2.loadLocalStorageState R2.appParamsKey cache -- | Render -- | pure $ hydrateStore { cacheParams: cache' } -------------------------------------------------------------- type HydrateStoreProps = ( cacheParams :: CacheParams ) hydrateStore :: R2.Leaf HydrateStoreProps hydrateStore = R2.leaf hydrateStoreCpt hydrateStoreCpt :: R.Component HydrateStoreProps hydrateStoreCpt = here.component "hydrateStore" cpt where cpt { cacheParams } _ = do -- | Computed -- | wsNotification <- RU.hook $ \_ -> NotificationsT.emptyWSNotification (state :: Record AppStore.State) <- pure $ -- (cache options) { expandTableEdition: getter _.expandTableEdition cacheParams , showTree: getter _.showTree cacheParams -- (default options) } `Record.merge` (AppStore.options wsNotification) -- | Render -- | pure $ AppStore.provide state [ mainApp {} ] -------------------------------------------------------------- mainApp :: R2.Leaf () mainApp = R2.leaf mainAppCpt mainAppCpt :: R.Component () mainAppCpt = here.component "main" cpt where cpt _ _ = do boxes <- AppStore.use -- tasks <- T.useBox Nothing -- storage for asynchronous tasks reductor R.useEffectOnce' $ do void $ Sessions.load boxes.sessions -- tasks <- GAT.useTasks boxes.reloadRoot boxes.reloadForest -- NOTE Task storage is not needed with new-style notifications -- and async workers. The tasks (with their pgoress) should be -- pushed as soon as the worker computes the task's chunk -- R.useEffectOnce' $ do -- tasksStorage <- GAT.readAsyncTasks -- T.write_ tasksStorage boxes.tasks -- R.useEffectOnce' $ do -- T.write (Just tasksReductor) tasks R.useEffectOnce' $ do R2.loadLocalStorageState R2.openNodesKey boxes.forestOpen T.listen (R2.listenLocalStorageState R2.openNodesKey) boxes.forestOpen -- | Websockets R.useEffectOnce' $ do ws <- T.read boxes.wsNotification -- TODO See G.C.Forest: we need a WS connection for every backend we're connected to (Sessions.Sessions { sessions }) <- T.read boxes.sessions let session = Seq.head sessions -- here.log2 "[mainApp] sessions" sessions' wsProto <- Notifications.wsProtocol h <- host Notifications.connect ws (wsProto <> "://" <> h <> "/ws") session -- T.write_ ws boxes.wsNotification -- NOTE: Dummy subscription -- let action = NotificationsT.InsertCallback (NotificationsT.UpdateTree (-1)) "some-uuid" (\_ -> here.log "callback!") -- Notifications.performAction ws action -- Store in the box the current backend, as -- derived from the href, before the window gets -- injected with the router. R.useEffectOnce' $ do mLoc <- Config.matchCurrentLocation T.write_ mLoc boxes.backend useHashRouter Router.router boxes.route -- Install router to window pure $ router { boxes } -- Render router component