miso 0.17.0.0 → 0.18.0.0
raw patch · 10 files changed
+127/−29 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- examples/mario/Main.hs +5/−2
- ghcjs-src/Miso.hs +10/−0
- ghcjs-src/Miso/FFI.hs +24/−0
- ghcjs-src/Miso/Html/Internal.hs +15/−13
- ghcjs-src/Miso/Subscription/History.hs +11/−8
- ghcjs-src/Miso/Subscription/Window.hs +32/−4
- ghcjs-src/Miso/Types.hs +2/−0
- jsbits/delegate.js +26/−0
- jsbits/diff.js +1/−1
- miso.cabal +1/−1
examples/mario/Main.hs view
@@ -25,13 +25,16 @@ main = do time <- now let m = mario { time = time }- startApp App { model = m, initialAction = NoOp, ..}+ startApp App { model = m+ , initialAction = NoOp+ , ..+ } where update = updateMario view = display events = defaultEvents subs = [ arrowsSub GetArrows- , windowSub WindowCoords+ , windowCoordsSub WindowCoords ] mountPoint = Nothing
ghcjs-src/Miso.hs view
@@ -87,10 +87,12 @@ (Acc oldModel (pure ())) actions effects when (oldModel /= newModel) $ do+ swapCallbacks newVTree <- runView (view newModel) writeEvent oldVTree <- readIORef viewRef void $ waitForAnimationFrame (diff mountPoint) (Just oldVTree) (Just newVTree)+ releaseCallbacks atomicWriteIORef viewRef newVTree loop newModel loop m@@ -137,3 +139,11 @@ -- entry point into isomorphic javascript foreign import javascript unsafe "copyDOMIntoVTree($1);" copyDOMIntoVTree :: JSVal -> IO ()++-- | Pins down the current callbacks for clearing later+foreign import javascript unsafe "swapCallbacks();"+ swapCallbacks :: IO ()++-- | Releases callbacks registered by the virtual DOM.+foreign import javascript unsafe "releaseCallbacks();"+ releaseCallbacks :: IO ()
ghcjs-src/Miso/FFI.hs view
@@ -16,6 +16,8 @@ , windowRemoveEventListener , windowInnerHeight , windowInnerWidth+ , eventPreventDefault+ , eventStopPropagation , now , consoleLog , stringify@@ -23,6 +25,8 @@ , item , jsvalToValue , clearBody+ , objectToJSON+ , getWindow ) where import Control.Monad@@ -79,6 +83,19 @@ foreign import javascript unsafe "window.removeEventListener($1, $2);" windowRemoveEventListener :: JSString -> Callback (JSVal -> IO ()) -> IO () ++foreign import javascript unsafe "$1.stopPropagation();"+ eventStopPropagation :: JSVal -> IO ()++foreign import javascript unsafe "$1.preventDefault();"+ eventPreventDefault :: JSVal -> IO ()+++-- | Window object+foreign import javascript unsafe "$r = window;"+ getWindow :: IO JSVal++ -- | Retrieves inner height foreign import javascript unsafe "$r = window.innerHeight;" windowInnerHeight :: IO Int@@ -125,3 +142,10 @@ -- creating multiple copies of your app when running in GHCJSi. foreign import javascript unsafe "document.body.innerHTML = '';" clearBody :: IO ()+++foreign import javascript unsafe "$r = objectToJSON($1,$2);"+ objectToJSON+ :: JSVal -- ^ decodeAt :: [JSString]+ -> JSVal -- ^ object with impure references to the DOM+ -> IO JSVal
ghcjs-src/Miso/Html/Internal.hs view
@@ -223,12 +223,6 @@ -> Attribute action on = onWithOptions defaultOptions -foreign import javascript unsafe "$r = objectToJSON($1,$2);"- objectToJSON- :: JSVal -- ^ decodeAt :: [JSString]- -> JSVal -- ^ object with impure references to the DOM- -> IO JSVal- -- | @onWithOptions opts eventName decoder toAction@ is an attribute -- that will set the event handler of the associated DOM node to a function that -- decodes its argument using @decoder@, converts it to an action@@ -251,12 +245,13 @@ eventHandlerObject@(Object eo) <- create jsOptions <- toJSVal options decodeAtVal <- toJSVal decodeAt- cb <- jsval <$> (asyncCallback1 $ \e -> do+ cb <- asyncCallback1 $ \e -> do Just v <- jsvalToValue =<< objectToJSON decodeAtVal e case parseEither decoder v of Left s -> error $ "Parse error on " <> unpack eventName <> ": " <> s- Right r -> sink (toAction r))- setProp "runEvent" cb eventHandlerObject+ Right r -> sink (toAction r)+ setProp "runEvent" (jsval cb) eventHandlerObject+ registerCallback cb setProp "options" jsOptions eventHandlerObject setProp eventName eo (Object eventObj) @@ -265,8 +260,9 @@ onCreated :: action -> Attribute action onCreated action = Attribute $ \sink n -> do- cb <- jsval <$> asyncCallback (sink action)- setProp "onCreated" cb n+ cb <- asyncCallback (sink action)+ setProp "onCreated" (jsval cb) n+ registerCallback cb -- | @onDestroyed action@ is an event that gets called after the DOM element -- is removed from the DOM. The @action@ is given the DOM element that was@@ -274,8 +270,9 @@ onDestroyed :: action -> Attribute action onDestroyed action = Attribute $ \sink n -> do- cb <- jsval <$> asyncCallback (sink action)- setProp "onDestroyed" cb n+ cb <- asyncCallback (sink action)+ setProp "onDestroyed" (jsval cb) n+ registerCallback cb -- | @style_ attrs@ is an attribute that will set the @style@ -- attribute of the associated DOM node to @attrs@.@@ -292,3 +289,8 @@ cssObj <- getProp "css" n forM_ (M.toList m) $ \(k,v) -> setProp k (jsval v) (Object cssObj)++foreign import javascript unsafe "registerCallback($1);"+ registerCallback+ :: Callback a+ -> IO ()
ghcjs-src/Miso/Subscription/History.hs view
@@ -49,18 +49,21 @@ -- | Pushes a new URI onto the History stack pushURI :: URI -> IO () {-# INLINE pushURI #-}-pushURI uri = pushStateNoModel uri { uriPath = path }- where- path | uriPath uri == mempty = "/"- | otherwise = uriPath uri+pushURI uri = pushStateNoModel uri { uriPath = toPath uri } +-- | Prepend '/' if necessary+toPath :: URI -> String+toPath uri =+ case uriPath uri of+ "" -> "/"+ "/" -> "/"+ xs@('/' : _) -> xs+ xs -> '/' : xs+ -- | Replaces current URI on stack replaceURI :: URI -> IO () {-# INLINE replaceURI #-}-replaceURI uri = replaceTo' uri { uriPath = path }- where- path | uriPath uri == mempty = "/"- | otherwise = uriPath uri+replaceURI uri = replaceTo' uri { uriPath = toPath uri } -- | Navigates backwards back :: IO ()
ghcjs-src/Miso/Subscription/Window.hs view
@@ -11,18 +11,28 @@ ---------------------------------------------------------------------------- module Miso.Subscription.Window where +import Control.Monad+import Data.Monoid+ import GHCJS.Foreign.Callback import GHCJS.Marshal- import JavaScript.Object import JavaScript.Object.Internal++import Miso.Event import Miso.FFI-import Miso.Html.Internal ( Sub )+import Miso.Html.Internal ( Sub )+import Miso.String +import Miso.String+import Miso.Event++import Data.Aeson.Types (parseEither)+ -- | Captures window coordinates changes as they occur and writes them to -- an event sink-windowSub :: ((Int, Int) -> action) -> Sub action-windowSub f = \sink -> do+windowCoordsSub :: ((Int, Int) -> action) -> Sub action+windowCoordsSub f = \sink -> do sink . f =<< (,) <$> windowInnerHeight <*> windowInnerWidth windowAddEventListener "resize" =<< do asyncCallback1 $ \windowEvent -> do@@ -30,3 +40,21 @@ Just w <- fromJSVal =<< getProp "innerWidth" (Object target) Just h <- fromJSVal =<< getProp "innerHeight" (Object target) sink $ f (h, w)++-- | @windowOn eventName decoder toAction@ is a subscription which parallels the+-- attribute handler `on`, providing a subscription to listen to window level events.+windowSub :: MisoString -> Decoder r -> (r -> action) -> Sub action+windowSub = windowSubWithOptions defaultOptions++windowSubWithOptions :: Options -> MisoString -> Decoder r -> (r -> action) -> Sub action+windowSubWithOptions Options{..} eventName Decoder{..} toAction = \sink -> do+ windowAddEventListener eventName =<< do+ decodeAtVal <- toJSVal decodeAt+ asyncCallback1 $ \e -> do+ Just v <- jsvalToValue =<< objectToJSON decodeAtVal e+ case parseEither decoder v of+ Left s -> error $ "Parse error on " <> unpack eventName <> ": " <> s+ Right r -> do+ when stopPropagation $ eventStopPropagation e+ when preventDefault $ eventPreventDefault e+ sink (toAction r)
ghcjs-src/Miso/Types.hs view
@@ -9,6 +9,8 @@ ---------------------------------------------------------------------------- module Miso.Types ( App (..)+ , Effect+ , Sub -- * The Transition Monad , Transition
jsbits/delegate.js view
@@ -1,3 +1,29 @@+var oldCallbacks = [];+var currentCallbacks = [];++/* Callbacks in ghcjs need to be released. With this function one can register+ callbacks that should be released right before diffing.+*/+function registerCallback(cb) {+ currentCallbacks.push(cb);+}++/* Swaps out the new calbacks for old callbacks.+The old callbacks should be cleared once the new callbacks have replaced them.+*/+function swapCallbacks() {+ oldCallbacks = currentCallbacks;+ currentCallbacks = [];+}++/* This releases the old callbacks. */+function releaseCallbacks() {+ for (var i in oldCallbacks)+ h$release(oldCallbacks[i]);++ oldCallbacks = [];+}+ /* event delegation algorithm */ function delegate(mountPointElement, events, getVTree) { for (var event in events) {
jsbits/diff.js view
@@ -172,7 +172,7 @@ newFirstIndex = 0, oldLastIndex = os.length - 1, newLastIndex = ns.length - 1,- nFirst, nLast, tmp, found, node;+ nFirst, nLast, oLast, oFirst, tmp, found, node; for (;;) { /* check base case, first > last for both new and old [ ] -- old children empty (fully-swapped)
miso.cabal view
@@ -1,5 +1,5 @@ name: miso-version: 0.17.0.0+version: 0.18.0.0 category: Web, Miso, Data Structures license: BSD3 license-file: LICENSE