-----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Miso.Native.Element.Frame.Event
-- Copyright   :  (C) 2016-2026 David M. Johnson
-- License     :  BSD3-style (see the file LICENSE)
-- Maintainer  :  David M. Johnson <code@dmj.io>
-- Stability   :  experimental
-- Portability :  non-portable
----------------------------------------------------------------------------
module Miso.Native.Element.Frame.Event
  ( -- *** Events
    onLoad
  , onLoadWith
  , onLoadMain
  , onLoadMainWith
  , onLoadMetrics
  , onLoadMetricsWith
  , onLoadMetricsMain
  , onLoadMetricsMainWith
    -- *** Types
  , FrameLoadEvent (..)
  , FrameLoadMetricsEvent (..)
    -- *** Decoders
  , frameLoadDecoder
  , frameLoadMetricsDecoder
    -- *** Event Map
  , frameEvents
  ) where
-----------------------------------------------------------------------------
import qualified Data.Map as M
-----------------------------------------------------------------------------
import           Miso.Event
import           Miso.JSON
import           Miso.String (MisoString)
import           Miso.Types (Attribute, EventHandler, DOMRef)
-----------------------------------------------------------------------------
frameEvents :: Events
frameEvents :: Events
frameEvents
  = [(MisoString, Phase)] -> Events
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
  [ (MisoString
"load", Phase
BUBBLE)
  , (MisoString
"loadmetrics", Phase
BUBBLE)
  ]
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/frame.html#bindload
--
-- Triggered when the embedded \<frame\> page finishes loading.
data FrameLoadEvent
  = FrameLoadEvent
  { FrameLoadEvent -> Int
loadStatusCode :: Int
    -- ^ The load status code
  , FrameLoadEvent -> MisoString
loadStatusMessage :: MisoString
    -- ^ The load status message
  , FrameLoadEvent -> MisoString
loadUrl :: MisoString
    -- ^ The url of the loaded \<frame\> resource
  } deriving (Int -> FrameLoadEvent -> ShowS
[FrameLoadEvent] -> ShowS
FrameLoadEvent -> String
(Int -> FrameLoadEvent -> ShowS)
-> (FrameLoadEvent -> String)
-> ([FrameLoadEvent] -> ShowS)
-> Show FrameLoadEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FrameLoadEvent -> ShowS
showsPrec :: Int -> FrameLoadEvent -> ShowS
$cshow :: FrameLoadEvent -> String
show :: FrameLoadEvent -> String
$cshowList :: [FrameLoadEvent] -> ShowS
showList :: [FrameLoadEvent] -> ShowS
Show, FrameLoadEvent -> FrameLoadEvent -> Bool
(FrameLoadEvent -> FrameLoadEvent -> Bool)
-> (FrameLoadEvent -> FrameLoadEvent -> Bool) -> Eq FrameLoadEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FrameLoadEvent -> FrameLoadEvent -> Bool
== :: FrameLoadEvent -> FrameLoadEvent -> Bool
$c/= :: FrameLoadEvent -> FrameLoadEvent -> Bool
/= :: FrameLoadEvent -> FrameLoadEvent -> Bool
Eq)
-----------------------------------------------------------------------------
frameLoadDecoder :: Decoder FrameLoadEvent
frameLoadDecoder :: Decoder FrameLoadEvent
frameLoadDecoder = [MisoString
"detail"] [MisoString]
-> (Value -> Parser FrameLoadEvent) -> Decoder FrameLoadEvent
forall a. [MisoString] -> (Value -> Parser a) -> Decoder a
`at` Value -> Parser FrameLoadEvent
details
  where
    details :: Value -> Parser FrameLoadEvent
details = MisoString
-> (Object -> Parser FrameLoadEvent)
-> Value
-> Parser FrameLoadEvent
forall a. MisoString -> (Object -> Parser a) -> Value -> Parser a
withObject MisoString
"detail" ((Object -> Parser FrameLoadEvent)
 -> Value -> Parser FrameLoadEvent)
-> (Object -> Parser FrameLoadEvent)
-> Value
-> Parser FrameLoadEvent
forall a b. (a -> b) -> a -> b
$ \Object
o ->
      Int -> MisoString -> MisoString -> FrameLoadEvent
