gud commit
This commit is contained in:
Generated
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<bytecodeTargetLevel target="21" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetSelector">
|
||||||
|
<selectionStates>
|
||||||
|
<SelectionState runConfigName="app">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
|
</selectionStates>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+20
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
|
<component name="GradleSettings">
|
||||||
|
<option name="linkedExternalProjectsSettings">
|
||||||
|
<GradleProjectSettings>
|
||||||
|
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||||
|
<option name="modules">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
<option name="resolveExternalAnnotations" value="false" />
|
||||||
|
</GradleProjectSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
<option name="previewFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="KotlinJpsPluginSettings">
|
||||||
|
<option name="version" value="1.9.22" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectMigrations">
|
||||||
|
<option name="MigrateToGradleLocalJavaHome">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectType">
|
||||||
|
<option name="id" value="Android" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+17
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||||
|
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -19,6 +19,9 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
isDebuggable = true
|
||||||
|
}
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
@@ -87,4 +90,7 @@ dependencies {
|
|||||||
implementation("androidx.room:room-runtime:$roomVersion")
|
implementation("androidx.room:room-runtime:$roomVersion")
|
||||||
implementation("androidx.room:room-ktx:$roomVersion")
|
implementation("androidx.room:room-ktx:$roomVersion")
|
||||||
ksp("androidx.room:room-compiler:$roomVersion")
|
ksp("androidx.room:room-compiler:$roomVersion")
|
||||||
|
|
||||||
|
// Add Timber for logging
|
||||||
|
implementation("com.jakewharton.timber:timber:5.0.1")
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".EpookApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|||||||
@@ -7,31 +7,32 @@ import androidx.datastore.preferences.preferencesDataStore
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import inhale.rip.epook.data.AppDatabase
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "books")
|
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "books")
|
||||||
|
|
||||||
class BookStore(private val context: Context) {
|
class BookStore(private val context: Context) {
|
||||||
|
private val TAG = "BookStore" // Tag for logging
|
||||||
private val bookIdsKey = stringSetPreferencesKey("book_ids")
|
private val bookIdsKey = stringSetPreferencesKey("book_ids")
|
||||||
private val bookDao = AppDatabase.getDatabase(context).bookDao()
|
private val bookDao = AppDatabase.getDatabase(context).bookDao()
|
||||||
|
|
||||||
fun getAllBooks(): Flow<List<Book>> = context.dataStore.data.map { preferences ->
|
fun getAllBooks(): Flow<List<Book>> = bookDao.getAllBooks().map { entities ->
|
||||||
preferences[bookIdsKey]?.mapNotNull { id ->
|
entities.mapNotNull { entity ->
|
||||||
try {
|
try {
|
||||||
val bookFile = File(context.filesDir, "book_$id.epub")
|
val bookFile = File(entity.filePath)
|
||||||
val coverFile = File(context.filesDir, "cover_$id.jpg")
|
|
||||||
if (bookFile.exists()) {
|
if (bookFile.exists()) {
|
||||||
Book(
|
entity.toBook()
|
||||||
id = id,
|
} else {
|
||||||
title = preferences[stringPreferencesKey("title_$id")] ?: "Unknown Title",
|
// If the file doesn't exist, delete the database entry
|
||||||
coverImageFile = if (coverFile.exists()) coverFile else null,
|
Log.d(TAG, "Book file missing for ${entity.id}, cleaning up database entry")
|
||||||
filePath = bookFile.absolutePath
|
null
|
||||||
)
|
}
|
||||||
} else null
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("Error loading book $id: ${e.message}")
|
Log.e(TAG, "Error loading book ${entity.id}", e)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun addBook(book: Book) {
|
suspend fun addBook(book: Book) {
|
||||||
@@ -54,59 +55,76 @@ class BookStore(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteBook(bookId: String) {
|
suspend fun deleteBook(bookId: String) {
|
||||||
|
Log.e(TAG, "🔥 DELETE BOOK STARTED 🔥") // Very visible error log
|
||||||
|
Log.e(TAG, "Attempting to delete book with ID: $bookId")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Debug logging at start
|
// Check if book exists in Room database
|
||||||
println("=== Starting book deletion process ===")
|
val bookEntity = bookDao.getBook(bookId)
|
||||||
println("BookID: $bookId")
|
Log.e(TAG, if (bookEntity != null) {
|
||||||
|
"Found book in database: ${bookEntity.title} (ID: ${bookEntity.id})"
|
||||||
|
} else {
|
||||||
|
"Book not found in database with ID: $bookId"
|
||||||
|
})
|
||||||
|
|
||||||
// Delete the book files
|
if (bookEntity != null) {
|
||||||
|
// Try to delete from Room database
|
||||||
|
try {
|
||||||
|
bookDao.deleteBook(bookEntity)
|
||||||
|
Log.e(TAG, "Successfully deleted from database: ${bookEntity.title}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to delete from database: ${e.message}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File deletion
|
||||||
val bookFile = File(context.filesDir, "book_$bookId.epub")
|
val bookFile = File(context.filesDir, "book_$bookId.epub")
|
||||||
val coverFile = File(context.filesDir, "cover_$bookId.jpg")
|
Log.e(TAG, "Book file path: ${bookFile.absolutePath}")
|
||||||
|
|
||||||
println("Book file path: ${bookFile.absolutePath}")
|
|
||||||
println("Cover file path: ${coverFile.absolutePath}")
|
|
||||||
println("Book file exists: ${bookFile.exists()}")
|
|
||||||
println("Cover file exists: ${coverFile.exists()}")
|
|
||||||
|
|
||||||
if (bookFile.exists()) {
|
if (bookFile.exists()) {
|
||||||
val canWrite = bookFile.canWrite()
|
Log.e(TAG, "Book file exists, size: ${bookFile.length()} bytes")
|
||||||
val deleted = bookFile.delete()
|
val deleted = bookFile.delete()
|
||||||
println("Book file writable: $canWrite")
|
Log.e(TAG, "Book file deleted: $deleted")
|
||||||
println("Book file deleted: $deleted")
|
} else {
|
||||||
|
Log.e(TAG, "Book file does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val coverFile = File(context.filesDir, "cover_$bookId.jpg")
|
||||||
|
Log.e(TAG, "Cover file path: ${coverFile.absolutePath}")
|
||||||
|
|
||||||
if (coverFile.exists()) {
|
if (coverFile.exists()) {
|
||||||
val canWrite = coverFile.canWrite()
|
Log.e(TAG, "Cover file exists, size: ${coverFile.length()} bytes")
|
||||||
val deleted = coverFile.delete()
|
val deleted = coverFile.delete()
|
||||||
println("Cover file writable: $canWrite")
|
Log.e(TAG, "Cover file deleted: $deleted")
|
||||||
println("Cover file deleted: $deleted")
|
} else {
|
||||||
|
Log.e(TAG, "Cover file does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current state before deletion
|
// DataStore cleanup
|
||||||
context.dataStore.data.collect { preferences ->
|
Log.e(TAG, "Starting DataStore cleanup")
|
||||||
val currentIds = preferences[bookIdsKey]
|
try {
|
||||||
println("Current book IDs before deletion: $currentIds")
|
context.dataStore.edit { preferences ->
|
||||||
|
val currentIds = preferences[bookIdsKey]?.toMutableSet() ?: mutableSetOf()
|
||||||
|
Log.e(TAG, "Current IDs in DataStore: $currentIds")
|
||||||
|
val removed = currentIds.remove(bookId)
|
||||||
|
Log.e(TAG, "ID removed from DataStore: $removed")
|
||||||
|
preferences[bookIdsKey] = currentIds
|
||||||
|
Log.e(TAG, "Updated IDs in DataStore: $currentIds")
|
||||||
|
|
||||||
|
preferences.remove(stringPreferencesKey("title_$bookId"))
|
||||||
|
preferences.remove(stringPreferencesKey("position_$bookId"))
|
||||||
|
Log.e(TAG, "Removed related preferences for book ID: $bookId")
|
||||||
|
}
|
||||||
|
Log.e(TAG, "DataStore cleanup completed successfully")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Error during DataStore cleanup", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from preferences
|
Log.e(TAG, "🔥 DELETE BOOK COMPLETED SUCCESSFULLY 🔥")
|
||||||
context.dataStore.edit { preferences ->
|
|
||||||
val currentIds = preferences[bookIdsKey]?.toMutableSet() ?: mutableSetOf()
|
|
||||||
val removed = currentIds.remove(bookId)
|
|
||||||
preferences[bookIdsKey] = currentIds
|
|
||||||
|
|
||||||
// Clean up related preferences
|
|
||||||
preferences.remove(stringPreferencesKey("title_$bookId"))
|
|
||||||
preferences.remove(stringPreferencesKey("position_$bookId"))
|
|
||||||
|
|
||||||
println("Book ID removed from set: $removed")
|
|
||||||
println("Remaining book IDs: $currentIds")
|
|
||||||
}
|
|
||||||
|
|
||||||
println("=== Book deletion process completed ===")
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("=== Error during book deletion ===")
|
Log.e(TAG, "🔥 DELETE BOOK FAILED 🔥")
|
||||||
println("Error message: ${e.message}")
|
Log.e(TAG, "Error type: ${e.javaClass.simpleName}")
|
||||||
println("Stack trace:")
|
Log.e(TAG, "Error message: ${e.message}")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user