refactor epPicker into smaller functions using ExceptT

This commit is contained in:
Marko Andjelic 2026-07-11 15:47:00 +01:00
commit 9f9e59b450
Signed by: marko
GPG key ID: 9C5E99C8C682FB59

View file

@ -1,11 +1,13 @@
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | The GTK4 / WebKit front end. The book's structure loads in the background;
-- chapters are rendered lazily (and cached) the first time they're visited,
-- with neighbours preloaded so arrow-key paging feels instant.
module UI (runApp) where
import Data.Bifunctor (first)
import Control.Concurrent.Async (async)
import Control.Concurrent.STM (TVar, atomically, modifyTVar', newTVarIO, readTVarIO, writeTVar, readTVar, modifyTVar')
import Data.List (minimumBy)
@ -18,6 +20,8 @@ import qualified Data.Text as T
import Data.Word (Word32)
import Data.Bits ((.|.))
import Control.Exception (SomeException, try)
import Control.Monad.Except
import Control.Monad.IO.Class (liftIO)
import EpubParser (EpubEnv, openEpub) -- brings the `BookInfo EpubEnv` instance into scope
import qualified GI.GLib as GLib
import qualified GI.GLib.Constants as GLibConst
@ -272,18 +276,30 @@ epPicker :: Maybe Gtk.ApplicationWindow -> Ctx -> IO ()
epPicker window ctx = do
dg <- Gtk.fileDialogNew
Gtk.fileDialogOpen dg window (Nothing :: Maybe Gio.Cancellable) $ Just $ \_ result -> do
outcome <- try (Gtk.fileDialogOpenFinish dg result) :: IO (Either SomeException Gio.File)
case outcome of
Left _err -> putStrLn "picker cancelled or failed"
Right file -> do
mp <- Gio.fileGetPath file
case mp of
Nothing -> putStrLn "selected file has no local path"
Just path -> do
env <- openEpub path
case env of
Left err -> putStrLn ("open failed: " ++ err)
Right e -> loadBook e ctx
outcome <- runExceptT $ do
file <- pickerGetFile dg result
path <- getFilePath file
env <- extractEnv path
liftIO $ loadBook env ctx
either putStrLn pure outcome
pickerGetFile :: Gtk.FileDialog -> Gio.AsyncResult -> ExceptT String IO Gio.File
pickerGetFile dg result =
ExceptT $ first (const "picker cancelled or failed")
<$> (try (Gtk.fileDialogOpenFinish dg result) :: IO (Either SomeException Gio.File))
getFilePath :: Gio.File -> ExceptT String IO FilePath
getFilePath file = do
mp <- liftIO $ Gio.fileGetPath file
maybe (throwError "selected file has no local path") pure mp
extractEnv :: FilePath -> ExceptT String IO EpubEnv
extractEnv path =
ExceptT $ first ("open failed: " ++) <$> openEpub path
--------------------------------------------------------------------------------
-- Navigation + rendering