🛠️ BookRepository reformat

* Split into multiple smaller repositories
* Reformatted code

Co-authored-by: Ridho Pratama <dhoable@gmail.com>
This commit is contained in:
Acclorite 2024-10-02 09:03:01 +03:00
parent 1104100b3b
commit 9854c2d845
43 changed files with 755 additions and 523 deletions

View file

@ -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.TextParser
import ua.acclorite.book_story.data.parser.TextParserImpl import ua.acclorite.book_story.data.parser.TextParserImpl
import ua.acclorite.book_story.data.repository.BookRepositoryImpl 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.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 import javax.inject.Singleton
@Module @Module
@ -37,6 +49,42 @@ abstract class RepositoryModule {
bookRepositoryImpl: BookRepositoryImpl bookRepositoryImpl: BookRepositoryImpl
): BookRepository ): 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 @Binds
@Singleton @Singleton
abstract fun bindBookMapper( abstract fun bindBookMapper(

View file

@ -4,44 +4,26 @@ import android.app.Application
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.os.Environment
import android.provider.MediaStore import android.provider.MediaStore
import android.util.Log import android.util.Log
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.datastore.preferences.core.Preferences
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import ua.acclorite.book_story.R 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.local.room.BookDao
import ua.acclorite.book_story.data.mapper.book.BookMapper 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.FileParser
import ua.acclorite.book_story.data.parser.MarkdownParser import ua.acclorite.book_story.data.parser.MarkdownParser
import ua.acclorite.book_story.data.parser.TextParser 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.Book
import ua.acclorite.book_story.domain.model.BookWithText import ua.acclorite.book_story.domain.model.BookWithText
import ua.acclorite.book_story.domain.model.BookWithTextAndCover import ua.acclorite.book_story.domain.model.BookWithTextAndCover
import ua.acclorite.book_story.domain.model.Chapter 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.repository.BookRepository
import ua.acclorite.book_story.domain.util.CoverImage import ua.acclorite.book_story.domain.util.CoverImage
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText 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.BufferedReader
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
@ -51,33 +33,23 @@ import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
private const val GET_BOOK_FROM_FILE = "GET BOOK FROM FILE, REPOSITORY" private const val GET_TEXT = "GET TEXT, REPO"
private const val GET_TEXT = "GET TEXT, REPOSITORY" private const val GET_BOOKS = "GET BOOKS, REPO"
private const val GET_BOOKS = "GET BOOKS, REPOSITORY" private const val GET_BOOKS_BY_ID = "GET BOOKS, REPO"
private const val GET_BOOKS_BY_ID = "GET BOOKS, REPOSITORY" private const val INSERT_BOOK = "INSERT BOOK, REPO"
private const val INSERT_BOOK = "INSERT BOOK, REPOSITORY" private const val UPDATE_BOOK = "UPDATE BOOK, REPO"
private const val UPDATE_BOOK = "UPDATE BOOK, REPOSITORY" private const val DELETE_BOOKS = "DELETE BOOKS, REPO"
private const val DELETE_BOOKS = "DELETE BOOKS, REPOSITORY" private const val CAN_RESET_COVER = "CAN RESET COVER, REPO"
private const val CAN_RESET_COVER = "CAN RESET COVER, REPOSITORY" private const val RESET_COVER = "RESET COVER, REPO"
private const val RESET_COVER = "RESET COVER, REPOSITORY" private const val CHECK_FOR_TEXT_UPDATE = "CHECK TEXT UPD, REPO"
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"
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@Singleton @Singleton
class BookRepositoryImpl @Inject constructor( class BookRepositoryImpl @Inject constructor(
private val application: Application, private val application: Application,
private val database: BookDao, private val database: BookDao,
private val dataStore: DataStore,
private val githubAPI: GithubAPI,
private val updatesNotificationService: UpdatesNotificationService,
private val bookMapper: BookMapper, private val bookMapper: BookMapper,
private val historyMapper: HistoryMapper,
private val colorPresetMapper: ColorPresetMapper,
private val fileParser: FileParser, private val fileParser: FileParser,
private val textParser: TextParser, private val textParser: TextParser,
@ -610,355 +582,4 @@ class BookRepositoryImpl @Inject constructor(
Log.i(RESET_COVER, "Successfully reset cover image.") Log.i(RESET_COVER, "Successfully reset cover image.")
return true return true
} }
/**
* Puts DataStore constant to [DataStore].
*/
override suspend fun <T> putDataToDataStore(key: Preferences.Key<T>, 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<MainState>()
withContext(Dispatchers.Default) {
val keys = dataStore.getAllData()
val data = mutableMapOf<String, Any>()
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<SelectableFile> {
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<SelectableFile> {
val filesList = mutableListOf<SelectableFile>()
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<History> {
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<ColorPreset> {
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<ColorPreset>) {
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)
)
}
} }

View file

@ -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<ColorPreset> {
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<ColorPreset>) {
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
)
)
}
}

View file

@ -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 <T> putDataToDataStore(key: Preferences.Key<T>, 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<MainState>()
withContext(Dispatchers.Default) {
val keys = dataStore.getAllData()
val data = mutableMapOf<String, Any>()
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()
}
}

View file

@ -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)
)
}
}

