@@ -5,30 +5,149 @@ module Language.Javascript.JSaddle.WKWebView
55 , run
66 , runFile
77 , mainBundleResourcePath
8+ , AppDelegateConfig (..)
9+ , AppDelegateNotificationConfig (..)
10+ , AuthorizationOption (..)
811 ) where
912
1013import Data.ByteString (ByteString)
14+import Data.Default (Default, def)
15+import Data.Set (Set)
16+import qualified Data.Set as Set
17+import Data.Word
18+import Foreign.Marshal.Utils (fromBool)
1119import Language.Javascript.JSaddle.WKWebView.Internal (jsaddleMain, jsaddleMainFile, WKWebView(..), mainBundleResourcePath)
1220import System.Environment (getProgName)
1321import Foreign.C.String (CString, withCString)
1422import Foreign.StablePtr (StablePtr, newStablePtr)
1523import Language.Javascript.JSaddle (JSM)
1624
17−foreign import ccall runInWKWebView :: StablePtr (WKWebView -> IO ()) -> CString -> IO ()
25+foreign import ccall runInWKWebView
26+ :: StablePtr (WKWebView -> IO ())
27+ -> CString
28+ -> StablePtr (IO ()) -- willFinishLaunchingWithOptions
29+ -> StablePtr (IO ()) -- didFinishLaunchingWithOptions
30+ -> StablePtr (IO ()) -- applicationDidBecomeActive
31+ -> StablePtr (IO ()) -- applicationWillResignActive
32+ -> StablePtr (IO ()) -- applicationDidEnterBackground
33+ -> StablePtr (IO ()) -- applicationWillEnterForeground
34+ -> StablePtr (IO ()) -- applicationWillTerminate
35+ -> StablePtr (IO ()) -- applicationSignificantTimeChange
36+ -> Word64 -- whether to run requestAuthorizationWithOptions
37+ -> Word64 -- Ask for Badge authorization
38+ -> Word64 -- Ask for Sound authorization
39+ -> Word64 -- Ask for Alert authorization
40+ -> Word64 -- Ask for CarPlay authorization
41+ -> Word64 -- registerForRemoteNotifications
42+ -> StablePtr (CString -> IO ()) -- didRegisterForRemoteNotificationsWithDeviceToken
43+ -> StablePtr (CString -> IO ()) -- didFailToRegisterForRemoteNotificationsWithError
44+ -> IO ()
45+
46+data AppDelegateConfig = AppDelegateConfig
47+ { _appDelegateConfig_willFinishLaunchingWithOptions :: IO ()
48+ , _appDelegateConfig_didFinishLaunchingWithOptions :: IO ()
49+ , _appDelegateConfig_applicationDidBecomeActive :: IO ()
50+ , _appDelegateConfig_applicationWillResignActive :: IO ()
51+ , _appDelegateConfig_applicationDidEnterBackground :: IO ()
52+ , _appDelegateConfig_applicationWillEnterForeground :: IO ()
53+ , _appDelegateConfig_applicationWillTerminate :: IO ()
54+ , _appDelegateConfig_applicationSignificantTimeChange :: IO ()
55+ , _appDelegateConfig_appDelegateNotificationConfig :: AppDelegateNotificationConfig
56+ }
57+
58+instance Default AppDelegateConfig where
59+ def = AppDelegateConfig
60+ { _appDelegateConfig_willFinishLaunchingWithOptions = return ()
61+ , _appDelegateConfig_didFinishLaunchingWithOptions = return ()
62+ , _appDelegateConfig_applicationDidBecomeActive = return ()
63+ , _appDelegateConfig_applicationWillResignActive = return ()
64+ , _appDelegateConfig_applicationDidEnterBackground = return ()
65+ , _appDelegateConfig_applicationWillEnterForeground = return ()
66+ , _appDelegateConfig_applicationWillTerminate = return ()
67+ , _appDelegateConfig_applicationSignificantTimeChange = return ()
68+ , _appDelegateConfig_appDelegateNotificationConfig = def
69+ }
70+
71+data AuthorizationOption = AuthorizationOption_Badge
72+ | AuthorizationOption_Sound
73+ | AuthorizationOption_Alert
74+ | AuthorizationOption_CarPlay
75+ deriving (Show, Read, Eq, Ord)
76+
77+data AppDelegateNotificationConfig = AppDelegateNotificationConfig
78+ { _appDelegateNotificationConfig_requestAuthorizationWithOptions :: Maybe (Set AuthorizationOption)
79+ , _appDelegateNotificationConfig_registerForRemoteNotifications :: Bool
80+ , _appDelegateNotificationConfig_didRegisterForRemoteNotificationsWithDeviceToken :: CString -> IO ()
81+ , _appDelegateNotificationConfig_didFailToRegisterForRemoteNotificationsWithError :: CString -> IO ()
82+ }
83+
84+instance Default AppDelegateNotificationConfig where
85+ def = AppDelegateNotificationConfig
86+ { _appDelegateNotificationConfig_requestAuthorizationWithOptions = Nothing
87+ , _appDelegateNotificationConfig_registerForRemoteNotifications = False
88+ , _appDelegateNotificationConfig_didRegisterForRemoteNotificationsWithDeviceToken = \_ -> return ()
89+ , _appDelegateNotificationConfig_didFailToRegisterForRemoteNotificationsWithError = \_ -> return ()
90+ }
91+
1892
1993-- | Run JSaddle in a WKWebView
20−run :: JSM () -> IO ()
21−run f = do
22− handler <- newStablePtr (jsaddleMain f)
23− progName <- getProgName
24− withCString progName $ runInWKWebView handler
94+run :: AppDelegateConfig -> JSM () -> IO ()
95+run = run' Nothing
2596
2697-- | Run JSaddle in a WKWebView first loading the specified file
2798-- from the mainBundle (relative to the resourcePath).
2899runFile :: ByteString -- ^ The file to navigate to.
29100 -> ByteString -- ^ The path to allow read access to.
30− -> JSM () -> IO ()
31−runFile url allowing f = do
32− handler <- newStablePtr (jsaddleMainFile url allowing f)
101+ -> AppDelegateConfig
102+ -> JSM ()
103+ -> IO ()
104+runFile url allowing = run' $ Just (url, allowing)
105+
106+run' :: Maybe (ByteString, ByteString)
107+ -> AppDelegateConfig
108+ -> JSM ()
109+ -> IO ()
110+run' mUrl cfg f = do
111+ handler <- case mUrl of
112+ Just (url, allowing) -> newStablePtr (jsaddleMainFile url allowing f)
113+ Nothing -> newStablePtr (jsaddleMain f)
33114 progName <- getProgName
34− withCString progName $ runInWKWebView handler
115+
116+ -- AppDelegate callbacks
117+ willFinishLaunchingWithOptions <- newStablePtr $ _appDelegateConfig_willFinishLaunchingWithOptions cfg
118+ didFinishLaunchingWithOptions <- newStablePtr $ _appDelegateConfig_didFinishLaunchingWithOptions cfg
119+ applicationDidBecomeActive <- newStablePtr $ _appDelegateConfig_applicationDidBecomeActive cfg
120+ applicationWillResignActive <- newStablePtr $ _appDelegateConfig_applicationWillResignActive cfg
121+ applicationDidEnterBackground <- newStablePtr $ _appDelegateConfig_applicationDidEnterBackground cfg
122+ applicationWillEnterForeground <- newStablePtr $ _appDelegateConfig_applicationWillEnterForeground cfg
123+ applicationWillTerminate <- newStablePtr $ _appDelegateConfig_applicationWillTerminate cfg
124+ applicationSignificantTimeChange <- newStablePtr $ _appDelegateConfig_applicationSignificantTimeChange cfg
125+
126+ -- AppDelegate notification configuration
127+ let ncfg = _appDelegateConfig_appDelegateNotificationConfig cfg
128+ (requestAuthorizationWithOptions, authorizationOptions) =
129+ case _appDelegateNotificationConfig_requestAuthorizationWithOptions ncfg of
130+ Nothing -> (False, Set.empty)
131+ Just opts -> (True, opts)
132+ registerForRemoteNotifications = _appDelegateNotificationConfig_registerForRemoteNotifications ncfg
133+ didRegisterForRemoteNotificationsWithDeviceToken <- newStablePtr $ _appDelegateNotificationConfig_didRegisterForRemoteNotificationsWithDeviceToken ncfg
134+ didFailToRegisterForRemoteNotificationsWithError <- newStablePtr $ _appDelegateNotificationConfig_didFailToRegisterForRemoteNotificationsWithError ncfg
135+ withCString progName $ \pn -> runInWKWebView
136+ handler
137+ pn
138+ willFinishLaunchingWithOptions
139+ didFinishLaunchingWithOptions
140+ applicationDidBecomeActive
141+ applicationWillResignActive
142+ applicationDidEnterBackground
143+ applicationWillEnterForeground
144+ applicationWillTerminate
145+ applicationSignificantTimeChange
146+ (fromBool requestAuthorizationWithOptions)
147+ (fromBool $ Set.member AuthorizationOption_Badge authorizationOptions)
148+ (fromBool $ Set.member AuthorizationOption_Sound authorizationOptions)
149+ (fromBool $ Set.member AuthorizationOption_Alert authorizationOptions)
150+ (fromBool $ Set.member AuthorizationOption_CarPlay authorizationOptions)
151+ (fromBool registerForRemoteNotifications)
152+ didRegisterForRemoteNotificationsWithDeviceToken
153+ didFailToRegisterForRemoteNotificationsWithError