{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} module Hbro.Core ( -- * Types CaseSensitivity(..) , Direction(..) , Wrap(..) , ZoomDirection(..) -- * Getters , getCurrentURI , getFaviconURI , getFavicon , getLoadProgress , getPageTitle , getPageData -- * Browsing , goHome , load , reload , reloadBypassCache , stopLoading , goBack , goForward -- * Other , printPage , searchText , searchText_ , spawnHbro , spawnHbro' , quit , saveWebPage , executeJSFile ) where -- {{{ Imports import Graphics.UI.Gtk.WebKit.Extended import Hbro.Config as Config import Hbro.Dyre -- import Hbro.Gui as Gui import Hbro.Gui.MainView import Hbro.Logger import Hbro.Prelude as H import Graphics.UI.Gtk.Gdk.Pixbuf (Pixbuf) import Graphics.UI.Gtk.General.General.Extended import Graphics.UI.Gtk.WebKit.WebDataSource import Graphics.UI.Gtk.WebKit.WebFrame import Network.URI.Extended import System.Process.Extended -- }}} -- {{{ Types data CaseSensitivity = CaseSensitive | CaseInsensitive instance ToBool CaseSensitivity where toBool CaseSensitive = True toBool CaseInsensitive = False data Direction = Forward | Backward instance ToBool Direction where toBool Forward = True toBool Backward = False data Wrap = Wrap | NoWrap instance ToBool Wrap where toBool Wrap = True toBool NoWrap = False data ZoomDirection = In | Out -- }}} -- {{{ Getters getCurrentURI :: (MonadIO m, MonadReader r m, Has MainView r, MonadThrow m) => m URI getCurrentURI = webViewGetUri =<< getWebView getFaviconURI :: (MonadIO m, MonadReader r m, Has MainView r, MonadThrow m) => m URI getFaviconURI = webViewGetIconUri =<< getWebView getFavicon :: (MonadIO m, MonadReader r m, Has MainView r, MonadThrow m) => Int -> Int -> m Pixbuf getFavicon w h = (\v -> webViewTryGetFaviconPixbuf v w h) =<< getWebView getLoadProgress :: (MonadIO m, MonadReader r m, Has MainView r) => m Double getLoadProgress = gSync . webViewGetProgress =<< getWebView getPageTitle :: (MonadIO m, MonadReader r m, Has MainView r, MonadThrow m) => m Text getPageTitle = webViewGetTitle =<< getWebView -- | Return the HTML code of the current webpage. getPageData :: (MonadIO m, MonadReader r m, Has MainView r, MonadThrow m) => m ByteString getPageData = dataSourceGetData =<< io . webFrameGetDataSource =<< io . webViewGetMainFrame =<< getWebView -- }}} -- {{{ Browsing goHome :: (MonadIO m, MonadLogger m, MonadReader r m, Has MainView r, Has (TVar Config) r, MonadThrow m) => m () goHome = load =<< Config.get homePageL load :: (MonadIO m, MonadLogger m, MonadReader r m, Has MainView r, MonadThrow m) => URI -> m () load uri = do debug $ "Loading URI: " ++ tshow uri -- void . logErrors $ do -- currentURI <- getURI -- guard (currentURI /= uri') -- Browser.advance currentURI -- load' uri' webview <- getWebView gSync . webViewLoadUri webview $ show uri' where uri' = case uriScheme uri of [] -> uri { uriScheme = "http://" } _ -> uri -- baseOf uri = uri { -- uriPath = (++ "/") . join "/" . Prelude.init . split "/" $ uriPath uri -- } -- load' :: (MonadBaseControl IO m, MonadReader GUI m, HasHTTPClient t, MonadThrow m) => URI -> m () -- load' uri = do -- page <- Client.retrieve uri -- -- render page =<< Client.getURI -- render page uri reload, goBack, goForward :: (MonadIO m, MonadReader r m, Has MainView r, MonadLogger m) => m () -- reload = load =<< Client.getURI -- goBack = load' =<< Browser.stepBackward =<< getURI -- goForward = load' =<< Browser.stepForward =<< getURI reload = gAsync . webViewReload =<< getWebView goBack = do gAsync . webViewGoBack =<< getWebView unlessM (gSync . webViewCanGoBack =<< getWebView) $ warning "Unable to go back." goForward = do gAsync . webViewGoForward =<< getWebView unlessM (gSync . webViewCanGoForward =<< getWebView) $ warning "Unable to go forward." reloadBypassCache, stopLoading :: (MonadIO m, MonadLogger m, MonadReader r m, Has MainView r) => m () reloadBypassCache = getWebView >>= gAsync . webViewReloadBypassCache >> debug "Reloading without cache." stopLoading = getWebView >>= gAsync . webViewStopLoading >> debug "Stopped loading" -- }}} -- {{{ searchText :: (MonadIO m, MonadLogger m, MonadReader r m, Has MainView r) => CaseSensitivity -> Direction -> Wrap -> Text -> m Bool searchText s d w text = do debug $ "Searching text: " ++ text v <- getWebView gSync $ webViewSearchText v text (toBool s) (toBool d) (toBool w) searchText_ :: (MonadIO m, Functor m, MonadLogger m, MonadReader r m, Has MainView r) => CaseSensitivity -> Direction -> Wrap -> Text -> m () searchText_ s d w text = void $ searchText s d w text printPage :: (MonadIO m, MonadReader r m, Has MainView r) => m () printPage = gAsync . webFramePrint =<< gSync . webViewGetMainFrame =<< getWebView -- }}} -- | Spawn another browser instance. spawnHbro :: (MonadIO m, MonadLogger m) => m () spawnHbro = do executable <- getHbroExecutable spawn (pack executable) [] -- | Spawn another browser instance and load the given URI at start-up. spawnHbro' :: (MonadIO m, MonadLogger m) => URI -> m () spawnHbro' uri = do executable <- getHbroExecutable spawn (pack executable) ["-u", tshow uri] -- | Terminate the program. quit :: (MonadIO m) => m () quit = gAsync mainQuit -- {{{ Misc saveWebPage :: (ControlIO m, MonadLogger m, MonadReader r m, Has MainView r, MonadThrow m) => FilePath -> m () saveWebPage file = writeFile file =<< getPageData -- | Execute a javascript file on current webpage. executeJSFile :: (MonadIO m, MonadLogger m) => FilePath -> WebView -> m () executeJSFile filePath webView' = do debug $ "Executing Javascript file: " ++ pack filePath script <- readFile filePath let script' = asText . unwords . map (++ "\n") . lines $ script gAsync $ webViewExecuteScript webView' script' -- }}} -- | Save current web page to a file, -- along with all its resources in a separated directory. -- Doesn't work for now, because web_resource_get_data's binding is missing... _savePage :: Text -> WebView -> IO () _savePage _path webView' = do frame <- webViewGetMainFrame webView' dataSource <- webFrameGetDataSource frame _mainResource <- webDataSourceGetMainResource dataSource _subResources <- webDataSourceGetSubresources dataSource return ()