Add persistence module
This will allow us to save the last chapter the user read, thus making it easier to track progress. Implement persistence module saveLastRead saves the chapter after each new one is read and writes it to xdgdata
This commit is contained in:
parent
7c92e161cb
commit
fab1d6b84c
2 changed files with 57 additions and 10 deletions
|
|
@ -1,4 +1,40 @@
|
|||
module Persistence where
|
||||
module Persistence
|
||||
( saveLastRead
|
||||
, loadLastRead
|
||||
) where
|
||||
|
||||
-- TODO: Add book state persistence
|
||||
import System.Directory (getXdgDirectory, XdgDirectory(XdgData), createDirectoryIfMissing)
|
||||
import System.FilePath ((</>))
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as TIO
|
||||
import Control.Exception (try, SomeException)
|
||||
import Text.Read (readMaybe)
|
||||
|
||||
saveLastRead :: FilePath -> Int -> IO ()
|
||||
saveLastRead bPath chapterIdx = do
|
||||
dataDir <- getXdgDirectory XdgData "svitak"
|
||||
createDirectoryIfMissing True dataDir
|
||||
|
||||
let configFile = dataDir </> "last_read.txt"
|
||||
-- Line 1 = Path, Line 2 = Index
|
||||
let content = T.pack bPath <> T.pack "\n" <> T.pack (show chapterIdx)
|
||||
|
||||
TIO.writeFile configFile content
|
||||
putStrLn $ "Progress saved to: " ++ configFile
|
||||
|
||||
loadLastRead :: IO (Maybe (FilePath, Int))
|
||||
loadLastRead = do
|
||||
dataDir <- getXdgDirectory XdgData "svitak"
|
||||
let configFile = dataDir </> "last_read.txt"
|
||||
|
||||
result <- try (TIO.readFile configFile) :: IO (Either SomeException T.Text)
|
||||
|
||||
case result of
|
||||
Left _ -> pure Nothing
|
||||
Right content -> do
|
||||
let linesOfFile = T.lines content
|
||||
case linesOfFile of
|
||||
[path, idxStr]
|
||||
| Just idx <- readMaybe (T.unpack idxStr) ->
|
||||
pure $ Just (T.unpack path, idx)
|
||||
_ -> pure Nothing
|
||||
|
|
|
|||
27
app/UI.hs
27
app/UI.hs
|
|
@ -12,7 +12,8 @@ import Control.Monad.Reader (runReaderT)
|
|||
import Data.IORef (newIORef, readIORef, writeIORef)
|
||||
import Text.HTML.TagSoup (renderTags)
|
||||
|
||||
import EpubParser (EpubEnv, resolveSpine, getChapter)
|
||||
import EpubParser (EpubEnv, resolveSpine, getChapter, bookPath)
|
||||
import Persistence (saveLastRead, loadLastRead)
|
||||
|
||||
runApp :: EpubEnv -> IO ()
|
||||
runApp env = do
|
||||
|
|
@ -20,7 +21,7 @@ runApp env = do
|
|||
app <- Gtk.applicationNew (Just "com.svitak.reader.v2") []
|
||||
|
||||
_ <- Gtk.on app #activate $ do
|
||||
putStrLn "DEBUG: App Activated"
|
||||
putStrLn "App Activated"
|
||||
|
||||
-- Setup window
|
||||
window <- Gtk.applicationWindowNew app
|
||||
|
|
@ -34,30 +35,40 @@ runApp env = do
|
|||
-- Get the spine
|
||||
spine <- runReaderT resolveSpine env
|
||||
let totalChapters = length spine
|
||||
putStrLn $ "DEBUG: Spine loaded. Total chapters: " ++ show totalChapters
|
||||
putStrLn $ "Spine loaded. Total chapters: " ++ show totalChapters
|
||||
|
||||
if totalChapters == 0
|
||||
then putStrLn "ERROR: This book has no chapters!"
|
||||
else do
|
||||
currentIndex <- newIORef 0
|
||||
|
||||
|
||||
let loadChapter index = do
|
||||
let maxIdx = totalChapters - 1
|
||||
let safeIdx = max 0 (min index maxIdx)
|
||||
|
||||
|
||||
-- Save state after every chapter
|
||||
writeIORef currentIndex safeIdx
|
||||
putStrLn $ "DEBUG: Loading Chapter " ++ show (safeIdx + 1)
|
||||
putStrLn $ "Loading Chapter " ++ show (safeIdx + 1)
|
||||
saveLastRead (bookPath env) safeIdx
|
||||
|
||||
let filename = spine !! safeIdx
|
||||
tags <- runReaderT (getChapter filename) env
|
||||
|
||||
let htmlContent = renderTags tags
|
||||
|
||||
-- Load HTML
|
||||
WebKit.webViewLoadHtml webView htmlContent (Just "file:///")
|
||||
|
||||
-- Load the first chapter
|
||||
loadChapter 0
|
||||
-- If there's no state saved then load the first chapter
|
||||
maybeSaved <- loadLastRead
|
||||
|
||||
case maybeSaved of
|
||||
Just (path, index)
|
||||
| path == bookPath env -> loadChapter index
|
||||
| otherwise -> loadChapter 0
|
||||
|
||||
Nothing -> loadChapter 0
|
||||
|
||||
|
||||
-- Setup keyboard input
|
||||
keyController <- Gtk.eventControllerKeyNew
|
||||
|
|
|
|||
Loading…
Reference in a new issue