diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..103e00cb
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..94a25f7f
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0ac4ad07..54050d3c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -2,6 +2,8 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
+
+ id("com.google.dagger.hilt.android")
kotlin("kapt")
}
@@ -47,6 +49,7 @@ android {
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
+ excludes += "/META-INF/gradle/incremental.annotation.processors"
}
}
}
@@ -77,16 +80,13 @@ dependencies {
// All dependencies
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
- implementation ("androidx.compose.material:material-icons-extended:$composeVersion")
+ implementation ("androidx.compose.material:material-icons-extended")
implementation ("androidx.activity:activity-compose:1.8.2")
implementation ("com.google.accompanist:accompanist-swiperefresh:0.24.2-alpha")
- //Dagger - Hilt
- implementation ("com.google.dagger:hilt-compiler:latest.release")
- implementation ("com.google.dagger:hilt-android:latest.release")
- kapt ("com.google.dagger:hilt-android-compiler:latest.release")
- kapt ("androidx.hilt:hilt-compiler:latest.release")
- implementation ("androidx.hilt:hilt-navigation-compose:1.1.0")
+ // Dagger
+ implementation("com.google.dagger:hilt-android:2.50")
+ kapt("com.google.dagger:hilt-android-compiler:2.50")
// Room
implementation ("androidx.room:room-runtime:2.6.1")
@@ -94,4 +94,7 @@ dependencies {
// Kotlin Extensions and Coroutines support for Room
implementation ("androidx.room:room-ktx:2.6.1")
+
+ // Datastore
+ implementation ("androidx.datastore:datastore-preferences:latest.release")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index df9ffba9..8d22b2a4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
getData (key: Preferences.Key, defaultValue: T): Flow
+ suspend fun putData (key: Preferences.Key, value: T)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/local/data_store/DataStoreImpl.kt b/app/src/main/java/com/acclorite/books_history/data/local/data_store/DataStoreImpl.kt
new file mode 100644
index 00000000..82e8794e
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/local/data_store/DataStoreImpl.kt
@@ -0,0 +1,37 @@
+package com.acclorite.books_history.data.local.data_store
+
+import android.app.Application
+import android.content.Context
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.emptyPreferences
+import androidx.datastore.preferences.preferencesDataStore
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.map
+import java.io.IOException
+import javax.inject.Inject
+
+private val Context.dataStore by preferencesDataStore("data_store")
+
+class DataStoreImpl @Inject constructor(context: Application): DataStore {
+ private val dataStore = context.dataStore
+
+ override suspend fun getData(key: Preferences.Key, defaultValue: T): Flow =
+ dataStore.data.catch { exception ->
+ if (exception is IOException){
+ emit(emptyPreferences())
+ } else{
+ throw exception
+ }
+ }.map { preferences ->
+ val result = preferences[key]?: defaultValue
+ result
+ }
+
+ override suspend fun putData(key: Preferences.Key, value: T) {
+ dataStore.edit { preferences ->
+ preferences[key] = value
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/local/dto/BookEntity.kt b/app/src/main/java/com/acclorite/books_history/data/local/dto/BookEntity.kt
new file mode 100644
index 00000000..68cc6b11
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/local/dto/BookEntity.kt
@@ -0,0 +1,29 @@
+package com.acclorite.books_history.data.local.dto
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.acclorite.books_history.domain.model.Category
+
+@Entity
+data class BookEntity(
+ @PrimaryKey(true) val id: Int? = null,
+ val title: String,
+ val filePath: String,
+ val progress: Float,
+ var lastOpened: Long? = null,
+ val image: ByteArray = byteArrayOf(),
+ val category: Category
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as BookEntity
+
+ return image.contentEquals(other.image)
+ }
+
+ override fun hashCode(): Int {
+ return image.contentHashCode()
+ }
+}
diff --git a/app/src/main/java/com/acclorite/books_history/data/local/room/BookDao.kt b/app/src/main/java/com/acclorite/books_history/data/local/room/BookDao.kt
new file mode 100644
index 00000000..6b0b5f28
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/local/room/BookDao.kt
@@ -0,0 +1,33 @@
+package com.acclorite.books_history.data.local.room
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import androidx.room.Update
+import com.acclorite.books_history.data.local.dto.BookEntity
+
+@Dao
+interface BookDao {
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertBooks(
+ books: List
+ )
+
+ @Query(
+ """
+ SELECT *
+ FROM bookentity
+ WHERE LOWER(title) LIKE '%' || LOWER(:query) || '%'
+ """
+ )
+ suspend fun searchBooks(query: String): List
+
+ @Delete
+ suspend fun deleteBooks(books: List)
+
+ @Update
+ suspend fun updateBooks(books: List)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/local/room/BookDatabase.kt b/app/src/main/java/com/acclorite/books_history/data/local/room/BookDatabase.kt
new file mode 100644
index 00000000..91c12767
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/local/room/BookDatabase.kt
@@ -0,0 +1,14 @@
+package com.acclorite.books_history.data.local.room
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+import com.acclorite.books_history.data.local.dto.BookEntity
+
+@Database(
+ entities = [BookEntity::class],
+ version = 1,
+ exportSchema = false
+)
+abstract class BookDatabase : RoomDatabase() {
+ abstract val dao: BookDao
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapper.kt b/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapper.kt
new file mode 100644
index 00000000..e9a82de1
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapper.kt
@@ -0,0 +1,10 @@
+package com.acclorite.books_history.data.mapper
+
+import com.acclorite.books_history.data.local.dto.BookEntity
+import com.acclorite.books_history.domain.model.Book
+
+interface BookMapper {
+ fun Book.toBookEntity(): BookEntity
+
+ fun BookEntity.toBook(): Book
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapperImpl.kt b/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapperImpl.kt
new file mode 100644
index 00000000..e4982442
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/mapper/BookMapperImpl.kt
@@ -0,0 +1,15 @@
+package com.acclorite.books_history.data.mapper
+
+import com.acclorite.books_history.data.local.dto.BookEntity
+import com.acclorite.books_history.domain.model.Book
+import javax.inject.Inject
+
+class BookMapperImpl @Inject constructor(): BookMapper {
+ override fun Book.toBookEntity(): BookEntity {
+ TODO("Not yet implemented")
+ }
+
+ override fun BookEntity.toBook(): Book {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/repository/BookRepositoryImpl.kt b/app/src/main/java/com/acclorite/books_history/data/repository/BookRepositoryImpl.kt
new file mode 100644
index 00000000..ff022f7f
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/repository/BookRepositoryImpl.kt
@@ -0,0 +1,46 @@
+package com.acclorite.books_history.data.repository
+
+import androidx.datastore.preferences.core.Preferences
+import com.acclorite.books_history.data.local.data_store.DataStore
+import com.acclorite.books_history.data.local.room.BookDao
+import com.acclorite.books_history.data.mapper.toBookEntity
+import com.acclorite.books_history.domain.model.Book
+import com.acclorite.books_history.domain.repository.BookRepository
+import com.acclorite.books_history.util.Resource
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class BookRepositoryImpl @Inject constructor(
+ private val database: BookDao,
+ private val dataStore: DataStore
+): BookRepository {
+
+ override suspend fun getBooks(query: String): Flow>> {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun insertBooks(books: List) {
+ database.insertBooks(books.map { it.toBookEntity() })
+ }
+
+ override suspend fun updateBooks(books: List) {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun deleteBooks(books: List) {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun retrieveDataFromDataStore(
+ key: Preferences.Key,
+ defaultValue: T
+ ): Flow {
+ return dataStore.getData(key, defaultValue)
+ }
+
+ override suspend fun putDataToDataStore(key: Preferences.Key, value: T) {
+ dataStore.putData(key, value)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/data/use_case/ChangeLanguageImpl.kt b/app/src/main/java/com/acclorite/books_history/data/use_case/ChangeLanguageImpl.kt
new file mode 100644
index 00000000..b07f56e2
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/data/use_case/ChangeLanguageImpl.kt
@@ -0,0 +1,23 @@
+package com.acclorite.books_history.data.use_case
+
+import androidx.activity.ComponentActivity
+import com.acclorite.books_history.domain.use_case.ChangeLanguage
+import java.util.Locale
+import javax.inject.Inject
+
+class ChangeLanguageImpl @Inject constructor() : ChangeLanguage {
+ override fun execute(language: String, activity: ComponentActivity) {
+ val config = activity.resources.configuration
+ val resources = activity.resources
+ val locale = Locale(language)
+
+ Locale.setDefault(locale)
+ config.setLocale(locale)
+
+ activity.createConfigurationContext(config)
+ resources.updateConfiguration(
+ config,
+ resources.displayMetrics
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/domain/model/Book.kt b/app/src/main/java/com/acclorite/books_history/domain/model/Book.kt
new file mode 100644
index 00000000..243945c8
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/domain/model/Book.kt
@@ -0,0 +1,17 @@
+package com.acclorite.books_history.domain.model
+
+import android.graphics.Bitmap
+import java.io.File
+
+data class Book(
+ val id: Int,
+ val title: String,
+ val author: String,
+ val description: String?,
+ val text: List = emptyList(),
+ val progress: Float,
+ val file: File?,
+ val lastOpened: Long?,
+ val category: Category,
+ val coverImage: Bitmap?
+)
diff --git a/app/src/main/java/com/acclorite/books_history/domain/model/Category.kt b/app/src/main/java/com/acclorite/books_history/domain/model/Category.kt
new file mode 100644
index 00000000..55c56261
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/domain/model/Category.kt
@@ -0,0 +1,5 @@
+package com.acclorite.books_history.domain.model
+
+enum class Category {
+ READING, ALREADY_READ, PLANNING, DROPPED
+}
diff --git a/app/src/main/java/com/acclorite/books_history/domain/model/FormattedLine.kt b/app/src/main/java/com/acclorite/books_history/domain/model/FormattedLine.kt
new file mode 100644
index 00000000..afadef0c
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/domain/model/FormattedLine.kt
@@ -0,0 +1,15 @@
+package com.acclorite.books_history.domain.model
+
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.sp
+import java.util.UUID
+
+@Immutable
+data class FormattedLine(
+ val line: String,
+ val style: TextStyle = TextStyle(),
+ val textSize: TextUnit = 0.sp,
+ val id: String = UUID.randomUUID().toString()
+)
diff --git a/app/src/main/java/com/acclorite/books_history/domain/repository/BookRepository.kt b/app/src/main/java/com/acclorite/books_history/domain/repository/BookRepository.kt
new file mode 100644
index 00000000..8a830a1a
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/domain/repository/BookRepository.kt
@@ -0,0 +1,35 @@
+package com.acclorite.books_history.domain.repository
+
+import androidx.datastore.preferences.core.Preferences
+import com.acclorite.books_history.domain.model.Book
+import com.acclorite.books_history.util.Resource
+import kotlinx.coroutines.flow.Flow
+
+interface BookRepository {
+
+ suspend fun getBooks(
+ query: String
+ ): Flow>>
+
+ suspend fun insertBooks(
+ books: List
+ )
+
+ suspend fun updateBooks(
+ books: List
+ )
+
+ suspend fun deleteBooks(
+ books: List
+ )
+
+ suspend fun retrieveDataFromDataStore(
+ key: Preferences.Key,
+ defaultValue: T
+ ): Flow
+
+ suspend fun putDataToDataStore(
+ key: Preferences.Key,
+ value: T
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/domain/use_case/ChangeLanguage.kt b/app/src/main/java/com/acclorite/books_history/domain/use_case/ChangeLanguage.kt
new file mode 100644
index 00000000..957cee71
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/domain/use_case/ChangeLanguage.kt
@@ -0,0 +1,11 @@
+package com.acclorite.books_history.domain.use_case
+
+import androidx.activity.ComponentActivity
+import androidx.annotation.Size
+
+interface ChangeLanguage {
+ fun execute(
+ @Size(max = 2) language: String,
+ activity: ComponentActivity
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/presentation/MainViewModel.kt b/app/src/main/java/com/acclorite/books_history/presentation/MainViewModel.kt
new file mode 100644
index 00000000..0e042594
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/presentation/MainViewModel.kt
@@ -0,0 +1,22 @@
+package com.acclorite.books_history.presentation
+
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import com.acclorite.books_history.domain.repository.BookRepository
+import com.acclorite.books_history.domain.use_case.ChangeLanguage
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+/**
+ * Stores all variables such as theme, language etc
+ */
+@HiltViewModel
+class MainViewModel @Inject constructor(
+ private val stateHandle: SavedStateHandle,
+ private val repository: BookRepository,
+
+ private val changeLanguage: ChangeLanguage
+) : ViewModel() {
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/presentation/Navigation.kt b/app/src/main/java/com/acclorite/books_history/presentation/Navigation.kt
new file mode 100644
index 00000000..96f0f110
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/presentation/Navigation.kt
@@ -0,0 +1,208 @@
+package com.acclorite.books_history.presentation
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.BackHandler
+import androidx.activity.viewModels
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.EnterTransition
+import androidx.compose.animation.ExitTransition
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.lifecycle.AbstractSavedStateViewModelFactory
+import androidx.lifecycle.SavedStateHandle
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.createSavedStateHandle
+import androidx.lifecycle.viewModelScope
+import androidx.savedstate.SavedStateRegistryOwner
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import dagger.hilt.android.lifecycle.HiltViewModel
+import dagger.hilt.android.lifecycle.withCreationCallback
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+
+private const val CURRENT_SCREEN = "current_screen"
+private const val BACKSTACK = "back_stack"
+
+/**
+ * All screens are listed here, later each screen will be passed as a param for [Navigator.composable] function.
+ */
+enum class Screen {
+ LIBRARY,
+ HISTORY,
+ BROWSE,
+
+
+}
+
+data class Argument(
+ val key: String,
+ val arg: Any?
+)
+
+
+/**
+ * Navigator. Using for navigation between screens.
+ *
+ * [Navigator.currentScreen] param represents current [Screen].
+ * [Navigator.navigate] navigates to [Screen] passed as param.
+ */
+@HiltViewModel(assistedFactory = Navigator.Factory::class)
+class Navigator @AssistedInject constructor(
+ private val savedStateHandle: SavedStateHandle,
+ @Assisted startScreen: Screen
+) : ViewModel() {
+
+ private val currentScreen = savedStateHandle.getStateFlow(CURRENT_SCREEN, startScreen)
+ private val backStack = savedStateHandle.getStateFlow(BACKSTACK, mutableListOf())
+ private val arguments = mutableStateListOf()
+
+ private fun putArgument(argument: Argument) {
+ var found = false
+
+ for ((index, arg) in arguments.withIndex()) {
+ if (arg.key == argument.key) {
+ arguments[index] = argument
+ found = true
+ break
+ }
+ }
+
+ if (!found) {
+ arguments.add(argument)
+ }
+ }
+
+ fun retrieveArgument(key: String): Any? {
+ for (arg in arguments) {
+ if (arg.key == key) {
+ return arg.arg
+ }
+ }
+ return null
+ }
+
+ fun navigate(screen: Screen, vararg args: Argument) =
+ viewModelScope.launch(Dispatchers.Default) {
+ backStack.value.add(currentScreen.value)
+
+ args.forEach {
+ putArgument(it)
+ }
+
+ savedStateHandle[CURRENT_SCREEN] = screen
+ }
+
+ fun navigateBack() = viewModelScope.launch(Dispatchers.Default) {
+ if (canGoBack()) {
+ savedStateHandle[CURRENT_SCREEN] = backStack.value.last()
+ backStack.value.removeLast()
+ }
+ }
+
+ fun canGoBack(): Boolean {
+ return backStack.value.isNotEmpty()
+ }
+
+ fun clearBackStack() {
+ backStack.value.clear()
+ }
+
+ fun getCurrentScreen(): StateFlow {
+ return currentScreen
+ }
+
+ fun init(startScreen: Screen) {
+ savedStateHandle[CURRENT_SCREEN] = startScreen
+ }
+
+ /**
+ * Animated Screen. Using in [NavigationHost]. Be sure to not use the same [screen] parameter twice, it'll override the highest one in your code.
+ *
+ * @param screen The [Screen] that represents [content].
+ * @param enterAnim Enter Animation.
+ * @param exitAnim Exit Animation.
+ * @param content The Screen content to show when [Navigator.currentScreen] equals [screen].
+ */
+ @SuppressLint("ComposableNaming")
+ @Composable
+ fun composable(
+ screen: Screen,
+ enterAnim: EnterTransition = fadeIn(tween(300)),
+ exitAnim: ExitTransition = fadeOut(tween(300)),
+ content: @Composable () -> Unit
+ ) {
+ AnimatedVisibility(
+ visible = getCurrentScreen().collectAsState().value == screen,
+ enter = enterAnim,
+ exit = exitAnim,
+ label = screen.toString()
+ ) {
+ content()
+ }
+ }
+
+
+ @AssistedFactory
+ interface Factory {
+ fun create(startScreen: Screen): Navigator
+ }
+}
+
+/**
+ * Navigation Host. Contains [Navigator.composable]s in [content].
+ *
+ * @param startScreen Start Screen. Be sure to pass [Screen] that uses in one of your [Navigator.composable]s.
+ * @param colorBetweenAnimations The color, that using between animations, recommended to set this to background or navigation bar color.
+ * @param content Content of the [NavigationHost]. Highly recommended to use [Navigator.composable].
+ */
+
+@Composable
+fun NavigationHost(
+ startScreen: Screen,
+ activity: ComponentActivity,
+ colorBetweenAnimations: Color = MaterialTheme.colorScheme.surface,
+ content: @Composable Navigator.() -> Unit
+) {
+ activity.apply {
+ val navigator by viewModels(
+ extrasProducer = {
+ defaultViewModelCreationExtras.withCreationCallback { factory ->
+ factory.create(startScreen)
+ }
+ }
+ )
+
+ BackHandler {
+ if (navigator.canGoBack()) {
+ navigator.navigateBack()
+ } else {
+ activity.finishAffinity()
+ }
+ }
+
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(colorBetweenAnimations)
+ )
+
+ content(navigator)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/util/BookApplication.kt b/app/src/main/java/com/acclorite/books_history/util/BookApplication.kt
new file mode 100644
index 00000000..efc2af1c
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/util/BookApplication.kt
@@ -0,0 +1,7 @@
+package com.acclorite.books_history.util
+
+import android.app.Application
+import dagger.hilt.android.HiltAndroidApp
+
+@HiltAndroidApp
+class BookApplication : Application()
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/util/Constants.kt b/app/src/main/java/com/acclorite/books_history/util/Constants.kt
new file mode 100644
index 00000000..3d612eeb
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/util/Constants.kt
@@ -0,0 +1,5 @@
+package com.acclorite.books_history.util
+
+object Constants {
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/util/DataStoreConstants.kt b/app/src/main/java/com/acclorite/books_history/util/DataStoreConstants.kt
new file mode 100644
index 00000000..6174c0b0
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/util/DataStoreConstants.kt
@@ -0,0 +1,19 @@
+package com.acclorite.books_history.util
+
+import androidx.datastore.preferences.core.stringPreferencesKey
+
+object DataStoreConstants {
+ val LANGUAGE = stringPreferencesKey("language")
+ val THEME = stringPreferencesKey("theme")
+ val DARK_THEME = stringPreferencesKey("dark_theme")
+ val GUIDE = stringPreferencesKey("guide")
+
+ val BACKGROUND_COLOR = stringPreferencesKey("background_color")
+ val FONT_COLOR = stringPreferencesKey("font_color")
+ val FONT = stringPreferencesKey("font")
+ val FONT_STYLE = stringPreferencesKey("font_style")
+ val FONT_SIZE = stringPreferencesKey("font_size")
+ val LINE_HEIGHT = stringPreferencesKey("line_height")
+ val PARAGRAPH_HEIGHT = stringPreferencesKey("paragraph_height")
+ val PARAGRAPH_INDENTATION = stringPreferencesKey("paragraph_indentation")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/util/Resource.kt b/app/src/main/java/com/acclorite/books_history/util/Resource.kt
new file mode 100644
index 00000000..00ae2b9c
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/util/Resource.kt
@@ -0,0 +1,7 @@
+package com.acclorite.books_history.util
+
+sealed class Resource (val data: T? = null, val message: String? = null) {
+ class Success(data: T?): Resource(data)
+ class Error(message: String, data: T? = null): Resource(data, message)
+ class Loading(val isLoading: Boolean = true): Resource()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/acclorite/books_history/util/UIText.kt b/app/src/main/java/com/acclorite/books_history/util/UIText.kt
new file mode 100644
index 00000000..b72dcbc1
--- /dev/null
+++ b/app/src/main/java/com/acclorite/books_history/util/UIText.kt
@@ -0,0 +1,26 @@
+package com.acclorite.books_history.util
+
+import android.content.Context
+import androidx.annotation.StringRes
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+
+sealed class UIText {
+ data class StringValue(val value: String): UIText()
+ class StringResource(@StringRes val resId: Int, vararg val args: Any): UIText()
+
+ @Composable
+ fun asString(): String {
+ return when(this) {
+ is StringValue -> value
+ is StringResource -> stringResource(resId, *args)
+ }
+ }
+
+ fun asString(context: Context): String {
+ return when(this) {
+ is StringValue -> value
+ is StringResource -> context.getString(resId, *args)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index c04d61c3..9f7f942a 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -1,6 +1,5 @@
- Воскресіння Історії Книги
-
+ Історія Книги: Воскресіння
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 877bf1ce..a9cfeb1d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,7 +1,7 @@
0.0.1
- Book\'s History Resurrection
+ Book\'s History: Resurrection
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 94da8ef6..3896da22 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,10 +3,5 @@ plugins {
id("com.android.application") version "8.2.0-rc03" apply false
id("org.jetbrains.kotlin.android") version "1.9.21" apply false
id("com.google.devtools.ksp") version "1.9.21-1.0.16" apply false
-}
-
-buildscript {
- dependencies {
- classpath ("com.google.dagger:hilt-android-gradle-plugin:latest.release")
- }
+ id("com.google.dagger.hilt.android") version "2.50" apply false
}
\ No newline at end of file