FrameLoadEvent
        (Int -> MisoString -> MisoString -> FrameLoadEvent)
-> Parser Int
-> Parser (MisoString -> MisoString -> FrameLoadEvent)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> MisoString -> Parser Int
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"statusCode"
        Parser (MisoString -> MisoString -> FrameLoadEvent)
-> Parser MisoString -> Parser (MisoString -> FrameLoadEvent)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> MisoString -> Parser MisoString
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"statusMessage"
        Parser (MisoString -> FrameLoadEvent)
-> Parser MisoString -> Parser FrameLoadEvent
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> MisoString -> Parser MisoString
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"url"
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/frame.html#bindloadmetrics
--
-- Triggered with performance metrics for the embedded \<frame\> page load.
data FrameLoadMetricsEvent
  = FrameLoadMetricsEvent
  { FrameLoadMetricsEvent -> Object
metricsEntry :: Object
    -- ^ The @FrameLoadMetricsEntry@ payload
  , FrameLoadMetricsEvent -> MisoString
metricsMode :: MisoString
    -- ^ The load mode
  , FrameLoadMetricsEvent -> MisoString
metricsUrl :: MisoString
    -- ^ The url of the loaded \<frame\> resource
  } deriving (Int -> FrameLoadMetricsEvent -> ShowS
[FrameLoadMetricsEvent] -> ShowS
FrameLoadMetricsEvent -> String
(Int -> FrameLoadMetricsEvent -> ShowS)
-> (FrameLoadMetricsEvent -> String)
-> ([FrameLoadMetricsEvent] -> ShowS)
-> Show FrameLoadMetricsEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FrameLoadMetricsEvent -> ShowS
showsPrec :: Int -> FrameLoadMetricsEvent -> ShowS
$cshow :: FrameLoadMetricsEvent -> String
show :: FrameLoadMetricsEvent -> String
$cshowList :: [FrameLoadMetricsEvent] -> ShowS
showList :: [FrameLoadMetricsEvent] -> ShowS
Show, FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool
(FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool)
-> (FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool)
-> Eq FrameLoadMetricsEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool
== :: FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool
$c/= :: FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool
/= :: FrameLoadMetricsEvent -> FrameLoadMetricsEvent -> Bool
Eq)
-----------------------------------------------------------------------------
frameLoadMetricsDecoder :: Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder :: Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder = [MisoString
"detail"] [MisoString]
-> (Value -> Parser FrameLoadMetricsEvent)
-> Decoder FrameLoadMetricsEvent
forall a. [MisoString] -> (Value -> Parser a) -> Decoder a
`at` Value -> Parser FrameLoadMetricsEvent
details
  where
    details :: Value -> Parser FrameLoadMetricsEvent
details = MisoString
-> (Object -> Parser FrameLoadMetricsEvent)
-> Value
-> Parser FrameLoadMetricsEvent
forall a. MisoString -> (Object -> Parser a) -> Value -> Parser a
withObject MisoString
"detail" ((Object -> Parser FrameLoadMetricsEvent)
 -> Value -> Parser FrameLoadMetricsEvent)
-> (Object -> Parser FrameLoadMetricsEvent)
-> Value
-> Parser FrameLoadMetricsEvent
forall a b. (a -> b) -> a -> b
$ \Object
o ->
      Object -> MisoString -> MisoString -> FrameLoadMetricsEvent
FrameLoadMetricsEvent
        (Object -> MisoString -> MisoString -> FrameLoadMetricsEvent)
-> Parser Object
-> Parser (MisoString -> MisoString -> FrameLoadMetricsEvent)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> MisoString -> Parser Object
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"entry"
        Parser (MisoString -> MisoString -> FrameLoadMetricsEvent)
-> Parser MisoString
-> Parser (MisoString -> FrameLoadMetricsEvent)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> MisoString -> Parser MisoString
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"mode"
        Parser (MisoString -> FrameLoadMetricsEvent)
