seperate state handling logic

This commit is contained in:
Marko Andjelic 2026-02-04 03:51:47 +00:00
commit 1cab6a9bab
4 changed files with 61 additions and 48 deletions

View file

@ -3,15 +3,12 @@
module EpubParser
( EpubAction
, EpubEnv(..)
, AppState(..)
, openEpub
, getOpfPath
, resolveSpine
, getChapter
, getChapterTitle
, Tag(..)
, prepareView
, ChapterView(..)
) where
import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry, toArchive)
@ -23,8 +20,7 @@ import Control.Monad.Reader (ReaderT, MonadReader(ask), liftIO)
import Control.Monad.Except (runExceptT)
import System.FilePath (takeDirectory, (</>), normalise)
import Data.List (find)
import Text.HTML.TagSoup (parseTags, innerText, Tag(..), renderTags)
import Control.Concurrent.Async (Async)
import Text.HTML.TagSoup (parseTags, innerText, Tag(..))
import Codec.Epub.Parse (getSpine, getMetadata, getManifest)
import qualified Codec.Epub.Data.Metadata as DMeta
import qualified Codec.Epub.Data.Manifest as DMan
@ -33,18 +29,6 @@ import qualified Data.ByteString.Base64 as B64
type EpubAction a = ReaderT EpubEnv IO a
data AppState = AppState
{ cEnv :: EpubEnv
, cIdx :: Int
, zoomlvl :: Double
, cSpine :: [FilePath]
, bTitle :: T.Text
, cTags :: Maybe [Tag T.Text]
, activeTask :: Maybe (Async ())
, cAllChapters :: [[Tag T.Text]]
, taskVersion :: Integer
}
data EpubEnv = EpubEnv
{ archive :: Archive
, opfXml :: String
@ -54,12 +38,6 @@ data EpubEnv = EpubEnv
, eManifest :: DMan.Manifest
}
data ChapterView = ChapterView
{ viewTitle :: T.Text
, viewHtml :: T.Text
, viewIdx :: Int
}
openEpub :: FilePath -> IO (Either String EpubEnv)
openEpub path = do
rawZip <- B.readFile path
@ -172,13 +150,3 @@ getChapterTitle tags =
ishding _ = False
isclose n (TagClose n') = n == n'
isclose _ _ = False
prepareView :: AppState -> Int -> Maybe ChapterView
prepareView st index
| index < 0 || index >= length (cAllChapters st) = Nothing
| otherwise = Just $ ChapterView
{ viewTitle = bTitle st <> " - " <> getChapterTitle tags
, viewHtml = renderTags tags
, viewIdx = index
}
where tags = cAllChapters st !! index

55
app/State.hs Normal file
View file

@ -0,0 +1,55 @@
{-# LANGUAGE OverloadedStrings #-}
module State where
import qualified Data.Text as T
import Text.HTML.TagSoup (Tag, renderTags)
import Control.Concurrent.Async (Async)
import EpubParser (EpubEnv, getChapterTitle)
data ChapterView = ChapterView
{ viewTitle :: T.Text,
viewHtml :: T.Text,
viewIdx :: Int
}
data AppState = AppState
{ cEnv :: EpubEnv,
cIdx :: Int,
zoomlvl :: Double,
cSpine :: [FilePath],
bTitle :: T.Text,
cAllChapters :: [[Tag T.Text]],
activeTask :: Maybe (Async ()),
taskVersion :: Integer,
cTags :: Maybe [Tag T.Text]
}
-- loading template
initialState :: EpubEnv -> AppState
initialState env =
AppState
{ cEnv = env,
cIdx = 0,
cTags = Nothing,
cSpine = [],
bTitle = "Svitak - Loading...",
zoomlvl = 1.0,
activeTask = Nothing,
cAllChapters = [],
taskVersion = 0
}
-- prepare the data for the UI
prepareView :: AppState -> Int -> Maybe ChapterView
prepareView st index
| null (cAllChapters st) = Nothing
| index < 0 || index >= length (cAllChapters st) = Nothing
| otherwise =
let tags = cAllChapters st !! index
in Just $
ChapterView
{ viewTitle = bTitle st <> " - " <> getChapterTitle tags,
viewHtml = renderTags tags,
viewIdx = index
}

View file

@ -17,8 +17,9 @@ import Control.Monad.Reader (runReaderT)
import Control.Concurrent.STM (newTVarIO, readTVar, atomically, modifyTVar)
import Control.Concurrent.Async (async)
import Codec.Epub.Data.Metadata (metaTitles, titleType, titleText)
import EpubParser (EpubEnv(..), AppState(..), resolveSpine, getChapter, prepareView, ChapterView(..))
import EpubParser (EpubEnv(..), resolveSpine, getChapter)
import Persistence (saveLastRead, loadLastRead)
import State (AppState(..), ChapterView(..), initialState, prepareView)
runApp :: EpubEnv -> IO ()
runApp env' = do
@ -26,19 +27,7 @@ runApp env' = do
_ <- Gtk.on app #activate $ do
let loadingState = AppState
{ cEnv = env'
, cIdx = 0
, cTags = Nothing
, cSpine = []
, bTitle = "Svitak - Loading..."
, zoomlvl = 1.0
, activeTask = Nothing
, cAllChapters = []
, taskVersion = 0
}
stateTVar <- newTVarIO loadingState
stateTVar <- newTVarIO (initialState env')
window <- Gtk.applicationWindowNew app
webView <- WebKit.webViewNew

View file

@ -53,7 +53,8 @@ executable svitak
other-modules: EpubParser,
UI,
Persistence
Persistence,
State
build-depends: base ^>=4.21.0.0,
base64-bytestring,