View file

@ -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<SelectableFile> {
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<SelectableFile> {
val filesList = mutableListOf<SelectableFile>()
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()
)
)
}
}

View file

@ -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<History> {
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
)
)
)
}
}

View file

@ -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
}
}
}
}

View file

@ -1,24 +1,15 @@
package ua.acclorite.book_story.domain.repository package ua.acclorite.book_story.domain.repository
import androidx.compose.ui.text.AnnotatedString 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.Book
import ua.acclorite.book_story.domain.model.BookWithText import ua.acclorite.book_story.domain.model.BookWithText
import ua.acclorite.book_story.domain.model.BookWithTextAndCover import ua.acclorite.book_story.domain.model.BookWithTextAndCover
import ua.acclorite.book_story.domain.model.Chapter 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.CoverImage
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.presentation.data.MainState
import java.io.File
interface BookRepository { interface BookRepository {
/* ------ Books ------------------------------ */
suspend fun getBooks( suspend fun getBooks(
query: String query: String
): List<Book> ): List<Book>
@ -61,82 +52,4 @@ interface BookRepository {
suspend fun resetCoverImage( suspend fun resetCoverImage(
bookId: Int bookId: Int
): Boolean ): Boolean
/* - - - - - - - - - - - - - - - - - - - - - - */
/* ------ DataStore -------------------------- */
suspend fun <T> putDataToDataStore(
key: Preferences.Key<T>,
value: T
)
suspend fun getAllSettings(): MainState
/* - - - - - - - - - - - - - - - - - - - - - - */
/* ------ File System ------------------------ */
suspend fun getFilesFromDevice(
query: String = ""
): List<SelectableFile>
suspend fun getBookFromFile(
file: File
): NullableBook
/* - - - - - - - - - - - - - - - - - - - - - - */
/* ------ History ---------------------------- */
suspend fun insertHistory(
history: History
)
suspend fun getHistory(): List<History>
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<ColorPreset>
suspend fun reorderColorPresets(
orderedColorPresets: List<ColorPreset>
)
suspend fun deleteColorPreset(
colorPreset: ColorPreset
)
/* - - - - - - - - - - - - - - - - - - - - - - */
/* ------ Favorite Directories --------------- */
suspend fun updateFavoriteDirectory(path: String)
/* - - - - - - - - - - - - - - - - - - - - - - */
} }

View file

@ -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<ColorPreset>
suspend fun reorderColorPresets(
orderedColorPresets: List<ColorPreset>
)
suspend fun deleteColorPreset(
colorPreset: ColorPreset
)
}

View file

@ -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 <T> putDataToDataStore(
key: Preferences.Key<T>,
value: T
)
suspend fun getAllSettings(): MainState
}

View file

@ -0,0 +1,6 @@
package ua.acclorite.book_story.domain.repository
interface FavoriteDirectoryRepository {
suspend fun updateFavoriteDirectory(path: String)
}

View file

@ -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<SelectableFile>
suspend fun getBookFromFile(
file: File
): NullableBook
}

View file

@ -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<History>
suspend fun getLatestBookHistory(
bookId: Int
): History?
suspend fun deleteWholeHistory()
suspend fun deleteBookHistory(
bookId: Int
)
suspend fun deleteHistory(
history: History
)
}

View file

@ -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?
}

View file

