@@ -1,11 +1,15 @@
11module Language.Javascript.JSaddle.WKWebView
22 ( jsaddleMain
3+ , jsaddleMainHTMLWithBaseURL
34 , jsaddleMainFile
45 , WKWebView(..)
56 , run
7+ , run'
68 , runWithAppConfig
9+ , runHTMLWithBaseURL
710 , runFile
811 , mainBundleResourcePath
12+ , ApplicationState (..)
913 , AppDelegateConfig (..)
1014 , AppDelegateNotificationConfig (..)
1115 , AuthorizationOption (..)
@@ -17,9 +21,11 @@ import Data.Set (Set)
1721import qualified Data.Set as Set
1822import Data.Word
1923import Foreign.Marshal.Utils (fromBool)
20−import Language.Javascript.JSaddle.WKWebView.Internal (jsaddleMain, jsaddleMainFile, WKWebView(..), mainBundleResourcePath)
24+import Language.Javascript.JSaddle.WKWebView.Internal
25+ (jsaddleMain, jsaddleMainHTMLWithBaseURL, jsaddleMainFile, WKWebView(..), mainBundleResourcePath)
2126import System.Environment (getProgName)
2227import Foreign.C.String (CString, withCString)
28+import Foreign.C.Types (CBool, CInt)
2329import Foreign.StablePtr (StablePtr, newStablePtr)
2430import Language.Javascript.JSaddle (JSM)
2531
@@ -35,6 +41,7 @@ foreign import ccall runInWKWebView
3541 -> StablePtr (IO ()) -- applicationWillTerminate
3642 -> StablePtr (IO ()) -- applicationSignificantTimeChange
3743 -> StablePtr (CString -> IO ()) -- applicationUniversalLink
44+ -> StablePtr (CInt -> CString -> IO ()) -- applicationDidReceiveRemoteNotification
3845 -> Word64 -- whether to run requestAuthorizationWithOptions
3946 -> Word64 -- Ask for Badge authorization
4047 -> Word64 -- Ask for Sound authorization
@@ -43,6 +50,8 @@ foreign import ccall runInWKWebView
4350 -> Word64 -- registerForRemoteNotifications
4451 -> StablePtr (CString -> IO ()) -- didRegisterForRemoteNotificationsWithDeviceToken
4552 -> StablePtr (CString -> IO ()) -- didFailToRegisterForRemoteNotificationsWithError
53+ -> Word64 -- developerExtrasEnabled
54+ -> StablePtr (CString -> IO CBool) -- applicationOpenFile
4655 -> IO ()
4756
4857data AppDelegateConfig = AppDelegateConfig
@@ -55,7 +64,25 @@ data AppDelegateConfig = AppDelegateConfig
5564 , _appDelegateConfig_applicationWillTerminate :: IO ()
5665 , _appDelegateConfig_applicationSignificantTimeChange :: IO ()
5766 , _appDelegateConfig_applicationUniversalLink :: CString -> IO ()
67+ -- ^ Called when the app is launched from a URL. 'CString' contains the URL.
68+ --
69+ -- The Core Foundation plist key CFBundleURLTypes controls which URL schemes
70+ -- the app should respond to.
71+ , _appDelegateConfig_applicationDidReceiveRemoteNotification :: ApplicationState -> CString -> IO ()
72+ -- ^ Called when the application receives a remote notification.
73+ -- 'ApplicationState' is the current state of the app.
74+ -- The 'CString' JSON-encoded user info contained in the notification.
75+ -- For more information see https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623117-application?language=objc
5876 , _appDelegateConfig_appDelegateNotificationConfig :: AppDelegateNotificationConfig
77+ , _appDelegateConfig_developerExtrasEnabled :: Bool
78+ -- ^ Allow devtools in the app. Defaults to 'True'
79+ , _appDelegateConfig_applicationOpenFile :: CString -> IO Bool
80+ -- ^ Called when the app is launched by opening a file. 'CString' contains
81+ -- the file path. Return value is 'True' if the file was successfully
82+ -- opened. Defaults to ignoring the file and returning 'False'.
83+ --
84+ -- The Core Foundation plist key CFBundleDocumentTypes controls which file
85+ -- types should be associated with the app.
5986 }
6087
6188instance Default AppDelegateConfig where
@@ -69,7 +96,10 @@ instance Default AppDelegateConfig where
6996 , _appDelegateConfig_applicationWillTerminate = return ()
7097 , _appDelegateConfig_applicationSignificantTimeChange = return ()
7198 , _appDelegateConfig_applicationUniversalLink = \_ -> return ()
99+ , _appDelegateConfig_applicationDidReceiveRemoteNotification = \_ _ -> return ()
72100 , _appDelegateConfig_appDelegateNotificationConfig = def
101+ , _appDelegateConfig_developerExtrasEnabled = True
102+ , _appDelegateConfig_applicationOpenFile = \_ -> return False
73103 }
74104
75105data AuthorizationOption = AuthorizationOption_Badge
@@ -78,6 +108,12 @@ data AuthorizationOption = AuthorizationOption_Badge
78108 | AuthorizationOption_CarPlay
79109 deriving (Show, Read, Eq, Ord)
80110
111+data ApplicationState = ApplicationState_Active
112+ | ApplicationState_Inactive
113+ | ApplicationState_Background
114+ | ApplicationState_Unknown CInt
115+ deriving (Show, Read, Eq, Ord)
116+
81117data AppDelegateNotificationConfig = AppDelegateNotificationConfig
82118 { _appDelegateNotificationConfig_requestAuthorizationWithOptions :: Maybe (Set AuthorizationOption)
83119 , _appDelegateNotificationConfig_registerForRemoteNotifications :: Bool
@@ -96,29 +132,38 @@ instance Default AppDelegateNotificationConfig where
96132
97133-- | Run JSaddle in a WKWebView
98134run :: JSM () -> IO ()
99−run = run' Nothing def
135+run f = run' def (jsaddleMain f)
100136
101137-- | Run JSaddle in a WKWebView
102138runWithAppConfig :: AppDelegateConfig -> JSM () -> IO ()
103−runWithAppConfig = run' Nothing
139+runWithAppConfig cfg = run' cfg . jsaddleMain
104140
105141-- | Run JSaddle in a WKWebView first loading the specified file
106142-- from the mainBundle (relative to the resourcePath).
107−runFile :: ByteString -- ^ The file to navigate to.
108− -> ByteString -- ^ The path to allow read access to.
109− -> AppDelegateConfig
110− -> JSM ()
111− -> IO ()
112−runFile url allowing = run' $ Just (url, allowing)
113−
114−run' :: Maybe (ByteString, ByteString)
115− -> AppDelegateConfig
116− -> JSM ()
143+runFile
144+ :: ByteString -- ^ The file to navigate to.
145+ -> ByteString -- ^ The path to allow read access to.
146+ -> AppDelegateConfig
147+ -> JSM ()
148+ -> IO ()
149+runFile url allowing cfg = run' cfg . jsaddleMainFile url allowing
150+
151+-- | Run JSaddle in a WKWebView first loading the specified html
152+-- as though it came from the specified URL
153+-- (calls WKWebKit function loadHTMLString).
154+runHTMLWithBaseURL
155+ :: ByteString -- ^ HTML to load.
156+ -> ByteString -- ^ pretend it came from this URL.
157+ -> AppDelegateConfig
158+ -> JSM ()
159+ -> IO ()
160+runHTMLWithBaseURL url allowing cfg = run' cfg . jsaddleMainHTMLWithBaseURL url allowing
161+
162+run' :: AppDelegateConfig
163+ -> (WKWebView -> IO ())
117164 -> IO ()
118−run' mUrl cfg f = do
119− handler <- case mUrl of
120− Just (url, allowing) -> newStablePtr (jsaddleMainFile url allowing f)
121− Nothing -> newStablePtr (jsaddleMain f)
165+run' cfg main = do
166+ handler <- newStablePtr main
122167 progName <- getProgName
123168
124169 -- AppDelegate callbacks
@@ -131,6 +176,14 @@ run' mUrl cfg f = do
131176 applicationWillTerminate <- newStablePtr $ _appDelegateConfig_applicationWillTerminate cfg
132177 applicationSignificantTimeChange <- newStablePtr $ _appDelegateConfig_applicationSignificantTimeChange cfg
133178 applicationUniversalLink <- newStablePtr $ _appDelegateConfig_applicationUniversalLink cfg
179+ applicationDidReceiveRemoteNotification <- newStablePtr $ \n s -> do
180+ let appState = case n of
181+ 0 -> ApplicationState_Active
182+ 1 -> ApplicationState_Inactive
183+ 2 -> ApplicationState_Background
184+ _ -> ApplicationState_Unknown n
185+ _appDelegateConfig_applicationDidReceiveRemoteNotification cfg appState s
186+ applicationOpenFile <- newStablePtr $ fmap fromBool . _appDelegateConfig_applicationOpenFile cfg
134187
135188 -- AppDelegate notification configuration
136189 let ncfg = _appDelegateConfig_appDelegateNotificationConfig cfg
@@ -153,6 +206,7 @@ run' mUrl cfg f = do
153206 applicationWillTerminate
154207 applicationSignificantTimeChange
155208 applicationUniversalLink
209+ applicationDidReceiveRemoteNotification
156210 (fromBool requestAuthorizationWithOptions)
157211 (fromBool $ Set.member AuthorizationOption_Badge authorizationOptions)
158212 (fromBool $ Set.member AuthorizationOption_Sound authorizationOptions)
@@ -161,3 +215,5 @@ run' mUrl cfg f = do
161215 (fromBool registerForRemoteNotifications)
162216 didRegisterForRemoteNotificationsWithDeviceToken
163217 didFailToRegisterForRemoteNotificationsWithError
218+ (fromBool $ _appDelegateConfig_developerExtrasEnabled cfg)
219+ applicationOpenFile