diff --git a/core/src/main/java/org/ireader/core/utils/Constants.kt b/core/src/main/java/org/ireader/core/utils/Constants.kt index cfd19855c..24e43e6b3 100644 --- a/core/src/main/java/org/ireader/core/utils/Constants.kt +++ b/core/src/main/java/org/ireader/core/utils/Constants.kt @@ -24,7 +24,7 @@ object Constants { const val CATALOG_REMOTE = "catalog_remote" const val UPDATE_TABLE = "updates" const val HISTORY_TABLE = "history" - const val CATEGORY_TABLE = "category_table" + const val CATEGORY_TABLE = "category" const val EXPLORE_BOOK_TABLE = "explore" @@ -38,17 +38,6 @@ object Constants { const val ARG_HIDE_BOTTOM_BAR = "ARG_HIDE_BOTTOM_BAR" - - const val NO_BOOKS_ERROR = "There is no book" - const val NO_BOOK_ERROR = "There is no book with this name" - const val NO_CHAPTER_ERROR = "There is No chapter with this name" - const val NO_CHAPTERS_ERROR = "There are no chapters with this name" - - const val CLOUDFLARE_PROTECTION_ERROR = - "Cloudflare site protection is enable, Please Open the WebView." - - const val UNKNOWN_ERROR = "Unknown Error Happened" - const val repo_url = "/repos/kazemcodes/IReader/releases/latest" const val github_api_url = "https://api.github.com" diff --git a/data/schemas/org.ireader.data.local.AppDatabase/13.json b/data/schemas/org.ireader.data.local.AppDatabase/13.json index 0ea82c56a..243f59bab 100644 --- a/data/schemas/org.ireader.data.local.AppDatabase/13.json +++ b/data/schemas/org.ireader.data.local.AppDatabase/13.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 13, - "identityHash": "8bcbb7c5073388da5a0a8fcaf4f0c940", + "identityHash": "8c1420c5d760d01a03ea739d80a6d316", "entities": [ { "tableName": "library", @@ -189,7 +189,7 @@ "foreignKeys": [] }, { - "tableName": "category_table", + "tableName": "category", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `sort` INTEGER NOT NULL, `updateInterval` INTEGER NOT NULL, `flags` INTEGER NOT NULL)", "fields": [ { @@ -524,11 +524,17 @@ }, { "tableName": "page_key_table", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `sourceId` INTEGER NOT NULL, `prevPage` INTEGER, `nextPage` INTEGER, PRIMARY KEY(`id`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `sourceId` INTEGER NOT NULL, `prevPage` INTEGER, `nextPage` INTEGER)", "fields": [ { "fieldPath": "id", "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", "affinity": "TEXT", "notNull": true }, @@ -555,7 +561,7 @@ "columnNames": [ "id" ], - "autoGenerate": false + "autoGenerate": true }, "indices": [], "foreignKeys": [] @@ -564,7 +570,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8bcbb7c5073388da5a0a8fcaf4f0c940')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8c1420c5d760d01a03ea739d80a6d316')" ] } } \ No newline at end of file diff --git a/data/src/main/java/org/ireader/data/local/dao/HistoryDao.kt b/data/src/main/java/org/ireader/data/local/dao/HistoryDao.kt index 3902a377b..ba1ad0662 100644 --- a/data/src/main/java/org/ireader/data/local/dao/HistoryDao.kt +++ b/data/src/main/java/org/ireader/data/local/dao/HistoryDao.kt @@ -22,8 +22,9 @@ interface HistoryDao { FROM history JOIN library ON history.bookId = library.id JOIN chapter ON history.chapterId = chapter.id + WHERE bookTitle LIKE '%' || :query || '%' ORDER BY history.readAt DESC""") - fun findHistoriesPaging(): kotlinx.coroutines.flow.Flow> + fun findHistoriesPaging(query: String): kotlinx.coroutines.flow.Flow> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertHistory(history: History): Long diff --git a/data/src/main/java/org/ireader/data/local/dao/LibraryBookDao.kt b/data/src/main/java/org/ireader/data/local/dao/LibraryBookDao.kt index 6ec509250..47ccfdbab 100644 --- a/data/src/main/java/org/ireader/data/local/dao/LibraryBookDao.kt +++ b/data/src/main/java/org/ireader/data/local/dao/LibraryBookDao.kt @@ -50,7 +50,7 @@ interface LibraryBookDao { desc: Boolean = false, ): Flow> - + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, MAX(history.readAt) AS max FROM library @@ -66,6 +66,7 @@ interface LibraryBookDao { """) fun subscribeLatestRead(desc: Boolean): Flow> + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, MAX(chapter.dateUpload) AS max FROM library @@ -78,6 +79,7 @@ interface LibraryBookDao { """) fun subscribeLatestChapter(desc: Boolean): Flow> + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, SUM(CASE WHEN chapter.read == 0 THEN 1 ELSE 0 END) AS unread FROM library @@ -91,6 +93,7 @@ interface LibraryBookDao { """) fun subscribeTotalChapter(desc: Boolean): Flow> + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, SUM(CASE WHEN chapter.read == 0 THEN 1 ELSE 0 END) AS unread, @@ -103,6 +106,7 @@ interface LibraryBookDao { """) suspend fun findUnreadBooks(): List + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, SUM(length(chapter.content) > 10) as total_download, @@ -115,6 +119,7 @@ interface LibraryBookDao { """) suspend fun findCompletedBooks(): List + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT library.*, SUM(CASE WHEN chapter.read == 0 THEN 1 ELSE 0 END) AS unread, diff --git a/data/src/main/java/org/ireader/data/local/dao/LibraryChapterDao.kt b/data/src/main/java/org/ireader/data/local/dao/LibraryChapterDao.kt index f32959d70..ab97b7cc2 100644 --- a/data/src/main/java/org/ireader/data/local/dao/LibraryChapterDao.kt +++ b/data/src/main/java/org/ireader/data/local/dao/LibraryChapterDao.kt @@ -19,6 +19,7 @@ interface LibraryChapterDao { chapterId: Long, ): Chapter? + @RewriteQueriesToDropUnusedColumns @Query(""" SELECT *,library.favorite FROM chapter @@ -64,22 +65,24 @@ WHERE library.favorite = 1 bookId: Int, ): PagingSource - + @RewriteQueriesToDropUnusedColumns @Query(""" - SELECT *, history.readAt as lastRead - from chapter - JOIN history ON history.bookId = chapter.bookId - GROUP BY chapterId - HAVING chapter.bookId == :bookId AND lastRead = (SELECT MAX(lastRead) FROM chapter WHERE bookId == :bookId) + SELECT * + from chapter + GROUP BY id + HAVING chapter.bookId == :bookId + ORDER BY readAt DESC LIMIT 1 """) fun subscribeLastReadChapter(bookId: Long): Flow + @RewriteQueriesToDropUnusedColumns @Query(""" - SELECT chapter.* , MAX(chapter.readAt) as lastRead + SELECT * from chapter - GROUP By chapter.id - HAVING chapter.readAt == lastRead AND chapter.bookId = :bookId + GROUP BY id + HAVING chapter.bookId == :bookId + ORDER BY readAt DESC LIMIT 1 """) suspend fun findLastReadChapter(bookId: Long): Chapter? diff --git a/data/src/main/java/org/ireader/data/local/dao/RemoteKeysDao.kt b/data/src/main/java/org/ireader/data/local/dao/RemoteKeysDao.kt index f6163cf05..c13cd0643 100644 --- a/data/src/main/java/org/ireader/data/local/dao/RemoteKeysDao.kt +++ b/data/src/main/java/org/ireader/data/local/dao/RemoteKeysDao.kt @@ -15,7 +15,12 @@ interface RemoteKeysDao { @Query("SELECT * FROM library WHERE id =:id") fun getExploreBookById(id: Int): Flow - @Query("SELECT DISTINCT library.* FROM library JOIN page_key_table ON library.title = page_key_table.id AND library.sourceId = page_key_table.sourceId OR tableId = 1 GROUP BY library.title ORDER BY id") + @Query(""" + SELECT DISTINCT library.* FROM library + JOIN page_key_table ON library.title = page_key_table.title AND library.sourceId = page_key_table.sourceId OR tableId = 1 + GROUP BY library.title + ORDER BY page_key_table.id + """) fun getAllExploreBookByPaging(): PagingSource diff --git a/data/src/main/java/org/ireader/data/repository/HistoryRepositoryImpl.kt b/data/src/main/java/org/ireader/data/repository/HistoryRepositoryImpl.kt index c4a417991..4118a5efb 100644 --- a/data/src/main/java/org/ireader/data/repository/HistoryRepositoryImpl.kt +++ b/data/src/main/java/org/ireader/data/repository/HistoryRepositoryImpl.kt @@ -18,9 +18,9 @@ class HistoryRepositoryImpl constructor(private val historyDao: HistoryDao) : Hi } @OptIn(ExperimentalCoroutinesApi::class) - override fun findHistoriesPaging(): + override fun findHistoriesPaging(query: String): Flow>> { - return historyDao.findHistoriesPaging().mapLatest { histories -> + return historyDao.findHistoriesPaging(query).mapLatest { histories -> histories.distinctBy { it.bookId }.groupBy { history -> history.date } } } diff --git a/data/src/main/java/org/ireader/data/repository/mediator/ExploreRemoteMediator.kt b/data/src/main/java/org/ireader/data/repository/mediator/ExploreRemoteMediator.kt index 165ab4874..83bf34d96 100644 --- a/data/src/main/java/org/ireader/data/repository/mediator/ExploreRemoteMediator.kt +++ b/data/src/main/java/org/ireader/data/repository/mediator/ExploreRemoteMediator.kt @@ -92,7 +92,7 @@ class ExploreRemoteMediator( } val keys = response.mangas.map { book -> RemoteKeys( - id = book.title, + title = book.title, prevPage = prevPage, nextPage = nextPage, sourceId = source.id diff --git a/domain/src/main/java/org/ireader/domain/feature_services/downloaderService/DownloaderService.kt b/domain/src/main/java/org/ireader/domain/feature_services/downloaderService/DownloaderService.kt index 767a11a60..9c3de00af 100644 --- a/domain/src/main/java/org/ireader/domain/feature_services/downloaderService/DownloaderService.kt +++ b/domain/src/main/java/org/ireader/domain/feature_services/downloaderService/DownloaderService.kt @@ -11,7 +11,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.ireader.core.R import org.ireader.domain.catalog.service.CatalogStore @@ -45,8 +44,6 @@ class DownloadService @AssistedInject constructor( ) : CoroutineWorker(context, params) { companion object { const val DOWNLOADER_SERVICE_NAME = "DOWNLOAD_SERVICE" - const val DOWNLOADER_BOOK_ID = "book_id" - const val DOWNLOADER_SOURCE_ID = "sourceId" const val DOWNLOADER_Chapters_IDS = "chapterIds" const val DOWNLOADER_BOOKS_IDS = "booksIds" } @@ -56,162 +53,161 @@ class DownloadService @AssistedInject constructor( override suspend fun doWork(): Result { - val bookId = inputData.getLong("book_id", 0) - val sourceId = inputData.getLong("sourceId", 0) + // val bookId = inputData.getLong("book_id", 0) + //val sourceId = inputData.getLong("sourceId", 0) val downloadIds = inputData.getLongArray(DOWNLOADER_Chapters_IDS)?.distinct() val booksIds = inputData.getLongArray(DOWNLOADER_BOOKS_IDS)?.distinct() - val bookResource = bookRepo.subscribeBookById(bookId).first() - ?: throw IllegalArgumentException( - "Invalid bookId as argument: $bookId" + booksIds?.forEach { bookId -> + val bookResource = bookRepo.findBookById(bookId) + ?: throw IllegalArgumentException( + "Invalid bookId as argument: $bookId" + ) + //Faking + savedDownload = SavedDownload( + bookId = bookId, + totalChapter = 100, + priority = 1, + chapterName = "", + chapterKey = "", + progress = 100, + translator = "", + chapterId = 0, + bookName = bookResource.title, + sourceId = bookResource.sourceId, ) - //Faking - savedDownload = SavedDownload( - bookId = bookId, - totalChapter = 100, - priority = 1, - chapterName = "", - chapterKey = "", - progress = 100, - translator = "", - chapterId = 0, - bookName = bookResource.title, - sourceId = bookResource.sourceId, - ) - - val source = extensions.get(sourceId)?.source - - val chapters = mutableListOf() - - if (booksIds?.isNotEmpty() == true) { - booksIds.forEach { - chapters.addAll(chapterRepo.findChaptersByBookId(it)) - } - } else { - chapters.addAll(chapterRepo.findChaptersByBookId(bookId).filter { - if (downloadIds != null) { - it.id in downloadIds - } else { - true - } - }) - } + val source = extensions.get(bookResource.sourceId)?.source - val cancelDownloadIntent = WorkManager.getInstance(applicationContext) - .createCancelPendingIntent(id) + val chapters = mutableListOf() - val builder = - NotificationCompat.Builder(applicationContext, CHANNEL_DOWNLOADER_PROGRESS).apply { - setContentTitle("Downloading ${bookResource.title}") - setSmallIcon(R.drawable.ic_downloading) - setOnlyAlertOnce(true) - priority = NotificationCompat.PRIORITY_LOW - setAutoCancel(true) - setOngoing(true) - addAction(R.drawable.baseline_close_24, "Cancel", cancelDownloadIntent) - setContentIntent(defaultNotificationHelper.openDownloadsPendingIntent) + if (downloadIds?.isEmpty() == true) { + chapters.addAll(chapterRepo.findChaptersByBookId(bookId)) + } else { + chapters.addAll(chapterRepo.findChaptersByBookId(bookId).filter { + if (downloadIds != null) { + it.id in downloadIds + } else { + true + } + }) } - NotificationManagerCompat.from(applicationContext).apply { - - builder.setProgress(chapters.size, 0, false) - notify(ID_DOWNLOAD_CHAPTER_PROGRESS, builder.build()) - try { - chapters.forEachIndexed { index, chapter -> - if (chapter.content.joinToString().length < 10) { - remoteUseCases.getRemoteReadingContent( - chapter = chapter, - source = source!!, - onSuccess = { content -> - withContext(Dispatchers.IO) { - insertUseCases.insertChapter(chapter = content) + val cancelDownloadIntent = WorkManager.getInstance(applicationContext) + .createCancelPendingIntent(id) - } - builder.setContentText(chapter.title) - builder.setSubText(index.toString()) - builder.setProgress(chapters.size, index, false) - savedDownload = savedDownload.copy( - bookId = bookId, - totalChapter = chapters.size, - priority = 1, - chapterName = chapter.title, - chapterKey = chapter.link, - progress = index, - translator = chapter.translator, - chapterId = chapter.id, - bookName = bookResource.title, - sourceId = bookResource.sourceId, - ) - notify(ID_DOWNLOAD_CHAPTER_PROGRESS, builder.build()) - withContext(Dispatchers.IO) { - downloadUseCases.insertDownload(savedDownload.copy(priority = 1)) - } + val builder = + NotificationCompat.Builder(applicationContext, CHANNEL_DOWNLOADER_PROGRESS).apply { + setContentTitle("Downloading ${bookResource.title}") + setSmallIcon(R.drawable.ic_downloading) + setOnlyAlertOnce(true) + priority = NotificationCompat.PRIORITY_LOW + setAutoCancel(true) + setOngoing(true) + addAction(R.drawable.baseline_close_24, "Cancel", cancelDownloadIntent) + setContentIntent(defaultNotificationHelper.openDownloadsPendingIntent) + } - }, - onError = { message -> - if (message?.asString(context)?.isNotBlank() == true) { - throw Exception(message.asString(context)) + NotificationManagerCompat.from(applicationContext).apply { + + builder.setProgress(chapters.size, 0, false) + notify(ID_DOWNLOAD_CHAPTER_PROGRESS, builder.build()) + try { + chapters.forEachIndexed { index, chapter -> + if (chapter.content.joinToString().length < 10) { + remoteUseCases.getRemoteReadingContent( + chapter = chapter, + source = source!!, + onSuccess = { content -> + withContext(Dispatchers.IO) { + insertUseCases.insertChapter(chapter = content) + + } + builder.setContentText(chapter.title) + builder.setSubText(index.toString()) + builder.setProgress(chapters.size, index, false) + savedDownload = savedDownload.copy( + bookId = bookId, + totalChapter = chapters.size, + priority = 1, + chapterName = chapter.title, + chapterKey = chapter.link, + progress = index, + translator = chapter.translator, + chapterId = chapter.id, + bookName = bookResource.title, + sourceId = bookResource.sourceId, + ) + notify(ID_DOWNLOAD_CHAPTER_PROGRESS, builder.build()) + withContext(Dispatchers.IO) { + downloadUseCases.insertDownload(savedDownload.copy(priority = 1)) + } + + + }, + onError = { message -> + if (message?.asString(context)?.isNotBlank() == true) { + throw Exception(message.asString(context)) + } } + ) + Timber.d("getNotifications: Successfully to downloaded ${bookResource.title} chapter ${chapter.title}") + delay(1000) + } + } + + } catch (e: Exception) { + Timber.e("getNotifications: Failed to download ${bookResource.title}") + notify( + ID_DOWNLOAD_CHAPTER_ERROR, + NotificationCompat.Builder(applicationContext, + Notifications.CHANNEL_DOWNLOADER_ERROR).apply { + if (e.localizedMessage == "Job was cancelled") { + setSubText("Download was cancelled") + setContentTitle("Download of ${bookResource.title} was canceled.") + } else { + setContentTitle("Failed to download ${bookResource.title}") + setSubText(e.localizedMessage) } - ) - Timber.d("getNotifications: Successfully to downloaded ${bookResource.title} chapter ${chapter.title}") - delay(1000) + setSmallIcon(R.drawable.ic_downloading) + priority = NotificationCompat.PRIORITY_DEFAULT + setAutoCancel(true) + setContentIntent(defaultNotificationHelper.openBookDetailPendingIntent( + bookId, + bookResource.sourceId)) + }.build() + ) + builder.setProgress(0, 0, false) + cancel(ID_DOWNLOAD_CHAPTER_PROGRESS) + withContext(Dispatchers.IO) { + downloadUseCases.insertDownload(savedDownload.copy(priority = 0)) } + return Result.failure() } - } catch (e: Exception) { - Timber.e("getNotifications: Failed to download ${bookResource.title}") + builder.setProgress(0, 0, false) + cancel(ID_DOWNLOAD_CHAPTER_PROGRESS) + withContext(Dispatchers.IO) { + downloadUseCases.insertDownload(savedDownload.copy(priority = 0)) + } notify( - ID_DOWNLOAD_CHAPTER_ERROR, + ID_DOWNLOAD_CHAPTER_COMPLETE, NotificationCompat.Builder(applicationContext, - Notifications.CHANNEL_DOWNLOADER_ERROR).apply { - if (e.localizedMessage == "Job was cancelled") { - setSubText("Download was cancelled") - setContentTitle("Download of ${bookResource.title} was canceled.") - } else { - setContentTitle("Failed to download ${bookResource.title}") - setSubText(e.localizedMessage) - } + Notifications.CHANNEL_DOWNLOADER_COMPLETE).apply { + setContentTitle("${bookResource.title} downloaded") setSmallIcon(R.drawable.ic_downloading) priority = NotificationCompat.PRIORITY_DEFAULT + setSubText("It was Downloaded Successfully") setAutoCancel(true) setContentIntent(defaultNotificationHelper.openBookDetailPendingIntent( bookId, - sourceId)) + bookResource.sourceId)) }.build() ) - builder.setProgress(0, 0, false) - cancel(ID_DOWNLOAD_CHAPTER_PROGRESS) - withContext(Dispatchers.IO) { - downloadUseCases.insertDownload(savedDownload.copy(priority = 0)) - } - return Result.failure() } - builder.setProgress(0, 0, false) - cancel(ID_DOWNLOAD_CHAPTER_PROGRESS) - withContext(Dispatchers.IO) { - downloadUseCases.insertDownload(savedDownload.copy(priority = 0)) - } - notify( - ID_DOWNLOAD_CHAPTER_COMPLETE, - NotificationCompat.Builder(applicationContext, - Notifications.CHANNEL_DOWNLOADER_COMPLETE).apply { - setContentTitle("${bookResource.title} downloaded") - setSmallIcon(R.drawable.ic_downloading) - priority = NotificationCompat.PRIORITY_DEFAULT - setSubText("It was Downloaded Successfully") - setAutoCancel(true) - setContentIntent(defaultNotificationHelper.openBookDetailPendingIntent(bookId, - sourceId)) - }.build() - ) } - return Result.success() } - - -} \ No newline at end of file +} diff --git a/domain/src/main/java/org/ireader/domain/feature_services/updater_service/UpdateService.kt b/domain/src/main/java/org/ireader/domain/feature_services/updater_service/UpdateService.kt index a1ab67e44..adc244253 100644 --- a/domain/src/main/java/org/ireader/domain/feature_services/updater_service/UpdateService.kt +++ b/domain/src/main/java/org/ireader/domain/feature_services/updater_service/UpdateService.kt @@ -20,7 +20,8 @@ import org.ireader.domain.feature_services.updater_service.models.Version import org.ireader.domain.use_cases.preferences.services.LastUpdateTime import org.ireader.infinity.feature_services.flags import java.util.* -import java.util.concurrent.TimeUnit +import kotlin.time.DurationUnit +import kotlin.time.toDuration @HiltWorker class UpdateService @AssistedInject constructor( @@ -33,10 +34,9 @@ class UpdateService @AssistedInject constructor( override suspend fun doWork(): Result { val last = lastUpdateTime.read() - val time = lastUpdateTime.read() + TimeUnit.DAYS.toMillis(1) - val oneDay = TimeUnit.DAYS.toMillis(1) + val time = lastUpdateTime.read() + 1.toDuration(DurationUnit.HOURS).inWholeMilliseconds - if (last > (last + oneDay)) { + if (last < time) { return Result.success() } diff --git a/domain/src/main/java/org/ireader/domain/models/RemoteKeys.kt b/domain/src/main/java/org/ireader/domain/models/RemoteKeys.kt index 1968812fc..e2ca5dda4 100644 --- a/domain/src/main/java/org/ireader/domain/models/RemoteKeys.kt +++ b/domain/src/main/java/org/ireader/domain/models/RemoteKeys.kt @@ -6,8 +6,9 @@ import org.ireader.core.utils.Constants @Entity(tableName = Constants.PAGE_KET_TABLE) data class RemoteKeys( - @PrimaryKey(autoGenerate = false) - val id: String, + @PrimaryKey(autoGenerate = true) + val id: Long = 0, + val title: String, val sourceId: Long, val prevPage: Int?, val nextPage: Int?, diff --git a/domain/src/main/java/org/ireader/domain/models/entities/Book.kt b/domain/src/main/java/org/ireader/domain/models/entities/Book.kt index 4e4977986..1959adee1 100644 --- a/domain/src/main/java/org/ireader/domain/models/entities/Book.kt +++ b/domain/src/main/java/org/ireader/domain/models/entities/Book.kt @@ -81,7 +81,7 @@ fun updateBook(newBook: Book, oldBook: Book): Book { ) } -fun MangaInfo.toBook(sourceId: Long, tableId: Long = 0): Book { +fun MangaInfo.toBook(sourceId: Long, tableId: Long = 0, lastUpdated: Long = 0): Book { return Book( id = 0, sourceId = sourceId, @@ -90,7 +90,7 @@ fun MangaInfo.toBook(sourceId: Long, tableId: Long = 0): Book { flags = 0, link = this.key, dataAdded = 0L, - lastUpdated = 0L, + lastUpdated = lastUpdated, favorite = false, title = this.title, status = this.status, diff --git a/domain/src/main/java/org/ireader/domain/repository/HistoryRepository.kt b/domain/src/main/java/org/ireader/domain/repository/HistoryRepository.kt index f58f4dd72..d75f50be6 100644 --- a/domain/src/main/java/org/ireader/domain/repository/HistoryRepository.kt +++ b/domain/src/main/java/org/ireader/domain/repository/HistoryRepository.kt @@ -9,7 +9,7 @@ interface HistoryRepository { suspend fun findHistoryByBookId(bookId: Long): History? - fun findHistoriesPaging(): Flow>> + fun findHistoriesPaging(query: String): Flow>> suspend fun findHistories(): List diff --git a/domain/src/main/java/org/ireader/domain/use_cases/history/HistoryUseCase.kt b/domain/src/main/java/org/ireader/domain/use_cases/history/HistoryUseCase.kt index b788f32f4..f4de89dec 100644 --- a/domain/src/main/java/org/ireader/domain/use_cases/history/HistoryUseCase.kt +++ b/domain/src/main/java/org/ireader/domain/use_cases/history/HistoryUseCase.kt @@ -17,8 +17,8 @@ class HistoryUseCase @Inject constructor(private val historyRepository: HistoryR return historyRepository.findHistoryByBookId(bookId) } - override fun findHistoriesPaging(): Flow>> { - return historyRepository.findHistoriesPaging() + override fun findHistoriesPaging(query: String): Flow>> { + return historyRepository.findHistoriesPaging(query) } override suspend fun findHistories(): List { diff --git a/domain/src/main/java/org/ireader/domain/use_cases/local/book_usecases/SubscribeInLibraryBooksPagingData.kt b/domain/src/main/java/org/ireader/domain/use_cases/local/book_usecases/SubscribeInLibraryBooksPagingData.kt index 901281976..4090ea22a 100644 --- a/domain/src/main/java/org/ireader/domain/use_cases/local/book_usecases/SubscribeInLibraryBooksPagingData.kt +++ b/domain/src/main/java/org/ireader/domain/use_cases/local/book_usecases/SubscribeInLibraryBooksPagingData.kt @@ -30,17 +30,14 @@ class SubscribeInLibraryBooks @Inject constructor(private val localBookRepositor val filteredBooks = mutableListOf() withContext(Dispatchers.IO) { - when { - filter.contains(FilterType.Unread) -> { - filteredBooks.addAll(localBookRepository.findUnreadBooks()) - } - filter.contains(FilterType.Downloaded) -> { - filteredBooks.addAll(localBookRepository.findCompletedBooks()) - } - filter.contains(FilterType.Completed) -> { - filteredBooks.addAll(localBookRepository.findDownloadedBooks()) - } - else -> {} + if (filter.contains(FilterType.Unread)) { + filteredBooks.addAll(localBookRepository.findUnreadBooks()) + } + if (filter.contains(FilterType.Downloaded)) { + filteredBooks.addAll(localBookRepository.findCompletedBooks()) + } + if (filter.contains(FilterType.Completed)) { + filteredBooks.addAll(localBookRepository.findDownloadedBooks()) } } emit(books.filter { book -> diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index 2120e3256..cecaa6985 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("com.android.library") id("kotlin-android") id("kotlin-kapt") + id("kotlinx-serialization") } android { diff --git a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/book_detail/viewmodel/BookDetailViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/book_detail/viewmodel/BookDetailViewModel.kt index cf5ef7a8e..74f4e1058 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/book_detail/viewmodel/BookDetailViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/book_detail/viewmodel/BookDetailViewModel.kt @@ -18,9 +18,7 @@ import org.ireader.core.utils.removeSameItemsFromList import org.ireader.core_ui.viewmodel.BaseViewModel import org.ireader.domain.catalog.interactor.GetLocalCatalog import org.ireader.domain.feature_services.downloaderService.DownloadService -import org.ireader.domain.feature_services.downloaderService.DownloadService.Companion.DOWNLOADER_BOOK_ID import org.ireader.domain.feature_services.downloaderService.DownloadService.Companion.DOWNLOADER_SERVICE_NAME -import org.ireader.domain.feature_services.downloaderService.DownloadService.Companion.DOWNLOADER_SOURCE_ID import org.ireader.domain.models.entities.Book import org.ireader.domain.models.entities.Chapter import org.ireader.domain.models.entities.updateBook @@ -264,8 +262,8 @@ class BookDetailViewModel @Inject constructor( work = OneTimeWorkRequestBuilder().apply { setInputData( Data.Builder().apply { - putLong(DOWNLOADER_BOOK_ID, book.id) - putLong(DOWNLOADER_SOURCE_ID, book.sourceId) + + putLongArray(DownloadService.DOWNLOADER_BOOKS_IDS, longArrayOf(book.id)) }.build() ) addTag(DOWNLOADER_SERVICE_NAME) diff --git a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/ChapterDetailScreen.kt b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/ChapterDetailScreen.kt index de53e425b..a540994d8 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/ChapterDetailScreen.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/ChapterDetailScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -58,6 +59,11 @@ fun ChapterDetailScreen( // LaunchedEffect(key1 = true) { // vm.book?.let { vm.getLocalBookById(it.id) } // } + LaunchedEffect(key1 = true) { + vm.book?.let { book -> + vm.getLastReadChapter(book) + } + } Scaffold( modifier = Modifier.systemBarsPadding(), topBar = { diff --git a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/viewmodel/ChapterDetailViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/viewmodel/ChapterDetailViewModel.kt index 9508375e5..dfcd27bc6 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/viewmodel/ChapterDetailViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_detail/presentation/chapter_detail/viewmodel/ChapterDetailViewModel.kt @@ -66,8 +66,18 @@ class ChapterDetailViewModel @Inject constructor( } } - suspend fun getLastReadChapter(book: Book) { - lastRead = getChapterUseCase.findLastReadChapter(book.id)?.id + fun getLastReadChapter(book: Book) { + viewModelScope.launch { + lastRead = getChapterUseCase.findLastReadChapter(book.id)?.id +// getChapterUseCase.subscribeLastReadChapter(book.id) +// .collect { +// it?.let { chapter -> +// lastRead = chapter.id +// } +// } + } + + // lastRead = getChapterUseCase.findLastReadChapter(book.id)?.id } fun reverseChapterInDB() { @@ -146,12 +156,9 @@ class ChapterDetailViewModel @Inject constructor( OneTimeWorkRequestBuilder().apply { setInputData( Data.Builder().apply { - putLong(DownloadService.DOWNLOADER_BOOK_ID, - book.id) - putLong(DownloadService.DOWNLOADER_SOURCE_ID, - book.sourceId) putLongArray(DOWNLOADER_Chapters_IDS, this@ChapterDetailViewModel.selection.toLongArray()) + putLongArray(DownloadService.DOWNLOADER_BOOKS_IDS, longArrayOf(book.id)) }.build() ) addTag(DownloadService.DOWNLOADER_SERVICE_NAME) diff --git a/presentation/src/main/java/org/ireader/presentation/feature_history/HistoryTopAppBar.kt b/presentation/src/main/java/org/ireader/presentation/feature_history/HistoryTopAppBar.kt index 9b9ec8f3f..361cd924d 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_history/HistoryTopAppBar.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_history/HistoryTopAppBar.kt @@ -31,6 +31,7 @@ fun HistoryTopAppBar( query = vm.searchQuery, onValueChange = { vm.searchQuery = it + vm.getHistoryBooks() }, onConfirm = { focusManager.clearFocus() @@ -48,6 +49,8 @@ fun HistoryTopAppBar( title = "Close", onClick = { vm.searchMode = false + vm.searchQuery = "" + vm.getHistoryBooks() }, ) } diff --git a/presentation/src/main/java/org/ireader/presentation/feature_history/viewmodel/HistoryViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_history/viewmodel/HistoryViewModel.kt index 232221084..aff9c9fd1 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_history/viewmodel/HistoryViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_history/viewmodel/HistoryViewModel.kt @@ -18,9 +18,9 @@ class HistoryViewModel @Inject constructor( - private fun getHistoryBooks() { + fun getHistoryBooks() { viewModelScope.launch { - historyUseCase.findHistoriesPaging().collect { histories -> + historyUseCase.findHistoriesPaging(searchQuery).collect { histories -> history = histories } } diff --git a/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/LibraryScreen.kt b/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/LibraryScreen.kt index fd882c013..a052fb3c1 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/LibraryScreen.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/LibraryScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.DoneOutline +import androidx.compose.material.icons.filled.GetApp import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope @@ -153,6 +154,12 @@ fun LibraryScreen( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { + AppIconButton(imageVector = Icons.Default.GetApp, + title = "Download", + onClick = { + vm.downloadChapters(context) + // vm.selection.clear() + }) AppIconButton(imageVector = Icons.Default.Done, title = "Mark as read", onClick = { diff --git a/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/viewmodel/LibraryViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/viewmodel/LibraryViewModel.kt index 957950d85..d18e4b69d 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/viewmodel/LibraryViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_library/presentation/viewmodel/LibraryViewModel.kt @@ -3,10 +3,7 @@ package org.ireader.presentation.feature_library.presentation.viewmodel import android.content.Context import androidx.lifecycle.viewModelScope -import androidx.work.ExistingWorkPolicy -import androidx.work.OneTimeWorkRequest -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkManager +import androidx.work.* import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -14,6 +11,8 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import org.ireader.core_ui.viewmodel.BaseViewModel import org.ireader.domain.feature_services.LibraryUpdatesService +import org.ireader.domain.feature_services.downloaderService.DownloadService +import org.ireader.domain.feature_services.downloaderService.DownloadService.Companion.DOWNLOADER_BOOKS_IDS import org.ireader.domain.models.DisplayMode import org.ireader.domain.models.FilterType import org.ireader.domain.models.SortType @@ -113,29 +112,28 @@ class LibraryViewModel @Inject constructor( this.layout = layoutType.layout } -// lateinit var downloadWork: OneTimeWorkRequest -// fun downloadChapters(book: List,context: Context) { -// downloadWork = -// OneTimeWorkRequestBuilder().apply { -// setInputData( -// Data.Builder().apply { -// putLong(DownloadService.DOWNLOADER_BOOK_ID, -// book.id) -// putLong(DownloadService.DOWNLOADER_SOURCE_ID, -// book.sourceId) -// }.build() -// ) -// addTag(DownloadService.DOWNLOADER_SERVICE_NAME) -// }.build() -// WorkManager.getInstance(context).enqueueUniqueWork( -// DownloadService.DOWNLOADER_SERVICE_NAME.plus( -// book.id + book.sourceId), -// ExistingWorkPolicy.REPLACE, -// downloadWork -// ) -// -// -// } + lateinit var downloadWork: OneTimeWorkRequest + fun downloadChapters(context: Context) { + downloadWork = + OneTimeWorkRequestBuilder().apply { + setInputData( + Data.Builder().apply { + + putLongArray(DOWNLOADER_BOOKS_IDS, selection.toLongArray()) + }.build() + ) + addTag(DownloadService.DOWNLOADER_SERVICE_NAME) + }.build() + WorkManager.getInstance(context).enqueueUniqueWork( + DownloadService.DOWNLOADER_SERVICE_NAME.plus( + "Group_Download"), + ExistingWorkPolicy.REPLACE, + downloadWork + ) + selection.clear() + + + } fun markAsRead() { viewModelScope.launch(Dispatchers.IO) { @@ -164,6 +162,7 @@ class LibraryViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { selection.forEach { bookId -> deleteUseCase.deleteBookById(bookId) + deleteUseCase.deleteChaptersByBookId(bookId) } selection.clear() } diff --git a/presentation/src/main/java/org/ireader/presentation/feature_reader/presentation/reader/viewmodel/ReaderScreenViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_reader/presentation/reader/viewmodel/ReaderScreenViewModel.kt index 3aa82b043..620e6dda4 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_reader/presentation/reader/viewmodel/ReaderScreenViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_reader/presentation/reader/viewmodel/ReaderScreenViewModel.kt @@ -18,6 +18,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import kotlinx.datetime.Clock import org.ireader.core.utils.* import org.ireader.core_ui.theme.OrientationMode import org.ireader.core_ui.theme.fonts @@ -138,7 +139,9 @@ class ReaderScreenViewModel @Inject constructor( clearError() this@ReaderScreenViewModel.toggleLoading(false) toggleLocalLoaded(true) - setChapter(resultChapter.copy(content = resultChapter.content)) + setChapter(resultChapter.copy(content = resultChapter.content, + read = true, + readAt = Clock.System.now().toEpochMilliseconds())) val chapter = state.stateChapter if ( chapter != null && @@ -176,7 +179,10 @@ class ReaderScreenViewModel @Inject constructor( source = source, onSuccess = { content -> if (content != null) { - insertChapter(content) + insertChapter(content.copy( + dateFetch = Clock.System.now() + .toEpochMilliseconds(), + )) setChapter(content) toggleLoading(false) toggleRemoteLoading(false) @@ -241,7 +247,8 @@ class ReaderScreenViewModel @Inject constructor( private fun updateLastReadTime(chapter: Chapter) { viewModelScope.launch(Dispatchers.IO) { insertUseCases.insertChapter( - chapter = chapter.copy(read = true) + chapter = chapter.copy(read = true, + readAt = Clock.System.now().toEpochMilliseconds()) ) historyUseCase.insertHistory(History( bookId = chapter.bookId, @@ -604,9 +611,9 @@ class ReaderScreenViewModel @Inject constructor( layoutParams.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED window.attributes = layoutParams - stateChapter?.let { + stateChapter?.let { chapter -> activity.lifecycleScope.launch { - insertChapter(it.copy(progress = scrollState.firstVisibleItemScrollOffset)) + insertChapter(chapter.copy(progress = scrollState.firstVisibleItemScrollOffset)) } } } @@ -644,7 +651,7 @@ class ReaderScreenViewModel @Inject constructor( insertUseCases.insertBook(book) } - suspend fun insertChapter(chapter: Chapter) { + private suspend fun insertChapter(chapter: Chapter) { withIOContext { insertUseCases.insertChapter(chapter) } diff --git a/presentation/src/main/java/org/ireader/presentation/feature_settings/presentation/setting/downloader/DownloaderViewModel.kt b/presentation/src/main/java/org/ireader/presentation/feature_settings/presentation/setting/downloader/DownloaderViewModel.kt index 1bc128354..56bc0c647 100644 --- a/presentation/src/main/java/org/ireader/presentation/feature_settings/presentation/setting/downloader/DownloaderViewModel.kt +++ b/presentation/src/main/java/org/ireader/presentation/feature_settings/presentation/setting/downloader/DownloaderViewModel.kt @@ -89,10 +89,8 @@ class DownloaderViewModel @Inject constructor( OneTimeWorkRequestBuilder().apply { setInputData( Data.Builder().apply { - putLong(DownloadService.DOWNLOADER_BOOK_ID, - bookId) - putLong(DownloadService.DOWNLOADER_SOURCE_ID, - sourceId) + + putLongArray(DownloadService.DOWNLOADER_BOOKS_IDS, longArrayOf(bookId)) }.build() ) addTag(DownloadService.DOWNLOADER_SERVICE_NAME) @@ -111,10 +109,7 @@ class DownloaderViewModel @Inject constructor( OneTimeWorkRequestBuilder().apply { setInputData( Data.Builder().apply { - putLong(DownloadService.DOWNLOADER_BOOK_ID, - bookId) - putLong(DownloadService.DOWNLOADER_SOURCE_ID, - sourceId) + putLongArray(DownloadService.DOWNLOADER_BOOKS_IDS, longArrayOf(bookId)) }.build() ) }.build() diff --git a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/BookImage.kt b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/BookImage.kt index e59f446e2..8d9363ae3 100644 --- a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/BookImage.kt +++ b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/BookImage.kt @@ -83,4 +83,5 @@ fun BookImage( } badge() } + } \ No newline at end of file diff --git a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/CompactGrid.kt b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/CompactGrid.kt index 8603c1477..6930f9af8 100644 --- a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/CompactGrid.kt +++ b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/CompactGrid.kt @@ -47,6 +47,9 @@ fun CompactGridLayoutComposable( if (isLocal && histories.find { it.bookId == book.id }?.readAt != 0L) { GoToLastReadComposable(onClick = { goToLatestChapter(book) }) } + if (!isLocal && book.favorite) { + TextBadge(text = "in Library") + } } } @@ -63,6 +66,9 @@ fun CompactGridLayoutComposable( if (isLocal && histories.find { it.bookId == books[index].id }?.readAt != 0L) { GoToLastReadComposable(onClick = { goToLatestChapter(books[index]) }) } + if (!isLocal && books[index].favorite) { + TextBadge(text = "in Library") + } } } } diff --git a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GoToLastReadComposable.kt b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GoToLastReadComposable.kt index 3237059fb..19a2b6af1 100644 --- a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GoToLastReadComposable.kt +++ b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GoToLastReadComposable.kt @@ -1,6 +1,7 @@ package org.ireader.presentation.presentation.layouts import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding @@ -12,9 +13,13 @@ import androidx.compose.material.OutlinedButton import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ImportContacts import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import org.ireader.presentation.presentation.reusable_composable.AppIconButton +import org.ireader.presentation.presentation.reusable_composable.SuperSmallTextComposable @Composable fun GoToLastReadComposable(onClick: () -> Unit) { @@ -43,4 +48,20 @@ fun GoToLastReadComposable(onClick: () -> Unit) { } } +} + +@Composable +fun TextBadge(modifier: Modifier = Modifier, text: String) { + Box( + modifier = Modifier + .padding(5.dp) + .size(width = 60.dp, height = 20.dp) + .background(MaterialTheme.colors.primary), + contentAlignment = Alignment.Center, + ) { + SuperSmallTextComposable(text = text, + color = Color.White, + maxLine = 1, + overflow = TextOverflow.Ellipsis) + } } \ No newline at end of file diff --git a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GridLayoutComposable.kt b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GridLayoutComposable.kt index abf4418bb..7363d9509 100644 --- a/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GridLayoutComposable.kt +++ b/presentation/src/main/java/org/ireader/presentation/presentation/layouts/GridLayoutComposable.kt @@ -43,6 +43,9 @@ fun GridLayoutComposable( if (book.lastUpdated > 1 && isLocal && histories.find { it.bookId == book.id }?.readAt != 0L) { GoToLastReadComposable(onClick = { goToLatestChapter(book) }) } + if (!isLocal && book.favorite) { + TextBadge(text = "in Library") + } } } } @@ -56,6 +59,9 @@ fun GridLayoutComposable( if (books[index].lastUpdated > 1 && isLocal && histories.find { it.bookId == books[index].id }?.readAt != 0L) { GoToLastReadComposable(onClick = { goToLatestChapter(books[index]) }) } + if (!isLocal && books[index].favorite) { + TextBadge(text = "in Library") + } } } } diff --git a/presentation/src/main/java/org/ireader/presentation/presentation/reusable_composable/TopAppBarReusableComposables.kt b/presentation/src/main/java/org/ireader/presentation/presentation/reusable_composable/TopAppBarReusableComposables.kt index 8c95aaf54..678be6d77 100644 --- a/presentation/src/main/java/org/ireader/presentation/presentation/reusable_composable/TopAppBarReusableComposables.kt +++ b/presentation/src/main/java/org/ireader/presentation/presentation/reusable_composable/TopAppBarReusableComposables.kt @@ -209,7 +209,7 @@ fun AppTextField( Box(contentAlignment = Alignment.CenterStart) { if (query.isBlank() && mode != 2) { Text( - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier.padding(horizontal = 0.dp), text = hint, style = MaterialTheme.typography.subtitle1, color = MaterialTheme.colors.onBackground.copy(alpha = .7F)