@ -5,7 +5,9 @@ import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import javax.inject.Inject 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<Pair<List<String>, List<Chapter>>?> { suspend fun execute(bookId: Int): Resource<Pair<List<String>, List<Chapter>>?> {
return repository.checkForTextUpdate(bookId) return repository.checkForTextUpdate(bookId)

View file

@ -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.model.Book
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.repository.HistoryRepository
import javax.inject.Inject 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<Book>) { suspend fun execute(books: List<Book>) {
repository.deleteBooks(books) bookRepository.deleteBooks(books)
books.forEach { books.forEach {
repository.deleteBookHistory(it.id) historyRepository.deleteBookHistory(it.id)
} }
} }
} }

View file

@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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? { suspend fun execute(id: Int): Book? {
return repository.getBooksById(listOf(id)).firstOrNull() return repository.getBooksById(listOf(id)).firstOrNull()

View file

@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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<Book> { suspend fun execute(query: String): List<Book> {
return repository.getBooks(query) return repository.getBooks(query)

View file

@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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<Int>): List<Book> { suspend fun execute(ids: List<Int>): List<Book> {
return repository.getBooksById(ids) return repository.getBooksById(ids)

View file

@ -4,7 +4,9 @@ import androidx.compose.ui.text.AnnotatedString
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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<AnnotatedString> { suspend fun execute(textPath: String): List<AnnotatedString> {
return repository.getBookText(textPath = textPath) return repository.getBookText(textPath = textPath)

View file

@ -4,7 +4,10 @@ import ua.acclorite.book_story.domain.model.BookWithTextAndCover
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject import javax.inject.Inject
class InsertBook @Inject constructor(private val repository: BookRepository) { class InsertBook @Inject constructor(
private val repository: BookRepository
) {
suspend fun execute( suspend fun execute(
bookWithTextAndCover: BookWithTextAndCover bookWithTextAndCover: BookWithTextAndCover
): Boolean { ): Boolean {

View file

@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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) { suspend fun execute(book: Book) {
repository.updateBook(book) repository.updateBook(book)

View file

@ -4,7 +4,9 @@ import ua.acclorite.book_story.domain.model.BookWithText
import ua.acclorite.book_story.domain.repository.BookRepository import ua.acclorite.book_story.domain.repository.BookRepository
import javax.inject.Inject 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 { suspend fun execute(bookWithText: BookWithText): Boolean {
return repository.updateBookWithText(bookWithText) return repository.updateBookWithText(bookWithText)

View file

@ -5,7 +5,9 @@ import ua.acclorite.book_story.domain.repository.BookRepository
import ua.acclorite.book_story.domain.util.CoverImage import ua.acclorite.book_story.domain.util.CoverImage
import javax.inject.Inject 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?) { suspend fun execute(bookWithOldCover: Book, newCoverImage: CoverImage?) {
repository.updateCoverImageOfBook(bookWithOldCover, newCoverImage) repository.updateCoverImageOfBook(bookWithOldCover, newCoverImage)

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.color_preset package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.domain.model.ColorPreset 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 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) { suspend fun execute(colorPreset: ColorPreset) {
repository.deleteColorPreset(colorPreset) repository.deleteColorPreset(colorPreset)

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.color_preset package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.domain.model.ColorPreset 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 import javax.inject.Inject
class GetColorPresets @Inject constructor(private val repository: BookRepository) { class GetColorPresets @Inject constructor(
private val repository: ColorPresetRepository
) {
suspend fun execute(): List<ColorPreset> { suspend fun execute(): List<ColorPreset> {
return repository.getColorPresets() return repository.getColorPresets()

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.color_preset package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.domain.model.ColorPreset 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 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<ColorPreset>) { suspend fun execute(reorderedColorPresets: List<ColorPreset>) {
repository.reorderColorPresets(reorderedColorPresets) repository.reorderColorPresets(reorderedColorPresets)

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.color_preset package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.domain.model.ColorPreset 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 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) { suspend fun execute(colorPreset: ColorPreset) {
repository.selectColorPreset(colorPreset) repository.selectColorPreset(colorPreset)

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.color_preset package ua.acclorite.book_story.domain.use_case.color_preset
import ua.acclorite.book_story.domain.model.ColorPreset 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 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) { suspend fun execute(colorPreset: ColorPreset) {
repository.updateColorPreset(colorPreset) repository.updateColorPreset(colorPreset)

View file

@ -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.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat 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 ua.acclorite.book_story.presentation.core.constants.DataStoreConstants
import javax.inject.Inject 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) { suspend fun execute(language: String) {
val appLocale = LocaleListCompat.forLanguageTags(language) val appLocale = LocaleListCompat.forLanguageTags(language)

View file

@ -1,11 +1,11 @@
package ua.acclorite.book_story.domain.use_case.data_store 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 ua.acclorite.book_story.presentation.data.MainState
import javax.inject.Inject import javax.inject.Inject
class GetAllSettings @Inject constructor( class GetAllSettings @Inject constructor(
private val repository: BookRepository private val repository: DataStoreRepository
) { ) {
suspend fun execute(): MainState { suspend fun execute(): MainState {

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.data_store package ua.acclorite.book_story.domain.use_case.data_store
import androidx.datastore.preferences.core.Preferences 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 import javax.inject.Inject
class SetDatastore @Inject constructor(private val repository: BookRepository) { class SetDatastore @Inject constructor(
private val repository: DataStoreRepository
) {
suspend fun <T> execute(key: Preferences.Key<T>, value: T) { suspend fun <T> execute(key: Preferences.Key<T>, value: T) {
repository.putDataToDataStore(key, value) repository.putDataToDataStore(key, value)

View file

@ -1,9 +1,12 @@
package ua.acclorite.book_story.domain.use_case.favorite_directory 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 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) { suspend fun execute(path: String) {
return repository.updateFavoriteDirectory(path) return repository.updateFavoriteDirectory(path)
} }

View file

@ -1,12 +1,12 @@
package ua.acclorite.book_story.domain.use_case.file_system package ua.acclorite.book_story.domain.use_case.file_system
import ua.acclorite.book_story.domain.model.NullableBook 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 java.io.File
import javax.inject.Inject import javax.inject.Inject
class GetBookFromFile @Inject constructor( class GetBookFromFile @Inject constructor(
private val repository: BookRepository private val repository: FileSystemRepository
) { ) {
suspend fun execute(file: File): NullableBook { suspend fun execute(file: File): NullableBook {

View file

@ -1,11 +1,11 @@
package ua.acclorite.book_story.domain.use_case.file_system package ua.acclorite.book_story.domain.use_case.file_system
import ua.acclorite.book_story.domain.model.SelectableFile 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 import javax.inject.Inject
class GetFilesFromDevice @Inject constructor( class GetFilesFromDevice @Inject constructor(
private val repository: BookRepository private val repository: FileSystemRepository
) { ) {
suspend fun execute(query: String): List<SelectableFile> { suspend fun execute(query: String): List<SelectableFile> {

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.history package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.domain.model.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 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) { suspend fun execute(history: History) {
repository.deleteHistory(history) repository.deleteHistory(history)

View file

@ -1,9 +1,11 @@
package ua.acclorite.book_story.domain.use_case.history 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 import javax.inject.Inject
class DeleteWholeHistory @Inject constructor(private val repository: BookRepository) { class DeleteWholeHistory @Inject constructor(
private val repository: HistoryRepository
) {
suspend fun execute() { suspend fun execute() {
repository.deleteWholeHistory() repository.deleteWholeHistory()

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.history package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.domain.model.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 import javax.inject.Inject
class GetHistory @Inject constructor(private val repository: BookRepository) { class GetHistory @Inject constructor(
private val repository: HistoryRepository
) {
suspend fun execute(): List<History> { suspend fun execute(): List<History> {
return repository.getHistory() return repository.getHistory()

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.history package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.domain.model.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 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? { suspend fun execute(bookId: Int): History? {
return repository.getLatestBookHistory(bookId) return repository.getLatestBookHistory(bookId)

View file

@ -1,10 +1,13 @@
package ua.acclorite.book_story.domain.use_case.history package ua.acclorite.book_story.domain.use_case.history
import ua.acclorite.book_story.domain.model.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 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) { suspend fun execute(history: History) {
repository.insertHistory(history) repository.insertHistory(history)
} }

View file

@ -1,10 +1,12 @@
package ua.acclorite.book_story.domain.use_case.remote package ua.acclorite.book_story.domain.use_case.remote
import ua.acclorite.book_story.data.remote.dto.LatestReleaseInfo 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 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? { suspend fun execute(postNotification: Boolean): LatestReleaseInfo? {
return repository.checkForUpdates(postNotification) return repository.checkForUpdates(postNotification)

View file

@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext 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.GetAllSettings
import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore
import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates