1.2 Beta last state !!!

This commit is contained in:
inhale-dir 2024-12-13 13:11:17 +01:00
parent d632e7ac0d
commit dc2a67ac0d
2 changed files with 112 additions and 37 deletions

View File

@ -40,6 +40,13 @@ import kotlinx.coroutines.flow.Flow
import inhale.rip.epook.data.Book
import nl.siegmann.epublib.domain.Book as EpubBook
// Move the Chapter data class outside the composable
private data class Chapter(
val index: Int,
val title: String,
val resource: Resource
)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReaderScreen(
@ -53,7 +60,7 @@ fun ReaderScreen(
var currentSettings by remember { mutableStateOf(Settings()) }
var currentChapterIndex by remember { mutableStateOf(0) }
var chapters by remember { mutableStateOf(listOf<Resource>()) }
var chapters by remember { mutableStateOf<List<Chapter>>(emptyList()) }
var book by remember { mutableStateOf<EpubBook?>(null) }
var showControls by remember { mutableStateOf(true) }
@ -62,6 +69,9 @@ fun ReaderScreen(
val backgroundColor = MaterialTheme.colorScheme.background.toArgb()
val textColor = MaterialTheme.colorScheme.onBackground.toArgb()
// Add state for reading position
var currentReadingPosition by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
try {
currentSettings = settingsStore.getSettings()
@ -72,17 +82,62 @@ fun ReaderScreen(
LaunchedEffect(bookId) {
try {
currentChapterIndex = bookStore.getReadingPosition(bookId).first()
val bookPath = bookStore.getBookPath(bookId)
val epubBook = EpubReader().readEpub(FileInputStream(bookPath))
book = epubBook
chapters = epubBook.spine.spineReferences.mapNotNull { spineRef: nl.siegmann.epublib.domain.SpineReference ->
spineRef.resource
// Extract chapters with titles
chapters = epubBook.spine.spineReferences.mapIndexed { index, spineRef ->
val resource = spineRef.resource
val title = when {
// Try to get title from TOC
epubBook.tableOfContents.allUniqueResources.contains(resource) -> {
epubBook.tableOfContents.allUniqueResources
.find { it == resource }
?.title ?: "Chapter ${index + 1}"
}
// Try to parse HTML for title
resource.mediaType.toString().contains("html") -> {
try {
val html = String(resource.data, Charset.defaultCharset())
val doc = Jsoup.parse(html)
doc.select("h1, h2, h3, title").firstOrNull()?.text()
?: "Chapter ${index + 1}"
} catch (e: Exception) {
"Chapter ${index + 1}"
}
}
else -> "Chapter ${index + 1}"
}
Chapter(index, title, resource)
}
} catch (e: Exception) {
Timber.e(e, "Error loading book")
}
}
// Save position when chapter changes
LaunchedEffect(currentChapterIndex) {
try {
bookStore.updateReadingPosition(bookId, currentChapterIndex)
} catch (e: Exception) {
Timber.e(e, "Error saving reading position")
}
}
// Handle back button to save position before leaving
BackHandler {
scope.launch {
try {
bookStore.updateReadingPosition(bookId, currentChapterIndex)
} catch (e: Exception) {
Timber.e(e, "Error saving reading position on exit")
}
onNavigateBack()
}
}
Scaffold(
topBar = {
AnimatedVisibility(
@ -149,28 +204,30 @@ fun ReaderScreen(
}
},
update = { webView ->
val chapter = chapters[currentChapterIndex]
val html = """
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: ${currentSettings.fontFamily};
line-height: ${currentSettings.lineHeight};
padding: ${currentSettings.padding}px;
margin: 0;
background-color: #${backgroundColor.toString(16)};
color: #${textColor.toString(16)};
}
</style>
</head>
<body>
${String(chapter.data, Charset.defaultCharset())}
</body>
</html>
""".trimIndent()
webView.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null)
val chapter = chapters.getOrNull(currentChapterIndex)?.resource
chapter?.let { resource ->
val html = """
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: ${currentSettings.fontFamily};
line-height: ${currentSettings.lineHeight};
padding: ${currentSettings.padding}px;
margin: 0;
background-color: #${backgroundColor.toString(16)};
color: #${textColor.toString(16)};
}
</style>
</head>
<body>
${String(resource.data, Charset.defaultCharset())}
</body>
</html>
""".trimIndent()
webView.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null)
}
}
)
}
@ -224,31 +281,33 @@ fun ReaderScreen(
if (showChapterList) {
AlertDialog(
onDismissRequest = { showChapterList = false },
title = { Text("Chapters") },
title = { Text("Table of Contents") },
text = {
LazyColumn {
items(
items = List(chapters.size) { it },
key = { it }
) { index ->
items = chapters,
key = { chapter: Chapter -> chapter.index }
) { chapter ->
ListItem(
headlineContent = {
Text("Chapter ${index + 1}")
Text(
text = chapter.title,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
},
modifier = Modifier.clickable {
currentChapterIndex = index
currentChapterIndex = chapter.index
showChapterList = false
},
leadingContent = if (currentChapterIndex == index) {
{
leadingContent = {
if (currentChapterIndex == chapter.index) {
Icon(
Icons.Default.RadioButtonChecked,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary
)
}
} else {
{
} else {
Icon(
Icons.Default.RadioButtonUnchecked,
contentDescription = null

View File

@ -12,6 +12,7 @@ import android.util.Log
import nl.siegmann.epublib.domain.Book as EpubBook
import nl.siegmann.epublib.epub.EpubReader
import java.io.FileInputStream
import timber.log.Timber
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "books")
@ -35,13 +36,28 @@ class BookStore(private val context: Context) {
}
suspend fun updateReadingPosition(bookId: String, position: Int) {
bookDao.updateReadingPosition(bookId, position)
try {
bookDao.updateReadingPosition(bookId, position)
Timber.d("Updated reading position for book $bookId to $position")
} catch (e: Exception) {
Timber.e(e, "Failed to update reading position")
throw e
}
}
fun getReadingPosition(bookId: String): Flow<Int> {
return bookDao.getBookPosition(bookId)
}
suspend fun getInitialReadingPosition(bookId: String): Int {
return try {
bookDao.getBook(bookId)?.readingPosition ?: 0
} catch (e: Exception) {
Timber.e(e, "Failed to get initial reading position")
0
}
}
suspend fun deleteBook(bookId: String) {
Log.e(TAG, "🔥 DELETE BOOK STARTED 🔥")
Log.e(TAG, "Attempting to delete book with ID: $bookId")