-> Parser MisoString -> Parser FrameLoadMetricsEvent
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> MisoString -> Parser MisoString
forall a. FromJSON a => Object -> MisoString -> Parser a
.: MisoString
"url"
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/frame.html#bindload
--
-- @
--
-- data Action = HandleLoad FrameLoadEvent
--
-- view :: context -> props -> Model -> View context Action
-- view _ _ model = frame_ [ src_ "http://url", onLoad HandleLoad ] []
--
-- update :: Action -> Effect props Model Action
-- update (HandleLoad FrameLoadEvent {..}) =
--   io_ (consoleLog "frame load event received")
--
-- @
--
onLoad :: (FrameLoadEvent -> action) -> Attribute model action
onLoad :: forall action model.
(FrameLoadEvent -> action) -> Attribute model action
onLoad FrameLoadEvent -> action
action = MisoString
-> Decoder FrameLoadEvent
-> (FrameLoadEvent -> model -> DOMRef -> action)
-> Attribute model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> Attribute model action
on MisoString
"load" Decoder FrameLoadEvent
frameLoadDecoder (\FrameLoadEvent
e model
_ DOMRef
_ -> FrameLoadEvent -> action
action FrameLoadEvent
e)
-----------------------------------------------------------------------------
-- | Like 'onLoad', but dispatched on the Lynx __main thread__ ('MTS').
--
-- Runs imperatively on the MTS (no VDOM diff). Meant to be used with
-- @-XStaticPointers@.
--
-- @
-- data Action = HandleLoad FrameLoadEvent
--
-- view_ [ event (static (onLoadMain HandleLoad)) ] [ "some view" ]
-- @
--
onLoadMain :: (FrameLoadEvent -> action) -> EventHandler model action
onLoadMain :: forall action model.
(FrameLoadEvent -> action) -> EventHandler model action
onLoadMain FrameLoadEvent -> action
action = MisoString
-> Decoder FrameLoadEvent
-> (FrameLoadEvent -> model -> DOMRef -> action)
-> EventHandler model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> EventHandler model action
onMain MisoString
"load" Decoder FrameLoadEvent
frameLoadDecoder (\FrameLoadEvent
e model
_ DOMRef
_ -> FrameLoadEvent -> action
action FrameLoadEvent
e)
-----------------------------------------------------------------------------
-- | Like 'onLoadMain', but the handler also receives read-only access to the
-- @model@ and the target element's 'DOMRef' (for imperative MTS mutation).
--
-- @
-- data Action = HandleLoad FrameLoadEvent Model DOMRef
--
-- view_ [ event (static (onLoadMainWith HandleLoad)) ] [ "some view" ]
-- @
--
onLoadMainWith :: (FrameLoadEvent -> model -> DOMRef -> action) -> EventHandler model action
onLoadMainWith :: forall model action.
(FrameLoadEvent -> model -> DOMRef -> action)
-> EventHandler model action
onLoadMainWith FrameLoadEvent -> model -> DOMRef -> action
action = MisoString
-> Decoder FrameLoadEvent
-> (FrameLoadEvent -> model -> DOMRef -> action)
-> EventHandler model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> EventHandler model action
onMain MisoString
"load" Decoder FrameLoadEvent
frameLoadDecoder FrameLoadEvent -> model -> DOMRef -> action
action
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/frame.html#bindloadmetrics
--
-- @
--
-- data Action = HandleMetrics FrameLoadMetricsEvent
--
-- view :: context -> props -> Model -> View context Action
-- view _ _ model = frame_ [ src_ "http://url", onLoadMetrics HandleMetrics ] []
--
-- update :: Action -> Effect props Model Action
-- update (HandleMetrics FrameLoadMetricsEvent {..}) =
--   io_ (consoleLog "frame load metrics event received")
--
-- @
--
onLoadMetrics :: (FrameLoadMetricsEvent -> action) -> Attribute model action
onLoadMetrics :: forall action model.
(FrameLoadMetricsEvent -> action) -> Attribute model action
onLoadMetrics FrameLoadMetricsEvent -> action
action = MisoString
-> Decoder FrameLoadMetricsEvent
-> (FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> Attribute model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> Attribute model action
on MisoString
"loadmetrics" Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder (\FrameLoadMetricsEvent
e model
_ DOMRef
_ -> FrameLoadMetricsEvent -> action
action FrameLoadMetricsEvent
e)
-----------------------------------------------------------------------------
-- | Like 'onLoadMetrics', but dispatched on the Lynx __main thread__ ('MTS').
--
-- Runs imperatively on the MTS (no VDOM diff). Meant to be used with
-- @-XStaticPointers@.
--
-- @
-- data Action = HandleMetrics FrameLoadMetricsEvent
--
-- view_ [ event (static (onLoadMetricsMain HandleMetrics)) ] [ "some view" ]
-- @
--
onLoadMetricsMain :: (FrameLoadMetricsEvent -> action) -> EventHandler model action
onLoadMetricsMain :: forall action model.
(FrameLoadMetricsEvent -> action) -> EventHandler model action
onLoadMetricsMain FrameLoadMetricsEvent -> action
action = MisoString
-> Decoder FrameLoadMetricsEvent
-> (FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> EventHandler model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> EventHandler model action
onMain MisoString
"loadmetrics" Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder (\FrameLoadMetricsEvent
e model
_ DOMRef
_ -> FrameLoadMetricsEvent -> action
action FrameLoadMetricsEvent
e)
-----------------------------------------------------------------------------
-- | Like 'onLoadMetricsMain', but the handler also receives read-only access to
-- the @model@ and the target element's 'DOMRef' (for imperative MTS mutation).
--
-- @
-- data Action = HandleMetrics FrameLoadMetricsEvent Model DOMRef
--
-- view_ [ event (static (onLoadMetricsMainWith HandleMetrics)) ] [ "some view" ]
-- @
--
onLoadMetricsMainWith :: (FrameLoadMetricsEvent -> model -> DOMRef -> action) -> EventHandler model action
onLoadMetricsMainWith :: forall model action.
(FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> EventHandler model action
onLoadMetricsMainWith FrameLoadMetricsEvent -> model -> DOMRef -> action
action = MisoString
-> Decoder FrameLoadMetricsEvent
-> (FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> EventHandler model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> EventHandler model action
onMain MisoString
"loadmetrics" Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder FrameLoadMetricsEvent -> model -> DOMRef -> action
action
-----------------------------------------------------------------------------
-- | Like 'onLoad', but the handler also receives the target element's 'DOMRef'.
-- Use for main-thread ('MTS') handlers that imperatively mutate the element.
onLoadWith :: (FrameLoadEvent -> DOMRef -> action) -> Attribute model action
onLoadWith :: forall action model.
(FrameLoadEvent -> DOMRef -> action) -> Attribute model action
onLoadWith FrameLoadEvent -> DOMRef -> action
action = MisoString
-> Decoder FrameLoadEvent
-> (FrameLoadEvent -> model -> DOMRef -> action)
-> Attribute model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> Attribute model action
on MisoString
"load" Decoder FrameLoadEvent
frameLoadDecoder ((FrameLoadEvent -> model -> DOMRef -> action)
 -> Attribute model action)
-> (FrameLoadEvent -> model -> DOMRef -> action)
-> Attribute model action
forall a b. (a -> b) -> a -> b
$ \FrameLoadEvent
f model
_ DOMRef
domRef -> FrameLoadEvent -> DOMRef -> action
action FrameLoadEvent
f DOMRef
domRef
-----------------------------------------------------------------------------
-- | Like 'onLoadMetrics', but the handler also receives the target element's 'DOMRef'.
-- Use for main-thread ('MTS') handlers that imperatively mutate the element.
onLoadMetricsWith :: (FrameLoadMetricsEvent -> DOMRef -> action) -> Attribute model action
onLoadMetricsWith :: forall action model.
(FrameLoadMetricsEvent -> DOMRef -> action)
-> Attribute model action
onLoadMetricsWith FrameLoadMetricsEvent -> DOMRef -> action
action = MisoString
-> Decoder FrameLoadMetricsEvent
-> (FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> Attribute model action
forall result model action.
MisoString
-> Decoder result
-> (result -> model -> DOMRef -> action)
-> Attribute model action
on MisoString
"loadmetrics" Decoder FrameLoadMetricsEvent
frameLoadMetricsDecoder ((FrameLoadMetricsEvent -> model -> DOMRef -> action)
 -> Attribute model action)
-> (FrameLoadMetricsEvent -> model -> DOMRef -> action)
-> Attribute model action
forall a b. (a -> b) -> a -> b
$ \FrameLoadMetricsEvent
f model
_ DOMRef
domRef -> FrameLoadMetricsEvent -> DOMRef -> action
action FrameLoadMetricsEvent
f DOMRef
domRef
-----------------------------------------------------------------------------