From 9854c2d845cd9813be5fe9b60e10f12976dd2f64 Mon Sep 17 00:00:00 2001 From: Acclorite <140836141+Acclorite@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:03:01 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20BookRepository=20reform?= =?UTF-8?q?at?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Split into multiple smaller repositories * Reformatted code Co-authored-by: Ridho Pratama --- .../book_story/data/di/RepositoryModule.kt | 48 +++ .../data/repository/BookRepositoryImpl.kt | 397 +----------------- .../repository/ColorPresetRepositoryImpl.kt | 81 ++++ .../repository/DataStoreRepositoryImpl.kt | 65 +++ .../FavoriteDirectoryRepositoryImpl.kt | 35 ++ .../repository/FileSystemRepositoryImpl.kt | 182 ++++++++ .../data/repository/HistoryRepositoryImpl.kt | 79 ++++ .../data/repository/RemoteRepositoryImpl.kt | 59 +++ .../domain/repository/BookRepository.kt | 87 ---- .../repository/ColorPresetRepository.kt | 24 ++ .../domain/repository/DataStoreRepository.kt | 14 + .../repository/FavoriteDirectoryRepository.kt | 6 + .../domain/repository/FileSystemRepository.kt | 16 + .../domain/repository/HistoryRepository.kt | 26 ++ .../domain/repository/RemoteRepository.kt | 10 + .../use_case/book/CheckForTextUpdate.kt | 4 +- .../domain/use_case/book/DeleteBooks.kt | 10 +- .../domain/use_case/book/GetBookById.kt | 4 +- .../domain/use_case/book/GetBooks.kt | 4 +- .../domain/use_case/book/GetBooksById.kt | 4 +- .../domain/use_case/book/GetText.kt | 4 +- .../domain/use_case/book/InsertBook.kt | 5 +- .../domain/use_case/book/UpdateBook.kt | 4 +- .../use_case/book/UpdateBookWithText.kt | 4 +- .../use_case/book/UpdateCoverImageOfBook.kt | 4 +- .../color_preset/DeleteColorPreset.kt | 6 +- .../use_case/color_preset/GetColorPresets.kt | 6 +- .../color_preset/ReorderColorPresets.kt | 6 +- .../color_preset/SelectColorPreset.kt | 6 +- .../color_preset/UpdateColorPreset.kt | 6 +- .../{common => data_store}/ChangeLanguage.kt | 8 +- .../use_case/data_store/GetAllSettings.kt | 4 +- .../use_case/data_store/SetDatastore.kt | 6 +- .../UpdateFavoriteDirectory.kt | 7 +- .../use_case/file_system/GetBookFromFile.kt | 4 +- .../file_system/GetFilesFromDevice.kt | 4 +- .../domain/use_case/history/DeleteHistory.kt | 6 +- .../use_case/history/DeleteWholeHistory.kt | 6 +- .../domain/use_case/history/GetHistory.kt | 6 +- .../use_case/history/GetLatestHistory.kt | 6 +- .../domain/use_case/history/InsertHistory.kt | 7 +- .../domain/use_case/remote/CheckForUpdates.kt | 6 +- .../presentation/data/MainViewModel.kt | 2 +- 43 files changed, 755 insertions(+), 523 deletions(-) create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/FavoriteDirectoryRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/HistoryRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/data/repository/RemoteRepositoryImpl.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/ColorPresetRepository.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/FavoriteDirectoryRepository.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/HistoryRepository.kt create mode 100644 app/src/main/java/ua/acclorite/book_story/domain/repository/RemoteRepository.kt rename app/src/main/java/ua/acclorite/book_story/domain/use_case/{common => data_store}/ChangeLanguage.kt (68%) diff --git a/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt b/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt index 71f89f64..5e1321f5 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/di/RepositoryModule.kt @@ -19,7 +19,19 @@ import ua.acclorite.book_story.data.parser.FileParserImpl import ua.acclorite.book_story.data.parser.TextParser import ua.acclorite.book_story.data.parser.TextParserImpl import ua.acclorite.book_story.data.repository.BookRepositoryImpl +import ua.acclorite.book_story.data.repository.ColorPresetRepositoryImpl +import ua.acclorite.book_story.data.repository.DataStoreRepositoryImpl +import ua.acclorite.book_story.data.repository.FavoriteDirectoryRepositoryImpl +import ua.acclorite.book_story.data.repository.FileSystemRepositoryImpl +import ua.acclorite.book_story.data.repository.HistoryRepositoryImpl +import ua.acclorite.book_story.data.repository.RemoteRepositoryImpl import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository +import ua.acclorite.book_story.domain.repository.DataStoreRepository +import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository +import ua.acclorite.book_story.domain.repository.FileSystemRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository +import ua.acclorite.book_story.domain.repository.RemoteRepository import javax.inject.Singleton @Module @@ -37,6 +49,42 @@ abstract class RepositoryModule { bookRepositoryImpl: BookRepositoryImpl ): BookRepository + @Binds + @Singleton + abstract fun bindHistoryRepository( + historyRepositoryImpl: HistoryRepositoryImpl + ): HistoryRepository + + @Binds + @Singleton + abstract fun bindColorPresetRepository( + colorPresetRepositoryImpl: ColorPresetRepositoryImpl + ): ColorPresetRepository + + @Binds + @Singleton + abstract fun bindDataStoreRepository( + dataStoreRepositoryImpl: DataStoreRepositoryImpl + ): DataStoreRepository + + @Binds + @Singleton + abstract fun bindFileSystemRepository( + fileSystemRepositoryImpl: FileSystemRepositoryImpl + ): FileSystemRepository + + @Binds + @Singleton + abstract fun bindRemoteRepository( + remoteRepositoryImpl: RemoteRepositoryImpl + ): RemoteRepository + + @Binds + @Singleton + abstract fun bindFavoriteDirectoryRepository( + favoriteDirectoryRepositoryImpl: FavoriteDirectoryRepositoryImpl + ): FavoriteDirectoryRepository + @Binds @Singleton abstract fun bindBookMapper( diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt index cb473685..7f7db758 100644 --- a/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/BookRepositoryImpl.kt @@ -4,44 +4,26 @@ import android.app.Application import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri -import android.os.Environment import android.provider.MediaStore import android.util.Log import androidx.compose.ui.text.AnnotatedString -import androidx.datastore.preferences.core.Preferences -import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll import kotlinx.coroutines.withContext import kotlinx.coroutines.yield import ua.acclorite.book_story.R -import ua.acclorite.book_story.data.local.data_store.DataStore -import ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity -import ua.acclorite.book_story.data.local.notification.UpdatesNotificationService import ua.acclorite.book_story.data.local.room.BookDao import ua.acclorite.book_story.data.mapper.book.BookMapper -import ua.acclorite.book_story.data.mapper.color_preset.ColorPresetMapper -import ua.acclorite.book_story.data.mapper.history.HistoryMapper import ua.acclorite.book_story.data.parser.FileParser import ua.acclorite.book_story.data.parser.MarkdownParser import ua.acclorite.book_story.data.parser.TextParser -import ua.acclorite.book_story.data.remote.GithubAPI -import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.BookWithText import ua.acclorite.book_story.domain.model.BookWithTextAndCover import ua.acclorite.book_story.domain.model.Chapter -import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.model.NullableBook -import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.util.CoverImage import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.UIText -import ua.acclorite.book_story.presentation.core.constants.Constants -import ua.acclorite.book_story.presentation.data.MainState import java.io.BufferedReader import java.io.ByteArrayOutputStream import java.io.File @@ -51,33 +33,23 @@ import java.util.UUID import javax.inject.Inject import javax.inject.Singleton -private const val GET_BOOK_FROM_FILE = "GET BOOK FROM FILE, REPOSITORY" -private const val GET_TEXT = "GET TEXT, REPOSITORY" -private const val GET_BOOKS = "GET BOOKS, REPOSITORY" -private const val GET_BOOKS_BY_ID = "GET BOOKS, REPOSITORY" -private const val INSERT_BOOK = "INSERT BOOK, REPOSITORY" -private const val UPDATE_BOOK = "UPDATE BOOK, REPOSITORY" -private const val DELETE_BOOKS = "DELETE BOOKS, REPOSITORY" -private const val CAN_RESET_COVER = "CAN RESET COVER, REPOSITORY" -private const val RESET_COVER = "RESET COVER, REPOSITORY" -private const val GET_ALL_SETTINGS = "GET ALL SETTINGS, REPOSITORY" -private const val GET_FILES_FROM_DEVICE = "GET FILES FROM DEVICE, REPOSITORY" -private const val CHECK_FOR_UPDATES = "CHECK FOR UPDATES, REPOSITORY" -private const val CHECK_FOR_TEXT_UPDATE = "CHECK FOR TEXT UPDATE, REPOSITORY" +private const val GET_TEXT = "GET TEXT, REPO" +private const val GET_BOOKS = "GET BOOKS, REPO" +private const val GET_BOOKS_BY_ID = "GET BOOKS, REPO" +private const val INSERT_BOOK = "INSERT BOOK, REPO" +private const val UPDATE_BOOK = "UPDATE BOOK, REPO" +private const val DELETE_BOOKS = "DELETE BOOKS, REPO" +private const val CAN_RESET_COVER = "CAN RESET COVER, REPO" +private const val RESET_COVER = "RESET COVER, REPO" +private const val CHECK_FOR_TEXT_UPDATE = "CHECK TEXT UPD, REPO" @Suppress("DEPRECATION") @Singleton class BookRepositoryImpl @Inject constructor( private val application: Application, private val database: BookDao, - private val dataStore: DataStore, - - private val githubAPI: GithubAPI, - private val updatesNotificationService: UpdatesNotificationService, private val bookMapper: BookMapper, - private val historyMapper: HistoryMapper, - private val colorPresetMapper: ColorPresetMapper, private val fileParser: FileParser, private val textParser: TextParser, @@ -610,355 +582,4 @@ class BookRepositoryImpl @Inject constructor( Log.i(RESET_COVER, "Successfully reset cover image.") return true } - - /** - * Puts DataStore constant to [DataStore]. - */ - override suspend fun putDataToDataStore(key: Preferences.Key, value: T) { - dataStore.putData(key, value) - } - - /** - * Gets all settings from DataStore and returns [MainState]. - */ - override suspend fun getAllSettings(): MainState { - Log.i(GET_ALL_SETTINGS, "Getting all settings.") - val result = CompletableDeferred() - - withContext(Dispatchers.Default) { - val keys = dataStore.getAllData() - val data = mutableMapOf() - - Log.i(GET_ALL_SETTINGS, "Got ${keys?.size} settings keys.") - - val jobs = keys?.map { key -> - async { - val nullableData = dataStore.getNullableData(key) - - if (nullableData == null) { - data.remove(key.name) - } else { - data[key.name] = nullableData - } - } - } - jobs?.awaitAll() - - result.complete(MainState.initialize(data)) - } - - return result.await() - } - - /** - * Get all matching files from device. - * Filters by [query] and sorts out not supported file formats and already added files. - */ - override suspend fun getFilesFromDevice(query: String): List { - Log.i(GET_FILES_FROM_DEVICE, "Getting files from device by query: \"$query\".") - - val existingBooks = database - .searchBooks("") - .map { bookMapper.toBook(it) } - val supportedExtensions = Constants.EXTENSIONS - - fun File.isValid(): Boolean { - if (!exists()) { - return false - } - - val isFileSupported = supportedExtensions.any { ext -> - name.endsWith( - ext, - ignoreCase = true - ) - } - - if (!isFileSupported) { - return false - } - - val isFileNotAdded = existingBooks.all { - it.filePath.lowercase().trim() != path.lowercase().trim() - } - - if (!isFileNotAdded) { - return false - } - - val isQuery = if (query.isEmpty()) true else name.trim().lowercase() - .contains(query.trim().lowercase()) - - return isQuery - } - - suspend fun File.getAllFiles(): List { - val filesList = mutableListOf() - - val files = listFiles() - if (files != null) { - for (file in files) { - if (!file.exists()) { - continue - } - - when { - file.isFile -> { - if (file.isValid()) { - filesList.add( - SelectableFile( - fileOrDirectory = file, - parentDirectory = this, - isDirectory = false, - isFavorite = false, - isSelected = false - ) - ) - } - } - - file.isDirectory -> { - val subDirectoryFiles = file.getAllFiles() - if (subDirectoryFiles.isNotEmpty()) { - filesList.add( - SelectableFile( - fileOrDirectory = file, - parentDirectory = this, - isDirectory = true, - isFavorite = database.favoriteDirectoryExits(file.path), - isSelected = false - ) - ) - filesList.addAll(subDirectoryFiles) - } - } - } - } - } - - return filesList - } - - val rootDirectory = Environment.getExternalStorageDirectory() - if ( - !rootDirectory.exists() || - !rootDirectory.isDirectory || - (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED && - Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED_READ_ONLY) - ) { - Log.e(GET_FILES_FROM_DEVICE, "Could not correctly get root directory.") - return emptyList() - } - - Log.i(GET_FILES_FROM_DEVICE, "Successfully got all matching files.") - return rootDirectory.getAllFiles() - } - - /** - * Gets book from given file. If error happened, returns [NullableBook.Null]. - */ - override suspend fun getBookFromFile(file: File): NullableBook { - val parsedBook = fileParser.parse(file) - if (parsedBook == null) { - Log.e(GET_BOOK_FROM_FILE, "Parsed file(${file.name}) is null.") - return NullableBook.Null( - file.name, - UIText.StringResource(R.string.error_something_went_wrong) - ) - } - - val parsedText = textParser.parse(file) - if (parsedText is Resource.Error) { - Log.e(GET_BOOK_FROM_FILE, "Parsed text(${file.name}) has error.") - return NullableBook.Null( - file.name, - parsedText.message - ) - } - - Log.i(GET_BOOK_FROM_FILE, "Successfully got book from file.") - return NullableBook.NotNull( - bookWithTextAndCover = BookWithTextAndCover( - book = parsedBook.book.copy( - chapters = parsedText.data!!.map { it.chapter }.run { - if (this.size == 1) return@run emptyList() - this - } - ), - coverImage = parsedBook.coverImage, - text = parsedText.data.map { - it.text - }.flatten() - ) - ) - } - - /** - * Insert history in database. - */ - override suspend fun insertHistory(history: History) { - database.insertHistory( - listOf( - historyMapper.toHistoryEntity( - history - ) - ) - ) - } - - /** - * Get all history from database. - */ - override suspend fun getHistory(): List { - return database.getHistory().map { - historyMapper.toHistory( - it - ) - } - } - - /** - * Get latest history of the matching [bookId]. - */ - override suspend fun getLatestBookHistory(bookId: Int): History? { - val history = database.getLatestHistoryForBook(bookId) - return history?.let { historyMapper.toHistory(it) } - } - - /** - * Delete whole history. - */ - override suspend fun deleteWholeHistory() { - database.deleteWholeHistory() - } - - /** - * Delete all history of the matching [bookId]. - */ - override suspend fun deleteBookHistory(bookId: Int) { - database.deleteBookHistory(bookId) - } - - /** - * Delete specific history item. - */ - override suspend fun deleteHistory(history: History) { - database.deleteHistory( - listOf( - historyMapper.toHistoryEntity( - history - ) - ) - ) - } - - /** - * Check for updates from GitHub. - * - * @param postNotification Whether notification should be send. - */ - override suspend fun checkForUpdates(postNotification: Boolean): LatestReleaseInfo? { - Log.i(CHECK_FOR_UPDATES, "Checking for updates. Post notification: $postNotification") - - return withContext(Dispatchers.IO) { - try { - val result = githubAPI.getLatestRelease() - - val version = result.tagName.substringAfter("v") - val currentVersion = application.getString(R.string.app_version) - - if (version != currentVersion && postNotification) { - Log.i(CHECK_FOR_UPDATES, "Posting notification.") - updatesNotificationService.postNotification( - result - ) - } - - result - } catch (e: Exception) { - Log.e(CHECK_FOR_UPDATES, "Could not get latest release information.") - e.printStackTrace() - null - } - } - } - - /** - * Update color preset. - */ - override suspend fun updateColorPreset(colorPreset: ColorPreset) { - database.updateColorPreset( - colorPresetMapper.toColorPresetEntity( - colorPreset, - if (colorPreset.id != -1) database.getColorPresetOrder(colorPreset.id) - else database.getColorPresetsSize() - ) - ) - } - - /** - * Select color preset. Only one can be selected at time. - */ - override suspend fun selectColorPreset(colorPreset: ColorPreset) { - database.getColorPresets().map { - it.copy( - isSelected = it.id == colorPreset.id - ) - }.forEach { - database.updateColorPreset(it) - } - } - - /** - * Get all color presets. - * Sorted by order (either manual or newest ones at the end). - */ - override suspend fun getColorPresets(): List { - return database.getColorPresets() - .sortedBy { it.order } - .map { colorPresetMapper.toColorPreset(it) } - } - - /** - * Reorder color presets. - * Changes the order of the color presets. - */ - override suspend fun reorderColorPresets(orderedColorPresets: List) { - database.deleteColorPresets() - - orderedColorPresets.forEachIndexed { index, colorPreset -> - database.updateColorPreset( - colorPresetMapper.toColorPresetEntity(colorPreset, order = index) - ) - } - } - - /** - * Delete color preset. - */ - override suspend fun deleteColorPreset(colorPreset: ColorPreset) { - database.deleteColorPreset( - colorPresetMapper.toColorPresetEntity( - colorPreset, -1 - ) - ) - } - - /** - * Create or delete favorite directory if already exists. - * - * @param path Path to directory. - */ - override suspend fun updateFavoriteDirectory(path: String) { - if (database.favoriteDirectoryExits(path)) { - database.deleteFavoriteDirectory( - FavoriteDirectoryEntity(path) - ) - return - } - - database.insertFavoriteDirectory( - FavoriteDirectoryEntity(path) - ) - } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt new file mode 100644 index 00000000..ea8da082 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/ColorPresetRepositoryImpl.kt @@ -0,0 +1,81 @@ +package ua.acclorite.book_story.data.repository + +import ua.acclorite.book_story.data.local.room.BookDao +import ua.acclorite.book_story.data.mapper.color_preset.ColorPresetMapper +import ua.acclorite.book_story.domain.model.ColorPreset +import ua.acclorite.book_story.domain.repository.ColorPresetRepository +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Color Preset repository. + * Manages all [ColorPreset] related work. + */ +@Singleton +class ColorPresetRepositoryImpl @Inject constructor( + private val database: BookDao, + + private val colorPresetMapper: ColorPresetMapper +) : ColorPresetRepository { + + /** + * Update color preset. + */ + override suspend fun updateColorPreset(colorPreset: ColorPreset) { + database.updateColorPreset( + colorPresetMapper.toColorPresetEntity( + colorPreset, + if (colorPreset.id != -1) database.getColorPresetOrder(colorPreset.id) + else database.getColorPresetsSize() + ) + ) + } + + /** + * Select color preset. Only one can be selected at time. + */ + override suspend fun selectColorPreset(colorPreset: ColorPreset) { + database.getColorPresets().map { + it.copy( + isSelected = it.id == colorPreset.id + ) + }.forEach { + database.updateColorPreset(it) + } + } + + /** + * Get all color presets. + * Sorted by order (either manual or newest ones at the end). + */ + override suspend fun getColorPresets(): List { + return database.getColorPresets() + .sortedBy { it.order } + .map { colorPresetMapper.toColorPreset(it) } + } + + /** + * Reorder color presets. + * Changes the order of the color presets. + */ + override suspend fun reorderColorPresets(orderedColorPresets: List) { + database.deleteColorPresets() + + orderedColorPresets.forEachIndexed { index, colorPreset -> + database.updateColorPreset( + colorPresetMapper.toColorPresetEntity(colorPreset, order = index) + ) + } + } + + /** + * Delete color preset. + */ + override suspend fun deleteColorPreset(colorPreset: ColorPreset) { + database.deleteColorPreset( + colorPresetMapper.toColorPresetEntity( + colorPreset, -1 + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt new file mode 100644 index 00000000..bc658932 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/DataStoreRepositoryImpl.kt @@ -0,0 +1,65 @@ +package ua.acclorite.book_story.data.repository + +import android.util.Log +import androidx.datastore.preferences.core.Preferences +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.withContext +import ua.acclorite.book_story.data.local.data_store.DataStore +import ua.acclorite.book_story.domain.repository.DataStoreRepository +import ua.acclorite.book_story.presentation.data.MainState +import javax.inject.Inject +import javax.inject.Singleton + +private const val GET_ALL_SETTINGS = "GET SETTINGS, REPO" + +/** + * Data Store repository. + * Manages all [DataStore] related work. + */ +@Singleton +class DataStoreRepositoryImpl @Inject constructor( + private val dataStore: DataStore +) : DataStoreRepository { + + /** + * Puts DataStore constant to [DataStore]. + */ + override suspend fun putDataToDataStore(key: Preferences.Key, value: T) { + dataStore.putData(key, value) + } + + /** + * Gets all settings from DataStore and returns [MainState]. + */ + override suspend fun getAllSettings(): MainState { + Log.i(GET_ALL_SETTINGS, "Getting all settings.") + val result = CompletableDeferred() + + withContext(Dispatchers.Default) { + val keys = dataStore.getAllData() + val data = mutableMapOf() + + Log.i(GET_ALL_SETTINGS, "Got ${keys?.size} settings keys.") + + val jobs = keys?.map { key -> + async { + val nullableData = dataStore.getNullableData(key) + + if (nullableData == null) { + data.remove(key.name) + } else { + data[key.name] = nullableData + } + } + } + jobs?.awaitAll() + + result.complete(MainState.initialize(data)) + } + + return result.await() + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/FavoriteDirectoryRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/FavoriteDirectoryRepositoryImpl.kt new file mode 100644 index 00000000..b3b7bfc0 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/FavoriteDirectoryRepositoryImpl.kt @@ -0,0 +1,35 @@ +package ua.acclorite.book_story.data.repository + +import ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity +import ua.acclorite.book_story.data.local.room.BookDao +import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Favorite Directory repository. + * Manages all [ua.acclorite.book_story.data.local.dto.FavoriteDirectoryEntity] related work. + */ +@Singleton +class FavoriteDirectoryRepositoryImpl @Inject constructor( + private val database: BookDao, +) : FavoriteDirectoryRepository { + + /** + * Create or delete favorite directory if already exists. + * + * @param path Path to directory. + */ + override suspend fun updateFavoriteDirectory(path: String) { + if (database.favoriteDirectoryExits(path)) { + database.deleteFavoriteDirectory( + FavoriteDirectoryEntity(path) + ) + return + } + + database.insertFavoriteDirectory( + FavoriteDirectoryEntity(path) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt new file mode 100644 index 00000000..27446608 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/FileSystemRepositoryImpl.kt @@ -0,0 +1,182 @@ +package ua.acclorite.book_story.data.repository + +import android.os.Environment +import android.util.Log +import ua.acclorite.book_story.R +import ua.acclorite.book_story.data.local.room.BookDao +import ua.acclorite.book_story.data.mapper.book.BookMapper +import ua.acclorite.book_story.data.parser.FileParser +import ua.acclorite.book_story.data.parser.TextParser +import ua.acclorite.book_story.domain.model.BookWithTextAndCover +import ua.acclorite.book_story.domain.model.NullableBook +import ua.acclorite.book_story.domain.model.NullableBook.NotNull +import ua.acclorite.book_story.domain.model.NullableBook.Null +import ua.acclorite.book_story.domain.model.SelectableFile +import ua.acclorite.book_story.domain.repository.FileSystemRepository +import ua.acclorite.book_story.domain.util.Resource +import ua.acclorite.book_story.domain.util.UIText +import ua.acclorite.book_story.presentation.core.constants.Constants +import java.io.File +import javax.inject.Inject +import javax.inject.Singleton + +private const val GET_BOOK_FROM_FILE = "BOOK FROM FILE, REPO" +private const val GET_FILES_FROM_DEVICE = "FILES FROM DEVICE, REPO" + +/** + * File System repository. + * Manages all File System([java.io.File]) related work. + */ +@Singleton +class FileSystemRepositoryImpl @Inject constructor( + private val database: BookDao, + + private val bookMapper: BookMapper, + + private val fileParser: FileParser, + private val textParser: TextParser, +) : FileSystemRepository { + + /** + * Get all matching files from device. + * Filters by [query] and sorts out not supported file formats and already added files. + */ + override suspend fun getFilesFromDevice(query: String): List { + Log.i(GET_FILES_FROM_DEVICE, "Getting files from device by query: \"$query\".") + + val existingBooks = database + .searchBooks("") + .map { bookMapper.toBook(it) } + val supportedExtensions = Constants.EXTENSIONS + + fun File.isValid(): Boolean { + if (!exists()) { + return false + } + + val isFileSupported = supportedExtensions.any { ext -> + name.endsWith( + ext, + ignoreCase = true + ) + } + + if (!isFileSupported) { + return false + } + + val isFileNotAdded = existingBooks.all { + it.filePath.lowercase().trim() != path.lowercase().trim() + } + + if (!isFileNotAdded) { + return false + } + + val isQuery = if (query.isEmpty()) true else name.trim().lowercase() + .contains(query.trim().lowercase()) + + return isQuery + } + + suspend fun File.getAllFiles(): List { + val filesList = mutableListOf() + + val files = listFiles() + if (files != null) { + for (file in files) { + if (!file.exists()) { + continue + } + + when { + file.isFile -> { + if (file.isValid()) { + filesList.add( + SelectableFile( + fileOrDirectory = file, + parentDirectory = this, + isDirectory = false, + isFavorite = false, + isSelected = false + ) + ) + } + } + + file.isDirectory -> { + val subDirectoryFiles = file.getAllFiles() + if (subDirectoryFiles.isNotEmpty()) { + filesList.add( + SelectableFile( + fileOrDirectory = file, + parentDirectory = this, + isDirectory = true, + isFavorite = database.favoriteDirectoryExits(file.path), + isSelected = false + ) + ) + filesList.addAll(subDirectoryFiles) + } + } + } + } + } + + return filesList + } + + val rootDirectory = Environment.getExternalStorageDirectory() + if ( + !rootDirectory.exists() || + !rootDirectory.isDirectory || + (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED && + Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED_READ_ONLY) + ) { + Log.e(GET_FILES_FROM_DEVICE, "Could not correctly get root directory.") + return emptyList() + } + + Log.i(GET_FILES_FROM_DEVICE, "Successfully got all matching files.") + return rootDirectory.getAllFiles() + } + + /** + * Gets book from given file. If error happened, returns [NullableBook.Null]. + */ + override suspend fun getBookFromFile(file: File): NullableBook { + val parsedBook = fileParser.parse(file) + if (parsedBook == null) { + Log.e(GET_BOOK_FROM_FILE, "Parsed file(${file.name}) is null.") + return Null( + file.name, + UIText.StringResource(R.string.error_something_went_wrong) + ) + } + + val parsedText = textParser.parse(file) + if (parsedText is Resource.Error) { + Log.e(GET_BOOK_FROM_FILE, "Parsed text(${file.name}) has error.") + return Null( + file.name, + parsedText.message + ) + } + + Log.i(GET_BOOK_FROM_FILE, "Successfully got book from file.") + return NotNull( + bookWithTextAndCover = BookWithTextAndCover( + book = parsedBook.book.copy( + chapters = parsedText.data!!.map { it.chapter }.run { + if (this.size == 1) return@run emptyList() + this + } + ), + coverImage = parsedBook.coverImage, + text = parsedText.data.map { + it.text + }.flatten() + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/HistoryRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/HistoryRepositoryImpl.kt new file mode 100644 index 00000000..16f3970c --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/HistoryRepositoryImpl.kt @@ -0,0 +1,79 @@ +package ua.acclorite.book_story.data.repository + +import ua.acclorite.book_story.data.local.room.BookDao +import ua.acclorite.book_story.data.mapper.history.HistoryMapper +import ua.acclorite.book_story.domain.model.History +import ua.acclorite.book_story.domain.repository.HistoryRepository +import javax.inject.Inject +import javax.inject.Singleton + +/** + * History repository. + * Manages all [History] related work. + */ +@Singleton +class HistoryRepositoryImpl @Inject constructor( + private val database: BookDao, + + private val historyMapper: HistoryMapper, +) : HistoryRepository { + + /** + * Insert history in database. + */ + override suspend fun insertHistory(history: History) { + database.insertHistory( + listOf( + historyMapper.toHistoryEntity( + history + ) + ) + ) + } + + /** + * Get all history from database. + */ + override suspend fun getHistory(): List { + return database.getHistory().map { + historyMapper.toHistory( + it + ) + } + } + + /** + * Get latest history of the matching [bookId]. + */ + override suspend fun getLatestBookHistory(bookId: Int): History? { + val history = database.getLatestHistoryForBook(bookId) + return history?.let { historyMapper.toHistory(it) } + } + + /** + * Delete whole history. + */ + override suspend fun deleteWholeHistory() { + database.deleteWholeHistory() + } + + /** + * Delete all history of the matching [bookId]. + */ + override suspend fun deleteBookHistory(bookId: Int) { + database.deleteBookHistory(bookId) + } + + /** + * Delete specific history item. + */ + override suspend fun deleteHistory(history: History) { + database.deleteHistory( + listOf( + historyMapper.toHistoryEntity( + history + ) + ) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/data/repository/RemoteRepositoryImpl.kt b/app/src/main/java/ua/acclorite/book_story/data/repository/RemoteRepositoryImpl.kt new file mode 100644 index 00000000..da0492d8 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/data/repository/RemoteRepositoryImpl.kt @@ -0,0 +1,59 @@ +package ua.acclorite.book_story.data.repository + +import android.app.Application +import android.util.Log +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import ua.acclorite.book_story.R +import ua.acclorite.book_story.data.local.notification.UpdatesNotificationService +import ua.acclorite.book_story.data.remote.GithubAPI +import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo +import ua.acclorite.book_story.domain.repository.RemoteRepository +import javax.inject.Inject +import javax.inject.Singleton + +private const val CHECK_FOR_UPDATES = "CHECK FOR UPD, REPO" + +/** + * Remote repository. + * Manages all API(online) related work. + */ +@Singleton +class RemoteRepositoryImpl @Inject constructor( + private val application: Application, + + private val githubAPI: GithubAPI, + private val updatesNotificationService: UpdatesNotificationService, +) : RemoteRepository { + + /** + * Check for updates from GitHub. + * + * @param postNotification Whether notification should be send. + */ + override suspend fun checkForUpdates(postNotification: Boolean): LatestReleaseInfo? { + Log.i(CHECK_FOR_UPDATES, "Checking for updates. Post notification: $postNotification") + + return withContext(Dispatchers.IO) { + try { + val result = githubAPI.getLatestRelease() + + val version = result.tagName.substringAfter("v") + val currentVersion = application.getString(R.string.app_version) + + if (version != currentVersion && postNotification) { + Log.i(CHECK_FOR_UPDATES, "Posting notification.") + updatesNotificationService.postNotification( + result + ) + } + + result + } catch (e: Exception) { + Log.e(CHECK_FOR_UPDATES, "Could not get latest release information.") + e.printStackTrace() + null + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt index 7f9eb55b..6387ea98 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/BookRepository.kt @@ -1,24 +1,15 @@ package ua.acclorite.book_story.domain.repository import androidx.compose.ui.text.AnnotatedString -import androidx.datastore.preferences.core.Preferences -import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.BookWithText import ua.acclorite.book_story.domain.model.BookWithTextAndCover import ua.acclorite.book_story.domain.model.Chapter -import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.model.NullableBook -import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.util.CoverImage import ua.acclorite.book_story.domain.util.Resource -import ua.acclorite.book_story.presentation.data.MainState -import java.io.File interface BookRepository { - /* ------ Books ------------------------------ */ suspend fun getBooks( query: String ): List @@ -61,82 +52,4 @@ interface BookRepository { suspend fun resetCoverImage( bookId: Int ): Boolean - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ DataStore -------------------------- */ - suspend fun putDataToDataStore( - key: Preferences.Key, - value: T - ) - - suspend fun getAllSettings(): MainState - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ File System ------------------------ */ - suspend fun getFilesFromDevice( - query: String = "" - ): List - - suspend fun getBookFromFile( - file: File - ): NullableBook - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ History ---------------------------- */ - suspend fun insertHistory( - history: History - ) - - suspend fun getHistory(): List - - suspend fun getLatestBookHistory( - bookId: Int - ): History? - - suspend fun deleteWholeHistory() - - suspend fun deleteBookHistory( - bookId: Int - ) - - suspend fun deleteHistory( - history: History - ) - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ API (GitHub) ----------------------- */ - suspend fun checkForUpdates( - postNotification: Boolean - ): LatestReleaseInfo? - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ Color Presets ---------------------- */ - suspend fun updateColorPreset( - colorPreset: ColorPreset - ) - - suspend fun selectColorPreset( - colorPreset: ColorPreset - ) - - suspend fun getColorPresets(): List - - suspend fun reorderColorPresets( - orderedColorPresets: List - ) - - suspend fun deleteColorPreset( - colorPreset: ColorPreset - ) - /* - - - - - - - - - - - - - - - - - - - - - - */ - - - /* ------ Favorite Directories --------------- */ - suspend fun updateFavoriteDirectory(path: String) - /* - - - - - - - - - - - - - - - - - - - - - - */ } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/ColorPresetRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/ColorPresetRepository.kt new file mode 100644 index 00000000..ba7e48c0 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/ColorPresetRepository.kt @@ -0,0 +1,24 @@ +package ua.acclorite.book_story.domain.repository + +import ua.acclorite.book_story.domain.model.ColorPreset + +interface ColorPresetRepository { + + suspend fun updateColorPreset( + colorPreset: ColorPreset + ) + + suspend fun selectColorPreset( + colorPreset: ColorPreset + ) + + suspend fun getColorPresets(): List + + suspend fun reorderColorPresets( + orderedColorPresets: List + ) + + suspend fun deleteColorPreset( + colorPreset: ColorPreset + ) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt new file mode 100644 index 00000000..ae2d1758 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/DataStoreRepository.kt @@ -0,0 +1,14 @@ +package ua.acclorite.book_story.domain.repository + +import androidx.datastore.preferences.core.Preferences +import ua.acclorite.book_story.presentation.data.MainState + +interface DataStoreRepository { + + suspend fun putDataToDataStore( + key: Preferences.Key, + value: T + ) + + suspend fun getAllSettings(): MainState +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/FavoriteDirectoryRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/FavoriteDirectoryRepository.kt new file mode 100644 index 00000000..8cccd6f1 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/FavoriteDirectoryRepository.kt @@ -0,0 +1,6 @@ +package ua.acclorite.book_story.domain.repository + +interface FavoriteDirectoryRepository { + + suspend fun updateFavoriteDirectory(path: String) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt new file mode 100644 index 00000000..74a2d4a7 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/FileSystemRepository.kt @@ -0,0 +1,16 @@ +package ua.acclorite.book_story.domain.repository + +import ua.acclorite.book_story.domain.model.NullableBook +import ua.acclorite.book_story.domain.model.SelectableFile +import java.io.File + +interface FileSystemRepository { + + suspend fun getFilesFromDevice( + query: String = "" + ): List + + suspend fun getBookFromFile( + file: File + ): NullableBook +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/HistoryRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/HistoryRepository.kt new file mode 100644 index 00000000..8e4f7f5f --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/HistoryRepository.kt @@ -0,0 +1,26 @@ +package ua.acclorite.book_story.domain.repository + +import ua.acclorite.book_story.domain.model.History + +interface HistoryRepository { + + suspend fun insertHistory( + history: History + ) + + suspend fun getHistory(): List + + suspend fun getLatestBookHistory( + bookId: Int + ): History? + + suspend fun deleteWholeHistory() + + suspend fun deleteBookHistory( + bookId: Int + ) + + suspend fun deleteHistory( + history: History + ) +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/repository/RemoteRepository.kt b/app/src/main/java/ua/acclorite/book_story/domain/repository/RemoteRepository.kt new file mode 100644 index 00000000..99364313 --- /dev/null +++ b/app/src/main/java/ua/acclorite/book_story/domain/repository/RemoteRepository.kt @@ -0,0 +1,10 @@ +package ua.acclorite.book_story.domain.repository + +import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo + +interface RemoteRepository { + + suspend fun checkForUpdates( + postNotification: Boolean + ): LatestReleaseInfo? +} \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/CheckForTextUpdate.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/CheckForTextUpdate.kt index 3754d288..29c82fb7 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/CheckForTextUpdate.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/CheckForTextUpdate.kt @@ -5,7 +5,9 @@ import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.util.Resource import javax.inject.Inject -class CheckForTextUpdate @Inject constructor(private val repository: BookRepository) { +class CheckForTextUpdate @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(bookId: Int): Resource, List>?> { return repository.checkForTextUpdate(bookId) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/DeleteBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/DeleteBooks.kt index 4d64d027..896eaca7 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/DeleteBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/DeleteBooks.kt @@ -2,14 +2,18 @@ package ua.acclorite.book_story.domain.use_case.book import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class DeleteBooks @Inject constructor(private val repository: BookRepository) { +class DeleteBooks @Inject constructor( + private val bookRepository: BookRepository, + private val historyRepository: HistoryRepository +) { suspend fun execute(books: List) { - repository.deleteBooks(books) + bookRepository.deleteBooks(books) books.forEach { - repository.deleteBookHistory(it.id) + historyRepository.deleteBookHistory(it.id) } } } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBookById.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBookById.kt index 8bfe74c2..6e18eb89 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBookById.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBookById.kt @@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class GetBookById @Inject constructor(private val repository: BookRepository) { +class GetBookById @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(id: Int): Book? { return repository.getBooksById(listOf(id)).firstOrNull() diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooks.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooks.kt index 43835da6..eb0c39b0 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooks.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooks.kt @@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class GetBooks @Inject constructor(private val repository: BookRepository) { +class GetBooks @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(query: String): List { return repository.getBooks(query) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooksById.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooksById.kt index 99b1df8f..3a71574f 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooksById.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetBooksById.kt @@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class GetBooksById @Inject constructor(private val repository: BookRepository) { +class GetBooksById @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(ids: List): List { return repository.getBooksById(ids) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetText.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetText.kt index 221373e0..5b03d6bc 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetText.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/GetText.kt @@ -4,7 +4,9 @@ import androidx.compose.ui.text.AnnotatedString import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class GetText @Inject constructor(private val repository: BookRepository) { +class GetText @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(textPath: String): List { return repository.getBookText(textPath = textPath) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/InsertBook.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/InsertBook.kt index dd01075b..8dde9166 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/InsertBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/InsertBook.kt @@ -4,7 +4,10 @@ import ua.acclorite.book_story.domain.model.BookWithTextAndCover import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class InsertBook @Inject constructor(private val repository: BookRepository) { +class InsertBook @Inject constructor( + private val repository: BookRepository +) { + suspend fun execute( bookWithTextAndCover: BookWithTextAndCover ): Boolean { diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBook.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBook.kt index 58d488dc..1be96a20 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBook.kt @@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class UpdateBook @Inject constructor(private val repository: BookRepository) { +class UpdateBook @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(book: Book) { repository.updateBook(book) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBookWithText.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBookWithText.kt index 5b7ac4c3..4640b08d 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBookWithText.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateBookWithText.kt @@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.BookWithText import ua.acclorite.book_story.domain.repository.BookRepository import javax.inject.Inject -class UpdateBookWithText @Inject constructor(private val repository: BookRepository) { +class UpdateBookWithText @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(bookWithText: BookWithText): Boolean { return repository.updateBookWithText(bookWithText) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateCoverImageOfBook.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateCoverImageOfBook.kt index eed4e807..549141f7 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateCoverImageOfBook.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/book/UpdateCoverImageOfBook.kt @@ -5,7 +5,9 @@ import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.util.CoverImage import javax.inject.Inject -class UpdateCoverImageOfBook @Inject constructor(private val repository: BookRepository) { +class UpdateCoverImageOfBook @Inject constructor( + private val repository: BookRepository +) { suspend fun execute(bookWithOldCover: Book, newCoverImage: CoverImage?) { repository.updateCoverImageOfBook(bookWithOldCover, newCoverImage) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/DeleteColorPreset.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/DeleteColorPreset.kt index d3dac537..fe53563d 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/DeleteColorPreset.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/DeleteColorPreset.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.color_preset import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject -class DeleteColorPreset @Inject constructor(private val repository: BookRepository) { +class DeleteColorPreset @Inject constructor( + private val repository: ColorPresetRepository +) { suspend fun execute(colorPreset: ColorPreset) { repository.deleteColorPreset(colorPreset) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/GetColorPresets.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/GetColorPresets.kt index 4dc755dc..bbc5d09e 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/GetColorPresets.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/GetColorPresets.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.color_preset import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject -class GetColorPresets @Inject constructor(private val repository: BookRepository) { +class GetColorPresets @Inject constructor( + private val repository: ColorPresetRepository +) { suspend fun execute(): List { return repository.getColorPresets() diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/ReorderColorPresets.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/ReorderColorPresets.kt index 675adce0..fafba519 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/ReorderColorPresets.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/ReorderColorPresets.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.color_preset import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject -class ReorderColorPresets @Inject constructor(private val repository: BookRepository) { +class ReorderColorPresets @Inject constructor( + private val repository: ColorPresetRepository +) { suspend fun execute(reorderedColorPresets: List) { repository.reorderColorPresets(reorderedColorPresets) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/SelectColorPreset.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/SelectColorPreset.kt index 2a413c28..f26c8a6f 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/SelectColorPreset.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/SelectColorPreset.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.color_preset import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject -class SelectColorPreset @Inject constructor(private val repository: BookRepository) { +class SelectColorPreset @Inject constructor( + private val repository: ColorPresetRepository +) { suspend fun execute(colorPreset: ColorPreset) { repository.selectColorPreset(colorPreset) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/UpdateColorPreset.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/UpdateColorPreset.kt index 726fb351..f571706a 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/UpdateColorPreset.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/color_preset/UpdateColorPreset.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.color_preset import ua.acclorite.book_story.domain.model.ColorPreset -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.ColorPresetRepository import javax.inject.Inject -class UpdateColorPreset @Inject constructor(private val repository: BookRepository) { +class UpdateColorPreset @Inject constructor( + private val repository: ColorPresetRepository +) { suspend fun execute(colorPreset: ColorPreset) { repository.updateColorPreset(colorPreset) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/common/ChangeLanguage.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguage.kt similarity index 68% rename from app/src/main/java/ua/acclorite/book_story/domain/use_case/common/ChangeLanguage.kt rename to app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguage.kt index 1a687020..78267584 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/common/ChangeLanguage.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/ChangeLanguage.kt @@ -1,12 +1,14 @@ -package ua.acclorite.book_story.domain.use_case.common +package ua.acclorite.book_story.domain.use_case.data_store import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.DataStoreRepository import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants import javax.inject.Inject -class ChangeLanguage @Inject constructor(private val repository: BookRepository) { +class ChangeLanguage @Inject constructor( + private val repository: DataStoreRepository +) { suspend fun execute(language: String) { val appLocale = LocaleListCompat.forLanguageTags(language) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetAllSettings.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetAllSettings.kt index 062546ad..505345cb 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetAllSettings.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/GetAllSettings.kt @@ -1,11 +1,11 @@ package ua.acclorite.book_story.domain.use_case.data_store -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.DataStoreRepository import ua.acclorite.book_story.presentation.data.MainState import javax.inject.Inject class GetAllSettings @Inject constructor( - private val repository: BookRepository + private val repository: DataStoreRepository ) { suspend fun execute(): MainState { diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/SetDatastore.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/SetDatastore.kt index 74d5fa7b..205aab17 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/SetDatastore.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/data_store/SetDatastore.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.data_store import androidx.datastore.preferences.core.Preferences -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.DataStoreRepository import javax.inject.Inject -class SetDatastore @Inject constructor(private val repository: BookRepository) { +class SetDatastore @Inject constructor( + private val repository: DataStoreRepository +) { suspend fun execute(key: Preferences.Key, value: T) { repository.putDataToDataStore(key, value) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/favorite_directory/UpdateFavoriteDirectory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/favorite_directory/UpdateFavoriteDirectory.kt index 9f4fa20c..8b0bd324 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/favorite_directory/UpdateFavoriteDirectory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/favorite_directory/UpdateFavoriteDirectory.kt @@ -1,9 +1,12 @@ package ua.acclorite.book_story.domain.use_case.favorite_directory -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.FavoriteDirectoryRepository import javax.inject.Inject -class UpdateFavoriteDirectory @Inject constructor(private val repository: BookRepository) { +class UpdateFavoriteDirectory @Inject constructor( + private val repository: FavoriteDirectoryRepository +) { + suspend fun execute(path: String) { return repository.updateFavoriteDirectory(path) } diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetBookFromFile.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetBookFromFile.kt index ab5e4960..529885d0 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetBookFromFile.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetBookFromFile.kt @@ -1,12 +1,12 @@ package ua.acclorite.book_story.domain.use_case.file_system import ua.acclorite.book_story.domain.model.NullableBook -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.FileSystemRepository import java.io.File import javax.inject.Inject class GetBookFromFile @Inject constructor( - private val repository: BookRepository + private val repository: FileSystemRepository ) { suspend fun execute(file: File): NullableBook { diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetFilesFromDevice.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetFilesFromDevice.kt index eb2a864b..1dad257e 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetFilesFromDevice.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/file_system/GetFilesFromDevice.kt @@ -1,11 +1,11 @@ package ua.acclorite.book_story.domain.use_case.file_system import ua.acclorite.book_story.domain.model.SelectableFile -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.FileSystemRepository import javax.inject.Inject class GetFilesFromDevice @Inject constructor( - private val repository: BookRepository + private val repository: FileSystemRepository ) { suspend fun execute(query: String): List { diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteHistory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteHistory.kt index 07b31ac2..b23bc93d 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteHistory.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.history import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class DeleteHistory @Inject constructor(private val repository: BookRepository) { +class DeleteHistory @Inject constructor( + private val repository: HistoryRepository +) { suspend fun execute(history: History) { repository.deleteHistory(history) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteWholeHistory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteWholeHistory.kt index 1a64554a..695295d2 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteWholeHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/DeleteWholeHistory.kt @@ -1,9 +1,11 @@ package ua.acclorite.book_story.domain.use_case.history -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class DeleteWholeHistory @Inject constructor(private val repository: BookRepository) { +class DeleteWholeHistory @Inject constructor( + private val repository: HistoryRepository +) { suspend fun execute() { repository.deleteWholeHistory() diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetHistory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetHistory.kt index 82bf004c..1bfddaee 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetHistory.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.history import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class GetHistory @Inject constructor(private val repository: BookRepository) { +class GetHistory @Inject constructor( + private val repository: HistoryRepository +) { suspend fun execute(): List { return repository.getHistory() diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetLatestHistory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetLatestHistory.kt index 3f04902e..e61f7819 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetLatestHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/GetLatestHistory.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.history import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class GetLatestHistory @Inject constructor(private val repository: BookRepository) { +class GetLatestHistory @Inject constructor( + private val repository: HistoryRepository +) { suspend fun execute(bookId: Int): History? { return repository.getLatestBookHistory(bookId) diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/InsertHistory.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/InsertHistory.kt index b63fc53d..94a6bd38 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/InsertHistory.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/history/InsertHistory.kt @@ -1,10 +1,13 @@ package ua.acclorite.book_story.domain.use_case.history import ua.acclorite.book_story.domain.model.History -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.HistoryRepository import javax.inject.Inject -class InsertHistory @Inject constructor(private val repository: BookRepository) { +class InsertHistory @Inject constructor( + private val repository: HistoryRepository +) { + suspend fun execute(history: History) { repository.insertHistory(history) } diff --git a/app/src/main/java/ua/acclorite/book_story/domain/use_case/remote/CheckForUpdates.kt b/app/src/main/java/ua/acclorite/book_story/domain/use_case/remote/CheckForUpdates.kt index 9fe8ae93..0e67acd4 100644 --- a/app/src/main/java/ua/acclorite/book_story/domain/use_case/remote/CheckForUpdates.kt +++ b/app/src/main/java/ua/acclorite/book_story/domain/use_case/remote/CheckForUpdates.kt @@ -1,10 +1,12 @@ package ua.acclorite.book_story.domain.use_case.remote import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo -import ua.acclorite.book_story.domain.repository.BookRepository +import ua.acclorite.book_story.domain.repository.RemoteRepository import javax.inject.Inject -class CheckForUpdates @Inject constructor(private val repository: BookRepository) { +class CheckForUpdates @Inject constructor( + private val repository: RemoteRepository +) { suspend fun execute(postNotification: Boolean): LatestReleaseInfo? { return repository.checkForUpdates(postNotification) diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt index 92380f6f..3d8c4780 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/data/MainViewModel.kt @@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import ua.acclorite.book_story.domain.use_case.common.ChangeLanguage +import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage import ua.acclorite.book_story.domain.use_case.data_store.GetAllSettings import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates