-- | -- Module : Reflex.Localize.Trans -- Copyright : (c) 2019 ATUM SOLUTIONS AG -- License : MIT -- Maintainer : lemarwin42@gmail.com -- Stability : unstable -- Portability : non-portable -- -- Plug-in implementation for `MonadLocalized` using wrapper around `ReaderT`. -- Internal module, implementation details can be changed at any moment. module Reflex.Localize.Trans where import Control.Monad.Reader import Control.Monad.State.Strict import GHC.Generics import Language.Javascript.JSaddle.Types import Reflex import Reflex.ExternalRef import Reflex.Localize.Language import Reflex.Localize.Monad data LocalizeEnv t = LocalizeEnv { locEnvLangRef :: !(ExternalRef t Language) } deriving (Generic) -- | Allocate new environment for `LocalizeT`. newLangEnv :: (Reflex t, TriggerEvent t m, MonadIO m) => Language -> m (LocalizeEnv t) newLangEnv initLang = fmap LocalizeEnv $ newExternalRef initLang -- | Plug-in implementation of `MonadLocalized`. newtype LocalizeT t m a = LocalizeT { unLocalizeT :: ReaderT (LocalizeEnv t) m a } deriving (Functor, Applicative, Monad, Generic, MonadFix) deriving instance PostBuild t m => PostBuild t (LocalizeT t m) deriving instance NotReady t m => NotReady t (LocalizeT t m) deriving instance PerformEvent t m => PerformEvent t (LocalizeT t m) deriving instance TriggerEvent t m => TriggerEvent t (LocalizeT t m) deriving instance MonadHold t m => MonadHold t (LocalizeT t m) deriving instance MonadSample t m => MonadSample t (LocalizeT t m) deriving instance MonadIO m => MonadIO (LocalizeT t m) #ifndef ghcjs_HOST_OS deriving instance MonadJSM m => MonadJSM (LocalizeT t m) #endif deriving instance (Group q, Additive q, Query q, Eq q, MonadQuery t q m, Monad m) => MonadQuery t q (LocalizeT t m) deriving instance (Monoid w, DynamicWriter t w m) => DynamicWriter t w (LocalizeT t m) #if !MIN_VERSION_reflex(0,7,0) deriving instance (Monoid w, MonadBehaviorWriter t w m) => MonadBehaviorWriter t w (RetractT t m) #endif deriving instance (Semigroup w, EventWriter t w m) => EventWriter t w (LocalizeT t m) deriving instance (Requester t m) => Requester t (LocalizeT t m) instance MonadTrans (LocalizeT t) where lift = LocalizeT . lift {-# INLINABLE lift #-} instance MonadReader e m => MonadReader e (LocalizeT t m) where ask = lift ask {-# INLINABLE ask #-} local f (LocalizeT ma) = LocalizeT $ do r <- ask lift $ local f $ runReaderT ma r {-# INLINABLE local #-} instance MonadState s m => MonadState s (LocalizeT t m) where get = lift get {-# INLINABLE get #-} put = lift . put {-# INLINABLE put #-} instance Adjustable t m => Adjustable t (LocalizeT t m) where runWithReplace a0 a' = do r <- LocalizeT ask lift $ runWithReplace (runLocalizeT a0 r) $ fmap (`runLocalizeT` r) a' {-# INLINABLE runWithReplace #-} traverseIntMapWithKeyWithAdjust f dm0 dm' = do r <- LocalizeT ask lift $ traverseIntMapWithKeyWithAdjust (\k v -> runLocalizeT (f k v) r) dm0 dm' {-# INLINABLE traverseIntMapWithKeyWithAdjust #-} traverseDMapWithKeyWithAdjust f dm0 dm' = do r <- LocalizeT ask lift $ traverseDMapWithKeyWithAdjust (\k v -> runLocalizeT (f k v) r) dm0 dm' {-# INLINABLE traverseDMapWithKeyWithAdjust #-} traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = do r <- LocalizeT ask lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runLocalizeT (f k v) r) dm0 dm' {-# INLINABLE traverseDMapWithKeyWithAdjustWithMove #-} -- | Execute localization widget with given environment. runLocalizeT :: LocalizeT t m a -> LocalizeEnv t -> m a runLocalizeT (LocalizeT ma) e = runReaderT ma e {-# INLINEABLE runLocalizeT #-} -- | Simplified version of `runLocalizeT` runLocalize :: (Reflex t, TriggerEvent t m, MonadIO m) => Language -> LocalizeT t m a -> m a runLocalize initLang ma = do re <- newLangEnv initLang runLocalizeT ma re {-# INLINABLE runLocalize #-} instance (PerformEvent t m, MonadHold t m, Adjustable t m, MonadFix m, MonadIO (Performable m), PostBuild t m, MonadIO m) => MonadLocalized t (LocalizeT t m) where setLanguage lang = do langRef <- LocalizeT $ asks locEnvLangRef writeExternalRef langRef lang setLanguageE langE = do langRef <- LocalizeT $ asks locEnvLangRef performEvent_ $ fmap (writeExternalRef langRef) langE getLanguage = LocalizeT $ (externalRefDynamic =<< asks locEnvLangRef) {-# INLINE setLanguage #-} {-# INLINE setLanguageE #-} {-# INLINE getLanguage #-}