reflex-dom 0.4 → 0.6.3.4
raw patch · 12 files changed
Files
- ChangeLog.md +84/−0
- LICENSE +1/−1
- benchmark.hs +2/−1
- benchmarks/krausest.hs +7/−7
- cbits/MainWidget.c +34/−0
- examples/sortableList.hs +8/−6
- java/org/reflexfrp/reflexdom/MainWidget.java +27/−5
- reflex-dom.cabal +80/−36
- src-android/Reflex/Dom/Android/MainWidget.hsc +20/−2
- src/Reflex/Dom.hs +2/−1
- src/Reflex/Dom/Internal.hs +39/−9
- src/Reflex/Dom/Location/Platform.hs +20/−0
+ ChangeLog.md view
@@ -0,0 +1,84 @@+# Revision history for reflex-dom++## 0.6.3.4++* Fix WASM related issues++## 0.6.3.3++* Support GHC 9.12++## 0.6.3.2-r1++* Require reflex-dom-core >= 0.8.1.0++## 0.6.3.2++* Build with GHC 9.10++## 0.6.3.1-r1++* Require reflex-dom-core >= 0.8.1.0++## 0.6.3.1++* Don't depend on webkit2gtk on android++## 0.6.3.0++* Use android-activity 0.2+* Fix bug in android back button handler++## 0.6.2.0++* [#452](https://github.com/reflex-frp/reflex-dom/pull/452) Allow file access on newer android, following usage recommended by the [official docs](https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader)+* [#453](https://github.com/reflex-frp/reflex-dom/pull/453) History management for android++## 0.6.1.1-r1++* Loosen reflex-dom-core version bounds to allow reflex-dom-core 0.7.*++## 0.6.1.1++* Compile with -fPIC++## 0.6.1.0-r1++* Loosen reflex-dom-core version bounds++## 0.6.1.0++* Update for new dependent-map and dependent-sum (after the "some" package split)++## 0.6.0.0++* ([#379](https://github.com/reflex-frp/reflex-dom/pull/379)) Re-export all modules from `reflex-dom-core`. The newly re-exported modules are:+ * `Foreign.JavaScript.Utils`+ * `Reflex.Dom.Builder.Hydratable`+ * `Reflex.Dom.Modals.Class`+ * `Reflex.Dom.Prerender`+ * `Reflex.Dom.Time`+ * `Reflex.Dom.WebSocket.Query`+ * `Reflex.Dom.Xhr.FormData`+* ([#366](https://github.com/reflex-frp/reflex-dom/pull/366)) Bump bounds for `reflex` to include 0.7.++## 0.5.3++* On Android, enable prompting the user for geolocation+ permissions on demand by default. See+ https://developer.android.com/reference/android/webkit/WebChromeClient.html#onGeolocationPermissionsShowPrompt(java.lang.String,%20android.webkit.GeolocationPermissions.Callback)+ for details.++ * Add `< 0.7` upper bound for reflex++## 0.5.2++* The default jsaddle backend on macOS when built from nix+ is now jsaddle-wkwebview, matching the behaviour of cabal+ builds.++## 0.5++* Re-export new hydration widget "mainWidget" functions.++* The use-warp flag now properly takes precedence on macOS.
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2015, Obsidian Systems LLC+Copyright (c) 2020, Obsidian Systems LLC All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
benchmark.hs view
@@ -15,8 +15,9 @@ import Reflex.Dom import System.Random import qualified Data.Map as Map-import Data.Dependent.Map (DMap (..), DSum (..))+import Data.Dependent.Map (DMap (..)) import qualified Data.Dependent.Map as DMap+import Data.Dependent.Sum (DSum (..)) import Data.Functor.Misc import Data.Functor.Identity import Data.Functor.Compose
benchmarks/krausest.hs view
@@ -28,15 +28,15 @@ seed <- randomIO mainWidgetWithHead' (\_ -> headW, \_ -> bodyW seed) -titleW :: MonadWidget t m => m ()+titleW :: DomBuilder t m => m () titleW = text "Reflex-dom keyed" -headW :: MonadWidget t m => m ()+headW :: DomBuilder t m => m () headW = do el "title" titleW elAttr "link" ("href" =: "/css/currentStyle.css" <> "rel" =: "stylesheet") blank -bodyW :: forall t m. MonadWidget t m => Entropy -> m ()+bodyW :: forall t m. (MonadFix m, MonadHold t m, DomBuilder t m) => Entropy -> m () bodyW seed = divClass "main" $ divClass "container" $ mdo buttonEvents <- divClass "jumbotron" $ divClass "row" $ do divClass "col-md-6" $ el "h1" titleW@@ -75,14 +75,14 @@ (m', dt) = f (m, t) t' = applyAlways dt t -buttonW :: MonadWidget t m => Text -> Text -> a -> m (Event t a)+buttonW :: DomBuilder t m => Text -> Text -> a -> m (Event t a) buttonW id txt val = divClass "col-sm-6 smallpad" $ buttonW' ("class" =: "btn btn-primary btn-block" <> "id" =: id) where buttonW' attrs = do (b, _) <- elAttr' "button" attrs $ text txt pure $ val <$ domEvent Click b -tableW :: MonadWidget t m => Event t TableDiff -> m (Event t (IntMap Step))+tableW :: (MonadHold t m, DomBuilder t m) => Event t TableDiff -> m (Event t (IntMap Step)) tableW diff = do elClass "table" "table table-hover table-striped test-data" $ do el "tbody" $ do@@ -90,7 +90,7 @@ rowEvents <- holdIncremental v0 v' return $ mergeIntIncremental rowEvents -rowW :: MonadWidget t m => Row -> m (Event t Step)+rowW :: DomBuilder t m => Row -> m (Event t Step) rowW row = elClass "tr" (if selected row then "danger" else "") $ do elClass "td" "col-md-1" $ do@@ -102,7 +102,7 @@ where tagClick f el = f row <$ (domEvent Click el) -deleteW :: MonadWidget t m => m ()+deleteW :: DomBuilder t m => m () deleteW = el "a" $ elAttr "span" ("aria-hidden" =: "true" <> "class" =: "glyphicon glyphicon-remove") blank
cbits/MainWidget.c view
@@ -53,6 +53,40 @@ (*env)->PopLocalFrame(env, 0); } +void Reflex_Dom_Android_MainWidget_back(jobject jsExecutor) {+ JNIEnv *env;+ jint attachResult = (*HaskellActivity_jvm)->AttachCurrentThread(HaskellActivity_jvm, &env, NULL);+ assert (attachResult == JNI_OK);++ (*env)->PushLocalFrame(env, 5);++ //TODO: Don't search for this method every time+ jclass cls = (*env)->GetObjectClass(env, jsExecutor);+ assert(cls);+ jmethodID evaluateJavascript = (*env)->GetMethodID(env, cls, "goBack", "()V");+ assert(evaluateJavascript);+ (*env)->CallVoidMethod(env, jsExecutor, evaluateJavascript);++ (*env)->PopLocalFrame(env, 0);+}++void Reflex_Dom_Android_MainWidget_clearHistory(jobject jsExecutor) {+ JNIEnv *env;+ jint attachResult = (*HaskellActivity_jvm)->AttachCurrentThread(HaskellActivity_jvm, &env, NULL);+ assert (attachResult == JNI_OK);++ (*env)->PushLocalFrame(env, 5);++ //TODO: Don't search for this method every time+ jclass cls = (*env)->GetObjectClass(env, jsExecutor);+ assert(cls);+ jmethodID evaluateJavascript = (*env)->GetMethodID(env, cls, "clearHistory", "()V");+ assert(evaluateJavascript);+ (*env)->CallVoidMethod(env, jsExecutor, evaluateJavascript);++ (*env)->PopLocalFrame(env, 0);+}+ JNIEXPORT void JNICALL Java_org_reflexfrp_reflexdom_MainWidget_00024JSaddleCallbacks_startProcessing (JNIEnv *env, jobject thisObj, jlong callbacksLong) { const JSaddleCallbacks *callbacks = (const JSaddleCallbacks *)callbacksLong; (*(callbacks->jsaddleStart))();
examples/sortableList.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-}@@ -5,21 +6,22 @@ {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE ScopedTypeVariables #-} import Control.Lens-import Control.Monad.Identity+import Control.Monad.Fix import Control.Monad.IO.Class-import Data.Dependent.Map (DMap)-import Data.Functor.Constant-import Data.Functor.Misc import Data.List import Data.Map (Map) import qualified Data.Map as Map-import Data.Monoid import Data.Ord+import Data.Patch.MapWithMove import qualified Data.Text as T import Data.Time.Clock import Reflex.Dom import System.Random +#if defined(wasm32_HOST_ARCH)+foreign export javascript "hs_start" main :: IO ()+#endif+ main :: IO () main = mainWidget $ do let f _ (a, b, c) = el "tr" $ do@@ -71,7 +73,7 @@ simpleSortableList f m0 resortFunc resortSlowFunc = do rec let resortPatchFast = attachWith (flip patchThatSortsMapWith) (currentIncremental m) resortFunc redrawPatch :: Map k v -> (v -> v -> Ordering) -> PatchMapWithMove k v- redrawPatch d cmp = unsafePatchMapWithMove $ fmap (MapEdit_Insert False) $ Map.fromList $ zip (Map.keys d) (sortBy cmp $ Map.elems d)+ redrawPatch d cmp = patchMapWithMoveInsertAll $ Map.fromList $ zip (Map.keys d) (sortBy cmp $ Map.elems d) resortPatchSlow = attachWith redrawPatch (currentIncremental m) resortSlowFunc resortPatch = leftmost [ resortPatchFast
java/org/reflexfrp/reflexdom/MainWidget.java view
@@ -8,6 +8,7 @@ import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.webkit.CookieManager;+import android.webkit.GeolocationPermissions; import android.webkit.JavascriptInterface; import android.webkit.MimeTypeMap; import android.webkit.PermissionRequest;@@ -22,6 +23,7 @@ import java.io.InputStream; import android.content.Intent; import android.content.ActivityNotFoundException;+import java.util.concurrent.atomic.AtomicBoolean; import java.nio.charset.StandardCharsets; @@ -39,24 +41,29 @@ a.setContentView(wv); final WebSettings ws = wv.getSettings(); ws.setJavaScriptEnabled(true);- ws.setAllowFileAccessFromFileURLs(true);- ws.setAllowUniversalAccessFromFileURLs(true); ws.setDomStorageEnabled(true); wv.setWebContentsDebuggingEnabled(true); // allow video to play without user interaction wv.getSettings().setMediaPlaybackRequiresUserGesture(false);+ final AtomicBoolean jsaddleLoaded = new AtomicBoolean(false); wv.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView _view, String _url) {- wv.evaluateJavascript(initialJS, null);+ Log.i("reflex", "onPageFinished");+ boolean alreadyLoaded = jsaddleLoaded.getAndSet(true);+ if(!alreadyLoaded) {+ Log.i("reflex", "loading jsaddle");+ wv.evaluateJavascript(initialJS, null);+ } } // Re-route / to /android_asset @Override public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) { Uri uri = request.getUrl();- if(!uri.getScheme().equals("file"))+ Log.i("reflex", uri.toString());+ if(!uri.getScheme().equals("file") && !uri.getEncodedAuthority().equals("appassets.androidplatform.net")) return null; String path = uri.getPath();@@ -79,7 +86,7 @@ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {- if( url != null && !url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("file://")) {+ if( url != null && !url.startsWith("http://appassets.androidplatform.net") && !url.startsWith("https://appassets.androidplatform.net") && !url.startsWith("file://")) { try { view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); }@@ -115,6 +122,11 @@ public Bitmap getDefaultVideoPoster() { return Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); }++ @Override+ public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {+ callback.invoke(origin, true, false);+ } }); wv.addJavascriptInterface(new JSaddleCallbacks(jsaddleCallbacks), "jsaddle");@@ -131,6 +143,16 @@ wv.evaluateJavascript(jsStr, null); } });+ }+ public final void goBack() {+ hnd.post(new Runnable() {+ @Override+ public void run() {+ if(wv.canGoBack()) {+ wv.goBack();+ }+ }+ }); } }; }
reflex-dom.cabal view
@@ -1,10 +1,20 @@+cabal-version: 1.24 Name: reflex-dom-Version: 0.4+Version: 0.6.3.4 Synopsis: Functional Reactive Web Apps with Reflex Description:- Reflex-DOM is a Functional Reactive web framework based on the Reflex FRP engine.+ Web applications without callbacks or side-effects.+ Reflex-DOM brings the power of functional reactive programming (FRP) to the web.+ Build HTML and other Document Object Model (DOM) data with a pure functional interface. .- For hackage documentation, please see: <https://hackage.haskell.org/package/reflex-dom-core>.+ Reflex-DOM is a Functional Reactive web framework based on the Reflex FRP engine: <https://reflex-frp.org/>.+ .+ The @reflex-dom@ package is a small wrapper around the @reflex-dom-core@ package. It pulls in the+ correct set of dependencies for each target platform (GHCJS, WebKitGTK, WASM, mobile, etc.).+ Libraries should depend on @reflex-dom-core@ and executables will usually depend on @reflex-dom@.+ All of @reflex-dom-core@'s modules are re-exported by @reflex-dom@.+ .+ For Hackage documentation, please see: <https://hackage.haskell.org/package/reflex-dom-core>. License: BSD3 License-file: LICENSE Author: Ryan Trinkle@@ -12,8 +22,9 @@ Stability: Experimental Category: FRP, Web, GUI, HTML, Javascript, Reactive, Reactivity, User Interfaces, User-interface Build-type: Simple-cabal-version: >=1.24-extra-source-files: java/org/reflexfrp/reflexdom/MainWidget.java+extra-source-files:+ java/org/reflexfrp/reflexdom/MainWidget.java+ ChangeLog.md flag use-warp description: Use jsaddle-warp server@@ -39,60 +50,59 @@ default: False manual: True -flag android- description: Build an Android app- default: False- manual: True- library hs-source-dirs: src- if flag(android)+ if os(android) hs-source-dirs: src-android other-modules: Reflex.Dom.Android.MainWidget build-depends:- aeson,- android-activity == 0.1.*,- data-default == 0.7.*,- jsaddle+ aeson >= 1.4 && < 2.3,+ android-activity == 0.2.*,+ data-default >= 0.7 && < 0.9,+ jsaddle >= 0.9.6 && < 0.10 c-sources: cbits/MainWidget.c include-dirs: cbits/include install-includes: MainWidget.h cpp-options: -DANDROID build-tools: hsc2hs build-depends:- base >= 4.7 && < 4.12,- bytestring == 0.10.*,- reflex == 0.5.*,- reflex-dom-core >=0.4 && <0.5,- text == 1.2.*+ base >= 4.7 && < 4.22,+ bytestring >= 0.10 && < 0.13,+ reflex >= 0.8 && < 1,+ reflex-dom-core >= 0.8.1.0 && <0.9,+ text >= 1.2 && < 2.2 if !impl(ghcjs)- if os(osx) || os(ios)+ if flag(use-warp) build-depends:- data-default == 0.7.*,- jsaddle,- jsaddle-wkwebview+ jsaddle >= 0.9.6 && < 0.10,+ jsaddle-warp >= 0.9.6 && < 0.10 else- if flag(use-warp)+ if os(osx) || os(ios) build-depends:- jsaddle,- jsaddle-warp+ data-default >= 0.7 && < 0.9,+ jsaddle >= 0.9.6 && < 0.10,+ jsaddle-wkwebview >= 0.9.6 && < 0.10 else- if flag(webkit2gtk)+ if arch(wasm32) build-depends:- jsaddle-webkit2gtk+ jsaddle >= 0.9.6 && < 0.10,+ jsaddle-wasm >= 0.1 && < 0.2 else- if !flag(android)+ if flag(webkit2gtk) && !os(android) build-depends:- jsaddle-webkit2gtk+ jsaddle-webkit2gtk >= 0.9.6 && < 0.10 exposed-modules: Reflex.Dom Reflex.Dom.Internal+ Reflex.Dom.Location.Platform reexported-modules:- Foreign.JavaScript.TH- , Foreign.JavaScript.Orphans+ Foreign.JavaScript.Orphans+ , Foreign.JavaScript.TH+ , Foreign.JavaScript.Utils , Reflex.Dom.Builder.Class , Reflex.Dom.Builder.Class.Events+ , Reflex.Dom.Builder.Hydratable , Reflex.Dom.Builder.Immediate , Reflex.Dom.Builder.InputDisabled , Reflex.Dom.Builder.Static@@ -100,15 +110,21 @@ , Reflex.Dom.Core , Reflex.Dom.Location , Reflex.Dom.Main+ , Reflex.Dom.Modals.Class , Reflex.Dom.Old+ , Reflex.Dom.Prerender+ , Reflex.Dom.Time , Reflex.Dom.WebSocket+ , Reflex.Dom.WebSocket.Query , Reflex.Dom.Widget , Reflex.Dom.Widget.Basic , Reflex.Dom.Widget.Input , Reflex.Dom.Widget.Lazy , Reflex.Dom.Widget.Resize , Reflex.Dom.Xhr- ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans+ , Reflex.Dom.Xhr.FormData+ ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans -fPIC+ cc-options: -fPIC if flag(expose-all-unfoldings) ghc-options: -fexpose-all-unfoldings if flag(use-reflex-optimizer)@@ -121,6 +137,7 @@ , dependent-map , lens , mtl+ , patch , random , reflex , reflex-dom@@ -137,9 +154,23 @@ if flag(use-reflex-optimizer) ghc-options: -fplugin=Reflex.Optimizer default-language: Haskell2010+ if arch(wasm32)+ ghc-options: -no-hs-main -optl-mexec-model=reactor "-optl-Wl,--export=hs_start" executable benchmark- build-depends: base, reflex, reflex-dom, text, prim-uniq, dependent-map, containers, transformers, mtl, ghcjs-dom, ghc-prim, random, dependent-sum+ build-depends: base+ , containers+ , dependent-map+ , dependent-sum+ , ghc-prim+ , ghcjs-dom+ , mtl+ , prim-uniq+ , random+ , reflex+ , reflex-dom+ , text+ , transformers hs-source-dirs: . main-is: benchmark.hs ghc-options: -O2 -fspecialise-aggressively@@ -148,7 +179,20 @@ default-language: Haskell2010 executable krausest- build-depends: base, reflex, reflex-dom, text, prim-uniq, dependent-map, containers, transformers, mtl, ghcjs-dom, ghc-prim, random, dependent-sum, vector+ build-depends: base+ , containers+ , dependent-map+ , dependent-sum+ , ghc-prim+ , ghcjs-dom+ , mtl+ , prim-uniq+ , random+ , reflex+ , reflex-dom+ , text+ , transformers+ , vector hs-source-dirs: benchmarks main-is: krausest.hs ghc-options: -O2 -fspecialise-aggressively
src-android/Reflex/Dom/Android/MainWidget.hsc view
@@ -2,11 +2,15 @@ {-# LANGUAGE OverloadedStrings #-} module Reflex.Dom.Android.MainWidget ( startMainWidget+ , goBack+ , JSExecutor(..)+ , withGlobalJSExecutor ) where import Android.HaskellActivity import Control.Concurrent import Control.Monad+import Control.Monad.IO.Class import Data.Aeson import Data.ByteString (ByteString) import qualified Data.ByteString as BS@@ -23,10 +27,10 @@ import Language.Javascript.JSaddle (JSM) import Language.Javascript.JSaddle.Run (runJavaScript) import Language.Javascript.JSaddle.Run.Files (initState, runBatch, ghcjsHelpers)+import System.IO.Unsafe #include "MainWidget.h" - startMainWidget :: HaskellActivity -> ByteString -> JSM () -> IO () startMainWidget a url jsm = do --TODO: Find a way to eventually release this@@ -57,13 +61,27 @@ \jsaddle.postReady();\n" } BS.useAsCString url $ \curl -> do- writeIORef executorRef =<< startMainWidget_ a curl callbacks+ executor <- startMainWidget_ a curl callbacks+ writeIORef executorRef executor+ writeIORef globalJSExecutor $ Just executor newtype JSExecutor = JSExecutor { unJSExecutor :: Ptr JSExecutor } +-- Ugh. But not doing this is also unfortunate for being able to clear the history so that the "back" list is good.+globalJSExecutor :: IORef (Maybe JSExecutor)+globalJSExecutor = unsafePerformIO $ newIORef Nothing++withGlobalJSExecutor :: MonadIO m => (JSExecutor -> IO ()) -> m ()+withGlobalJSExecutor f = liftIO $ do+ executor <- readIORef globalJSExecutor+ case executor of+ Just e -> f e+ _ -> pure ()+ foreign import ccall safe "Reflex_Dom_Android_MainWidget_start" startMainWidget_ :: HaskellActivity -> CString -> Ptr JSaddleCallbacksPtrs -> IO JSExecutor foreign import ccall safe "Reflex_Dom_Android_MainWidget_runJS" runJS :: JSExecutor -> CString -> CSize -> IO ()+foreign import ccall safe "Reflex_Dom_Android_MainWidget_back" goBack :: JSExecutor -> IO () data JSaddleCallbacks = JSaddleCallbacks { _jsaddleCallbacks_jsaddleStart :: IO ()
src/Reflex/Dom.hs view
@@ -6,5 +6,6 @@ import Foreign.JavaScript.Orphans () import Reflex.Dom.Core as X hiding (mainWidget, mainWidgetInElementById, mainWidgetWithCss,- mainWidgetWithHead, mainWidgetWithHead', runApp')+ mainWidgetWithHead, mainWidgetWithHead', runApp',+ mainHydrationWidgetWithHead, mainHydrationWidgetWithHead') import Reflex.Dom.Internal as X
src/Reflex/Dom/Internal.hs view
@@ -4,25 +4,28 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} module Reflex.Dom.Internal- (module Main, run, mainWidget, mainWidgetWithHead, mainWidgetWithCss,- mainWidgetWithHead', mainWidgetInElementById, runApp') where+ ( module Main+ , run+ , mainWidget+ , mainWidgetWithHead, mainWidgetWithCss, mainWidgetWithHead', mainWidgetInElementById, runApp'+ , mainHydrationWidgetWithHead, mainHydrationWidgetWithHead'+ ) where import Data.ByteString (ByteString) import Data.Text (Text)-import Reflex.Dom.Core (Widget) import Reflex.Dom.Main as Main hiding (mainWidget, mainWidgetWithHead, mainWidgetWithCss,- mainWidgetWithHead', mainWidgetInElementById, runApp')+ mainWidgetWithHead', mainWidgetInElementById, runApp',+ mainHydrationWidgetWithHead, mainHydrationWidgetWithHead') import qualified Reflex.Dom.Main as Main (mainWidget, mainWidgetWithHead, mainWidgetWithCss,- mainWidgetWithHead', mainWidgetInElementById, runApp')+ mainWidgetWithHead', mainWidgetInElementById, runApp',+ mainHydrationWidgetWithHead, mainHydrationWidgetWithHead') #if defined(ghcjs_HOST_OS) run :: a -> a run = id #elif defined(MIN_VERSION_jsaddle_warp)-import Data.Maybe (maybe)-import Data.Monoid ((<>)) import Language.Javascript.JSaddle (JSM) import qualified Language.Javascript.JSaddle.Warp as JW import System.Environment (lookupEnv)@@ -32,6 +35,7 @@ port <- maybe 3003 read <$> lookupEnv "JSADDLE_WARP_PORT" putStrLn $ "Running jsaddle-warp server on port " <> show port JW.run port jsm+ #elif defined(MIN_VERSION_jsaddle_wkwebview) #if defined(ios_HOST_OS) import Data.Default@@ -50,18 +54,24 @@ return "" Just p -> return $ "file://" <> p <> "/index.html" run' def $ jsaddleMainHTMLWithBaseURL indexHtml baseUrl jsm+ #else import Language.Javascript.JSaddle.WKWebView (run) #endif #elif defined(ANDROID) import Android.HaskellActivity import Control.Monad+import Control.Monad.IO.Class (liftIO, MonadIO) import Control.Concurrent+import Language.Javascript.JSaddle (JSM) import Data.Default+import Data.IORef+import Data.Maybe import Data.String import Reflex.Dom.Android.MainWidget import System.IO-import Language.Javascript.JSaddle (JSM)+import System.IO.Unsafe+import Language.Javascript.JSaddle (JSM, eval) run :: JSM () -> IO () run jsm = do@@ -70,12 +80,24 @@ continueWithCallbacks $ def { _activityCallbacks_onCreate = \_ -> do a <- getHaskellActivity- let startPage = fromString "file:///android_asset/index.html"+ let startPage = fromString "https://appassets.androidplatform.net/index.html" startMainWidget a startPage jsm+ , _activityCallbacks_onBackPressed = triggerBackButton } forever $ threadDelay 1000000000++triggerBackButton :: MonadIO m => m ()+triggerBackButton = withGlobalJSExecutor goBack++#elif defined(wasm32_HOST_ARCH)+import qualified Language.Javascript.JSaddle.Wasm as Wasm (run)+import Language.Javascript.JSaddle (JSM)+run :: JSM () -> IO ()+run = Wasm.run+ #else import Language.Javascript.JSaddle.WebKitGTK (run)+ #endif mainWidget :: (forall x. Widget x ()) -> IO ()@@ -101,3 +123,11 @@ runApp' :: (forall x. AppInput DomTimeline -> Widget x (AppOutput DomTimeline)) -> IO () runApp' app = run $ Main.runApp' app {-# INLINE runApp' #-}++mainHydrationWidgetWithHead :: (forall x. HydrationWidget x ()) -> (forall x. HydrationWidget x ()) -> IO ()+mainHydrationWidgetWithHead h b = run $ Main.mainHydrationWidgetWithHead h b+{-# INLINE mainHydrationWidgetWithHead #-}++mainHydrationWidgetWithHead' :: HydrationWidget () () -> HydrationWidget () () -> IO ()+mainHydrationWidgetWithHead' h b = run $ Main.mainHydrationWidgetWithHead' h b+{-# INLINE mainHydrationWidgetWithHead' #-}
+ src/Reflex/Dom/Location/Platform.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+#if defined(ANDROID)+module Reflex.Dom.Location.Platform where++import Reflex+import Control.Monad.IO.Class+import Reflex.Dom.Android.MainWidget++popHistoryState+ :: (PerformEvent t m, MonadIO (Performable m))+ => Event t ()+ -> m ()+popHistoryState evt = performEvent_ $ withGlobalJSExecutor goBack <$ evt+#else+module Reflex.Dom.Location.Platform (Reflex.Dom.Location.popHistoryState) where+import qualified Reflex.Dom.Location++#endif+