many improvements and prototype launcher image
No files matched your search
@@ -307,9 +307,24 @@ actual suspend fun saveLibraryReadingPosition(fileId: String, position: ReadingP
|
||||
}
|
||||
}
|
||||
|
||||
actual suspend fun clearLibraryReadingPosition(fileId: String) = withContext(Dispatchers.IO) {
|
||||
openLibraryDatabase().useLibrary { db ->
|
||||
val file = db.files.get(fileId) ?: return@useLibrary
|
||||
val clusterId = file.bodyClusterId ?: return@useLibrary
|
||||
db.readingStates.deleteForBodyCluster(clusterId)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
|
||||
actual suspend fun markLibraryReadingStatus(fileId: String, status: BookReadingStatus): Boolean = withContext(Dispatchers.IO) {
|
||||
openLibraryDatabase().useLibrary { db ->
|
||||
db.files.updateReadingStatus(fileId, status)
|
||||
db.transaction {
|
||||
if (status == BookReadingStatus.NEW) {
|
||||
val file = files.get(fileId) ?: return@transaction false
|
||||
file.bodyClusterId?.let { readingStates.deleteForBodyCluster(it) }
|
||||
}
|
||||
files.updateReadingStatus(fileId, status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,30 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Adaptive icon foreground: 108dp x 108dp canvas.
|
||||
Safe zone: inner 72dp circle (18dp..90dp). Book (200x260) scaled 0.2769x:
|
||||
translateX=26.31, translateY=18. Star sub-group at book coords (67,59) scale 0.888x.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
|
||||
<group
|
||||
android:translateX="26.31"
|
||||
android:translateY="18"
|
||||
android:scaleX="0.2769"
|
||||
android:scaleY="0.2769">
|
||||
|
||||
<!-- Pages stack -->
|
||||
<path android:fillColor="#e8e4d8"
|
||||
android:pathData="M36,18 H178 V248 H36 Z"/>
|
||||
<path android:fillColor="#ece9df"
|
||||
android:pathData="M34,16 H176 V246 H34 Z"/>
|
||||
<path android:fillColor="#f0ede3"
|
||||
android:pathData="M32,14 H174 V244 H32 Z"/>
|
||||
|
||||
<!-- Spine -->
|
||||
<path android:fillColor="#1a3d52"
|
||||
android:pathData="M18,14 H36 V244 H18 Z"/>
|
||||
<path android:fillColor="#00000000"
|
||||
android:strokeColor="#30000000"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M35,14 V244"/>
|
||||
|
||||
<!-- Cover -->
|
||||
<path android:fillColor="#2c5f7a"
|
||||
android:pathData="M32,14 H174 V244 H32 Z"/>
|
||||
|
||||
<!-- Cover border -->
|
||||
<path android:fillColor="#00000000"
|
||||
android:strokeColor="#30ffffff"
|
||||
android:strokeWidth="1.5"
|
||||
android:pathData="M40,22 H166 V236 H40 Z"/>
|
||||
|
||||
<!-- Star arms -->
|
||||
<group
|
||||
android:translateX="67"
|
||||
android:translateY="59"
|
||||
android:scaleX="0.888"
|
||||
android:scaleY="0.888">
|
||||
<path android:fillColor="#6197b4"
|
||||
android:pathData="m 32.120065,25.957965 -15.0296,-9.2912 c -0.3066,-0.187 -0.6532,0.1603 -0.4666,0.4676 l 8.9112,14.4745 c 0.2399,0.3874 0.5665,0.7013 0.9597,0.9284 l 14.0032,8.0555 V 0.34209525 c 0,-0.394094 -0.5532,-0.474248 -0.6665,-0.1002 z"/>
|
||||
<path android:fillColor="#bdccd6"
|
||||
android:pathData="m 25.901665,48.988865 -9.271,15.0556 c -0.1866,0.3073 0.16,0.6546 0.4665,0.4676 l 14.4431,-8.9305 c 0.3866,-0.2405 0.6999,-0.5678 0.9265,-0.9619 l 8.038,-14.0336 H 0.34134532 c -0.393231,0 -0.473212,0.5544 -0.09997,0.6679 z"/>
|
||||
<path android:fillColor="#94bfcf"
|
||||
android:pathData="m 55.101065,32.189965 9.2711,-15.0623 c 0.1866,-0.3072 -0.16,-0.6546 -0.4666,-0.4675 l -14.4431,8.9371 c -0.3865,0.2405 -0.6998,0.5678 -0.9264,0.9619 l -8.038,14.027 h 40.1634 c 0.3932,0 0.4732,-0.5544 0.1,-0.668 z"/>
|
||||
<path android:fillColor="#eee9d9"
|
||||
android:pathData="m 54.507965,48.641565 -14.0099,-8.0555 v 40.2507 c 0,0.3941 0.5532,0.4742 0.6665,0.1002 l 7.7181,-25.7094 15.0296,9.2912 c 0.3066,0.187 0.6532,-0.1603 0.4665,-0.4676 l -8.9177,-14.4812 c -0.2333,-0.3807 -0.5666,-0.7013 -0.9531,-0.9284 z"/>
|
||||
</group>
|
||||
|
||||
<!-- Bottom spine accent -->
|
||||
<path android:fillColor="#0e2030"
|
||||
android:pathData="M18,228 H36 V244 H18 Z"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -1,170 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF"/>
|
||||
</vector>
|
||||
android:fillColor="#0d2535"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 35 KiB |
@@ -118,7 +118,7 @@ private fun BookReaderApp(onThemeToggle: () -> Unit) {
|
||||
)
|
||||
is AppState.Reader -> {
|
||||
scope.launch { saveActiveReadingFileId(null) }
|
||||
AppState.Library(current.libraryItems, current.scanPath, current.message)
|
||||
AppState.Library(emptyList(), current.scanPath, current.message)
|
||||
}
|
||||
is AppState.Scan -> AppState.Library(current.items, current.scanPath, current.message)
|
||||
is AppState.Error -> AppState.LoadingLibrary
|
||||
|
||||
@@ -116,6 +116,8 @@ expect suspend fun loadLibraryReadingPosition(fileId: String): ReadingPosition?
|
||||
|
||||
expect suspend fun saveLibraryReadingPosition(fileId: String, position: ReadingPosition)
|
||||
|
||||
expect suspend fun clearLibraryReadingPosition(fileId: String)
|
||||
|
||||
expect suspend fun markLibraryReadingStatus(fileId: String, status: BookReadingStatus): Boolean
|
||||
|
||||
expect suspend fun shareLibraryBookFile(fileId: String): Boolean
|
||||
|
||||
@@ -146,6 +146,28 @@ internal fun LibraryScreen(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun applyReadingStatus(
|
||||
item: LibraryItem,
|
||||
status: BookReadingStatus,
|
||||
successMessage: String,
|
||||
) {
|
||||
if (markLibraryReadingStatus(item.fileId, status)) {
|
||||
val updatedItem = loadLibraryItem(item.fileId) ?: item.copy(readingStatus = status)
|
||||
items = items.replaceLibraryItem(updatedItem)
|
||||
searchResults = searchResults.replaceLibraryItem(updatedItem)
|
||||
message = successMessage
|
||||
if (searchActive) {
|
||||
searching = true
|
||||
searchResults = searchLibraryItems(searchText, SearchResultLimit)
|
||||
searching = false
|
||||
} else {
|
||||
loadPage(reset = true)
|
||||
}
|
||||
} else {
|
||||
message = "Could not update ${item.title}."
|
||||
}
|
||||
}
|
||||
|
||||
fun rescanAllLibrary() {
|
||||
settingsMenuOpen = false
|
||||
scope.launch {
|
||||
@@ -320,7 +342,13 @@ internal fun LibraryScreen(
|
||||
readerLibraryItems = readerLibraryItems.replaceLibraryItem(updatedItem)
|
||||
coverCache[updatedItem.fileId] = loadLibraryItemCover(updatedItem.fileId)
|
||||
}
|
||||
markLibraryReadingStatus(item.fileId, BookReadingStatus.READING)
|
||||
if (markLibraryReadingStatus(item.fileId, BookReadingStatus.READING)) {
|
||||
val readingItem = loadLibraryItem(item.fileId)
|
||||
?: item.copy(readingStatus = BookReadingStatus.READING)
|
||||
items = items.replaceLibraryItem(readingItem)
|
||||
searchResults = searchResults.replaceLibraryItem(readingItem)
|
||||
readerLibraryItems = readerLibraryItems.replaceLibraryItem(readingItem)
|
||||
}
|
||||
saveActiveReadingFileId(item.fileId)
|
||||
AppState.Reader(
|
||||
fileId = item.fileId,
|
||||
@@ -342,12 +370,7 @@ internal fun LibraryScreen(
|
||||
scope.launch {
|
||||
busy = true
|
||||
try {
|
||||
if (markLibraryReadingStatus(item.fileId, BookReadingStatus.READ)) {
|
||||
message = "Marked ${item.title} as read."
|
||||
refresh()
|
||||
} else {
|
||||
message = "Could not update ${item.title}."
|
||||
}
|
||||
applyReadingStatus(item, BookReadingStatus.READ, "Marked ${item.title} as read.")
|
||||
} finally {
|
||||
busy = false
|
||||
}
|
||||
@@ -357,12 +380,7 @@ internal fun LibraryScreen(
|
||||
scope.launch {
|
||||
busy = true
|
||||
try {
|
||||
if (markLibraryReadingStatus(item.fileId, BookReadingStatus.NEW)) {
|
||||
message = "Marked ${item.title} as unread."
|
||||
refresh()
|
||||
} else {
|
||||
message = "Could not update ${item.title}."
|
||||
}
|
||||
applyReadingStatus(item, BookReadingStatus.NEW, "Marked ${item.title} as unread.")
|
||||
} finally {
|
||||
busy = false
|
||||
}
|
||||
@@ -372,12 +390,7 @@ internal fun LibraryScreen(
|
||||
scope.launch {
|
||||
busy = true
|
||||
try {
|
||||
if (markLibraryReadingStatus(item.fileId, BookReadingStatus.NEW)) {
|
||||
message = "Removed marks from ${item.title}."
|
||||
refresh()
|
||||
} else {
|
||||
message = "Could not update ${item.title}."
|
||||
}
|
||||
applyReadingStatus(item, BookReadingStatus.NEW, "Removed marks from ${item.title}.")
|
||||
} finally {
|
||||
busy = false
|
||||
}
|
||||
@@ -387,12 +400,7 @@ internal fun LibraryScreen(
|
||||
scope.launch {
|
||||
busy = true
|
||||
try {
|
||||
if (markLibraryReadingStatus(item.fileId, BookReadingStatus.NOT_INTERESTED)) {
|
||||
message = "Marked ${item.title} as not interested."
|
||||
refresh()
|
||||
} else {
|
||||
message = "Could not update ${item.title}."
|
||||
}
|
||||
applyReadingStatus(item, BookReadingStatus.NOT_INTERESTED, "Marked ${item.title} as not interested.")
|
||||
} finally {
|
||||
busy = false
|
||||
}
|
||||
@@ -438,7 +446,8 @@ internal fun LibraryScreen(
|
||||
librarySection(
|
||||
key = "reading",
|
||||
title = "reading now",
|
||||
count = readingNow.size,
|
||||
itemCount = readingNow.size,
|
||||
displayCount = readingNow.size.takeIf { endReached },
|
||||
collapsed = readingNowCollapsed,
|
||||
onCollapsedChange = { readingNowCollapsed = it },
|
||||
) {
|
||||
@@ -447,7 +456,8 @@ internal fun LibraryScreen(
|
||||
librarySection(
|
||||
key = "library",
|
||||
title = "my library",
|
||||
count = myLibrary.size,
|
||||
itemCount = myLibrary.size,
|
||||
displayCount = myLibrary.size.takeIf { endReached },
|
||||
collapsed = myLibraryCollapsed,
|
||||
onCollapsedChange = { myLibraryCollapsed = it },
|
||||
) {
|
||||
@@ -456,7 +466,8 @@ internal fun LibraryScreen(
|
||||
librarySection(
|
||||
key = "not-interested",
|
||||
title = "not interested",
|
||||
count = notInterested.size,
|
||||
itemCount = notInterested.size,
|
||||
displayCount = notInterested.size.takeIf { endReached },
|
||||
collapsed = notInterestedCollapsed,
|
||||
onCollapsedChange = { notInterestedCollapsed = it },
|
||||
) {
|
||||
@@ -573,16 +584,17 @@ private fun EmptySearchPane(modifier: Modifier = Modifier) {
|
||||
private fun LazyListScope.librarySection(
|
||||
key: String,
|
||||
title: String,
|
||||
count: Int,
|
||||
itemCount: Int,
|
||||
displayCount: Int?,
|
||||
collapsed: Boolean,
|
||||
onCollapsedChange: (Boolean) -> Unit,
|
||||
content: LazyListScope.() -> Unit,
|
||||
) {
|
||||
if (count == 0) return
|
||||
if (itemCount == 0) return
|
||||
item(key = "section-$key") {
|
||||
LibrarySectionHeader(
|
||||
text = title,
|
||||
count = count,
|
||||
count = displayCount,
|
||||
collapsed = collapsed,
|
||||
onToggle = { onCollapsedChange(!collapsed) },
|
||||
)
|
||||
@@ -595,7 +607,7 @@ private fun LazyListScope.librarySection(
|
||||
@Composable
|
||||
private fun LibrarySectionHeader(
|
||||
text: String,
|
||||
count: Int,
|
||||
count: Int?,
|
||||
collapsed: Boolean,
|
||||
onToggle: () -> Unit,
|
||||
) {
|
||||
@@ -614,7 +626,7 @@ private fun LibrarySectionHeader(
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
Text(
|
||||
"$text ($count)",
|
||||
if (count == null) text else "$text ($count)",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
textAlign = TextAlign.Center,
|
||||
|
||||
@@ -255,9 +255,24 @@ actual suspend fun saveLibraryReadingPosition(fileId: String, position: ReadingP
|
||||
}
|
||||
}
|
||||
|
||||
actual suspend fun clearLibraryReadingPosition(fileId: String) = withContext(Dispatchers.IO) {
|
||||
openLibraryDatabase().useLibrary { db ->
|
||||
val file = db.files.get(fileId) ?: return@useLibrary
|
||||
val clusterId = file.bodyClusterId ?: return@useLibrary
|
||||
db.readingStates.deleteForBodyCluster(clusterId)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
|
||||
actual suspend fun markLibraryReadingStatus(fileId: String, status: BookReadingStatus): Boolean = withContext(Dispatchers.IO) {
|
||||
openLibraryDatabase().useLibrary { db ->
|
||||
db.files.updateReadingStatus(fileId, status)
|
||||
db.transaction {
|
||||
if (status == BookReadingStatus.NEW) {
|
||||
val file = files.get(fileId) ?: return@transaction false
|
||||
file.bodyClusterId?.let { readingStates.deleteForBodyCluster(it) }
|
||||
}
|
||||
files.updateReadingStatus(fileId, status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ actual suspend fun loadLibraryReadingPosition(fileId: String): ReadingPosition?
|
||||
|
||||
actual suspend fun saveLibraryReadingPosition(fileId: String, position: ReadingPosition) = Unit
|
||||
|
||||
actual suspend fun clearLibraryReadingPosition(fileId: String) = Unit
|
||||
|
||||
actual suspend fun markLibraryReadingStatus(fileId: String, status: BookReadingStatus): Boolean = false
|
||||
|
||||
actual suspend fun shareLibraryBookFile(fileId: String): Boolean = false
|
||||
|
||||