0.8.0 - History Screen and Project Name change
This commit is contained in:
parent
0b3a31a183
commit
5a966e9d9d
171 changed files with 3027 additions and 1877 deletions
2
.idea/.name
generated
2
.idea/.name
generated
|
|
@ -1 +1 @@
|
||||||
Book's History Resurrection
|
Book's Story
|
||||||
11
.idea/deploymentTargetDropDown.xml
generated
11
.idea/deploymentTargetDropDown.xml
generated
|
|
@ -4,19 +4,18 @@
|
||||||
<value>
|
<value>
|
||||||
<entry key="app">
|
<entry key="app">
|
||||||
<State>
|
<State>
|
||||||
<runningDeviceTargetSelectedWithDropDown>
|
<targetSelectedWithDropDown>
|
||||||
<Target>
|
<Target>
|
||||||
<type value="RUNNING_DEVICE_TARGET" />
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
<deviceKey>
|
<deviceKey>
|
||||||
<Key>
|
<Key>
|
||||||
<type value="VIRTUAL_DEVICE_PATH" />
|
<type value="VIRTUAL_DEVICE_PATH" />
|
||||||
<value value="$USER_HOME$/.android/avd/Phone_13_.avd" />
|
<value value="C:\Users\Administrator\.android\avd\Phone_33_.avd" />
|
||||||
</Key>
|
</Key>
|
||||||
</deviceKey>
|
</deviceKey>
|
||||||
</Target>
|
</Target>
|
||||||
</runningDeviceTargetSelectedWithDropDown>
|
</targetSelectedWithDropDown>
|
||||||
<timeTargetWasSelectedWithDropDown value="2024-02-22T17:49:53.931710327Z" />
|
<timeTargetWasSelectedWithDropDown value="2024-02-29T15:05:04.852701900Z" />
|
||||||
<multipleDevicesSelectedInDropDown value="true" />
|
|
||||||
<targetsSelectedWithDialog>
|
<targetsSelectedWithDialog>
|
||||||
<Target>
|
<Target>
|
||||||
<type value="QUICK_BOOT_TARGET" />
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
|
|
|
||||||
2
.idea/gradle.xml
generated
2
.idea/gradle.xml
generated
|
|
@ -5,7 +5,7 @@
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="jbr-17" />
|
<option name="gradleJvm" value="jbr-17 (2)" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
|
|
|
||||||
2
.idea/vcs.xml
generated
2
.idea/vcs.xml
generated
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -10,15 +10,15 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.acclorite.books_history"
|
namespace = "ua.acclorite.book_story"
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.acclorite.books_history"
|
applicationId = "ua.acclorite.book_story"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "0.6.0"
|
versionName = "0.8.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|
@ -140,4 +140,7 @@ dependencies {
|
||||||
}
|
}
|
||||||
implementation("org.slf4j:slf4j-android:latest.release")
|
implementation("org.slf4j:slf4j-android:latest.release")
|
||||||
implementation("org.jsoup:jsoup:latest.release")
|
implementation("org.jsoup:jsoup:latest.release")
|
||||||
|
|
||||||
|
implementation("androidx.appcompat:appcompat:latest.release")
|
||||||
|
implementation("androidx.appcompat:appcompat-resources:latest.release")
|
||||||
}
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.acclorite.books_history
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import org.junit.Assert.*
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("com.acclorite.books_history", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,9 +17,10 @@
|
||||||
android:theme="@style/Theme.Start.Splash"
|
android:theme="@style/Theme.Start.Splash"
|
||||||
android:enableOnBackInvokedCallback="true"
|
android:enableOnBackInvokedCallback="true"
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="screenSize|screenLayout|smallestScreenSize|locale|density"
|
android:configChanges="screenSize|screenLayout|smallestScreenSize|locale|density|uiMode"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/Theme.Start.Splash">
|
android:theme="@style/Theme.Start.Splash">
|
||||||
|
|
@ -28,6 +29,16 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||||
|
android:enabled="false"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data
|
||||||
|
android:name="autoStoreLocales"
|
||||||
|
android:value="true" />
|
||||||
|
</service>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.8 KiB |
|
|
@ -1,35 +0,0 @@
|
||||||
package com.acclorite.books_history.data.di
|
|
||||||
|
|
||||||
import com.acclorite.books_history.data.local.data_store.DataStore
|
|
||||||
import com.acclorite.books_history.data.local.data_store.DataStoreImpl
|
|
||||||
import com.acclorite.books_history.data.mapper.BookMapper
|
|
||||||
import com.acclorite.books_history.data.mapper.BookMapperImpl
|
|
||||||
import com.acclorite.books_history.data.repository.BookRepositoryImpl
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.hilt.InstallIn
|
|
||||||
import dagger.hilt.components.SingletonComponent
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(SingletonComponent::class)
|
|
||||||
abstract class RepositoryModule {
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
abstract fun bindDataStore(
|
|
||||||
dataStoreImpl: DataStoreImpl
|
|
||||||
): DataStore
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun bindBookRepository(
|
|
||||||
bookRepositoryImpl: BookRepositoryImpl
|
|
||||||
): BookRepository
|
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
|
||||||
abstract fun bindBookMapper(
|
|
||||||
bookMapperImpl: BookMapperImpl
|
|
||||||
): BookMapper
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
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 {
|
|
||||||
suspend fun toBookEntity(book: Book): BookEntity
|
|
||||||
|
|
||||||
suspend fun toBook(bookEntity: BookEntity): Book
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package com.acclorite.books_history.data.parser
|
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface FileParser {
|
|
||||||
|
|
||||||
suspend fun parse(file: File): Book?
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package com.acclorite.books_history.data.parser
|
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface TextParser {
|
|
||||||
suspend fun parse(file: File): List<StringWithId>
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class DeleteBooks @Inject constructor(private val repository: BookRepository) {
|
|
||||||
|
|
||||||
suspend fun execute(books: List<Book>) {
|
|
||||||
repository.deleteBooks(books)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
|
||||||
|
|
||||||
import androidx.compose.animation.animateColorAsState
|
|
||||||
import androidx.compose.animation.core.Spring
|
|
||||||
import androidx.compose.animation.core.spring
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.RowScope
|
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.statusBars
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.acclorite.books_history.ui.DefaultTransition
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun AnimatedTopAppBar(
|
|
||||||
containerColor: Color = MaterialTheme.colorScheme.surface,
|
|
||||||
scrolledContainerColor: Color?,
|
|
||||||
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior?,
|
|
||||||
isTopBarScrolled: Boolean?,
|
|
||||||
|
|
||||||
content1Visibility: Boolean,
|
|
||||||
content1NavigationIcon: @Composable () -> Unit,
|
|
||||||
content1Title: @Composable () -> Unit,
|
|
||||||
content1Actions: @Composable RowScope.() -> Unit,
|
|
||||||
|
|
||||||
content2Visibility: Boolean,
|
|
||||||
content2NavigationIcon: @Composable () -> Unit,
|
|
||||||
content2Title: @Composable () -> Unit,
|
|
||||||
content2Actions: @Composable RowScope.() -> Unit,
|
|
||||||
|
|
||||||
content3Visibility: Boolean,
|
|
||||||
content3NavigationIcon: @Composable () -> Unit,
|
|
||||||
content3Title: @Composable () -> Unit,
|
|
||||||
content3Actions: @Composable RowScope.() -> Unit
|
|
||||||
) {
|
|
||||||
val color =
|
|
||||||
if (isTopBarScrolled == true && scrolledContainerColor != null) scrolledContainerColor
|
|
||||||
else containerColor
|
|
||||||
|
|
||||||
val animatedColor by animateColorAsState(
|
|
||||||
targetValue = color,
|
|
||||||
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
|
|
||||||
label = "TopAppBar color animation"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (scrollBehavior != null && scrolledContainerColor != null) {
|
|
||||||
val isScrolled = scrollBehavior.state.overlappedFraction > 0.01f
|
|
||||||
val statusBarPadding = with(LocalDensity.current) {
|
|
||||||
WindowInsets.statusBars.getTop(LocalDensity.current).toDp()
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(64.dp + statusBarPadding)
|
|
||||||
.background(
|
|
||||||
if (isScrolled) scrolledContainerColor
|
|
||||||
else containerColor
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
DefaultTransition(visible = content1Visibility) {
|
|
||||||
TopAppBar(
|
|
||||||
navigationIcon = content1NavigationIcon,
|
|
||||||
title = content1Title,
|
|
||||||
actions = content1Actions,
|
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = animatedColor,
|
|
||||||
scrolledContainerColor = scrolledContainerColor ?: Color.Transparent
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultTransition(visible = content2Visibility) {
|
|
||||||
TopAppBar(
|
|
||||||
navigationIcon = content2NavigationIcon,
|
|
||||||
title = content2Title,
|
|
||||||
actions = content2Actions,
|
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = animatedColor,
|
|
||||||
scrolledContainerColor = scrolledContainerColor ?: Color.Transparent
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultTransition(visible = content3Visibility) {
|
|
||||||
TopAppBar(
|
|
||||||
navigationIcon = content3NavigationIcon,
|
|
||||||
title = content3Title,
|
|
||||||
actions = content3Actions,
|
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = animatedColor,
|
|
||||||
scrolledContainerColor = scrolledContainerColor ?: Color.Transparent
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.history
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
|
||||||
import com.acclorite.books_history.presentation.screens.history.data.HistoryViewModel
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun HistoryScreen(
|
|
||||||
viewModel: HistoryViewModel = hiltViewModel(),
|
|
||||||
navigator: Navigator
|
|
||||||
) {
|
|
||||||
val state by viewModel.state.collectAsState()
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.history.data
|
|
||||||
|
|
||||||
sealed class HistoryEvent
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.history.data
|
|
||||||
|
|
||||||
data class HistoryState(
|
|
||||||
val foo: Int = 0
|
|
||||||
)
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.history.data
|
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@HiltViewModel
|
|
||||||
class HistoryViewModel @Inject constructor(
|
|
||||||
|
|
||||||
) : ViewModel() {
|
|
||||||
|
|
||||||
private val _state = MutableStateFlow(HistoryState())
|
|
||||||
val state = _state.asStateFlow()
|
|
||||||
|
|
||||||
fun onEvent(event: HistoryEvent) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.reader.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ReaderSettingsBottomSheetItem(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
title: String,
|
|
||||||
description: String,
|
|
||||||
verticalPadding: Dp = 8.dp,
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable {
|
|
||||||
onClick()
|
|
||||||
}
|
|
||||||
.padding(horizontal = 18.dp, vertical = verticalPadding),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.Start
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
fontSize = 18.sp
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
|
||||||
Text(
|
|
||||||
description,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package com.acclorite.books_history.presentation.screens.settings.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SettingsOptionItem(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
title: String,
|
|
||||||
description: String,
|
|
||||||
verticalPadding: Dp = 8.dp,
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.clickable {
|
|
||||||
onClick()
|
|
||||||
}
|
|
||||||
.padding(horizontal = 16.dp, vertical = verticalPadding),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.Start
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
fontSize = 18.sp
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
|
||||||
Text(
|
|
||||||
description,
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
package com.acclorite.books_history
|
package ua.acclorite.book_story
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.slideInHorizontally
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
|
@ -15,33 +19,29 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.presentation.NavigationHost
|
|
||||||
import com.acclorite.books_history.presentation.Screen
|
|
||||||
import com.acclorite.books_history.presentation.components.BottomNavigationBar
|
|
||||||
import com.acclorite.books_history.presentation.data.MainEvent
|
|
||||||
import com.acclorite.books_history.presentation.data.MainViewModel
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.BookInfoScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.browse.BrowseScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.history.HistoryScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.library.LibraryScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.reader.ReaderScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.settings.SettingsScreen
|
|
||||||
import com.acclorite.books_history.presentation.screens.settings.nested.appearance.AppearanceSettings
|
|
||||||
import com.acclorite.books_history.presentation.screens.settings.nested.general.GeneralSettings
|
|
||||||
import com.acclorite.books_history.ui.BooksHistoryResurrectionTheme
|
|
||||||
import com.acclorite.books_history.ui.DefaultTransition
|
|
||||||
import com.acclorite.books_history.ui.Transitions
|
|
||||||
import com.acclorite.books_history.ui.isDark
|
|
||||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.presentation.NavigationHost
|
||||||
|
import ua.acclorite.book_story.presentation.Screen
|
||||||
|
import ua.acclorite.book_story.presentation.components.BottomNavigationBar
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainEvent
|
||||||
|
import ua.acclorite.book_story.presentation.data.MainViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.BookInfoScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.browse.BrowseScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.HistoryScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.LibraryScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.reader.ReaderScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.SettingsScreen
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.appearance.AppearanceSettings
|
||||||
|
import ua.acclorite.book_story.presentation.screens.settings.nested.general.GeneralSettings
|
||||||
|
import ua.acclorite.book_story.ui.BooksHistoryResurrectionTheme
|
||||||
|
import ua.acclorite.book_story.ui.Transitions
|
||||||
|
import ua.acclorite.book_story.ui.isDark
|
||||||
|
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val mainViewModel: MainViewModel by viewModels()
|
private val mainViewModel: MainViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -70,14 +70,17 @@ class MainActivity : ComponentActivity() {
|
||||||
if (!updating) {
|
if (!updating) {
|
||||||
NavigationHost(startScreen = Screen.LIBRARY) {
|
NavigationHost(startScreen = Screen.LIBRARY) {
|
||||||
val currentScreen by this.getCurrentScreen().collectAsState()
|
val currentScreen by this.getCurrentScreen().collectAsState()
|
||||||
DefaultTransition(
|
AnimatedVisibility(
|
||||||
visible = currentScreen == Screen.LIBRARY ||
|
visible = currentScreen == Screen.LIBRARY ||
|
||||||
currentScreen == Screen.HISTORY ||
|
currentScreen == Screen.HISTORY ||
|
||||||
currentScreen == Screen.BROWSE
|
currentScreen == Screen.BROWSE,
|
||||||
|
enter = fadeIn(tween(200)) +
|
||||||
|
slideInHorizontally(tween(200)) { it / 15 },
|
||||||
|
exit = Transitions.SlidingTransitionOut
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
BottomNavigationBar(navigator = this)
|
BottomNavigationBar(navigator = this@NavigationHost)
|
||||||
},
|
},
|
||||||
containerColor = MaterialTheme.colorScheme.surface
|
containerColor = MaterialTheme.colorScheme.surface
|
||||||
) {
|
) {
|
||||||
|
|
@ -122,8 +125,7 @@ class MainActivity : ComponentActivity() {
|
||||||
exitAnim = Transitions.SlidingTransitionOut
|
exitAnim = Transitions.SlidingTransitionOut
|
||||||
) {
|
) {
|
||||||
ReaderScreen(
|
ReaderScreen(
|
||||||
navigator = this@NavigationHost,
|
navigator = this@NavigationHost
|
||||||
mainViewModel = mainViewModel
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +147,6 @@ class MainActivity : ComponentActivity() {
|
||||||
exitAnim = Transitions.SlidingTransitionOut
|
exitAnim = Transitions.SlidingTransitionOut
|
||||||
) {
|
) {
|
||||||
GeneralSettings(
|
GeneralSettings(
|
||||||
mainViewModel = mainViewModel,
|
|
||||||
navigator = this@NavigationHost
|
navigator = this@NavigationHost
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +156,6 @@ class MainActivity : ComponentActivity() {
|
||||||
exitAnim = Transitions.SlidingTransitionOut
|
exitAnim = Transitions.SlidingTransitionOut
|
||||||
) {
|
) {
|
||||||
AppearanceSettings(
|
AppearanceSettings(
|
||||||
mainViewModel = mainViewModel,
|
|
||||||
navigator = this@NavigationHost
|
navigator = this@NavigationHost
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -165,8 +165,7 @@ class MainActivity : ComponentActivity() {
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(
|
.background(
|
||||||
if (darkTheme.isDark()) Color.Black
|
MaterialTheme.colorScheme.surface
|
||||||
else Color.White
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package com.acclorite.books_history.data.di
|
package ua.acclorite.book_story.data.di
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import com.acclorite.books_history.data.local.room.BookDao
|
|
||||||
import com.acclorite.books_history.data.local.room.BookDatabase
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import ua.acclorite.book_story.data.local.room.BookDao
|
||||||
|
import ua.acclorite.book_story.data.local.room.BookDatabase
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package ua.acclorite.book_story.data.di
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import ua.acclorite.book_story.data.local.data_store.DataStore
|
||||||
|
import ua.acclorite.book_story.data.local.data_store.DataStoreImpl
|
||||||
|
import ua.acclorite.book_story.data.mapper.BookMapper
|
||||||
|
import ua.acclorite.book_story.data.mapper.BookMapperImpl
|
||||||
|
import ua.acclorite.book_story.data.mapper.HistoryMapper
|
||||||
|
import ua.acclorite.book_story.data.mapper.HistoryMapperImpl
|
||||||
|
import ua.acclorite.book_story.data.repository.BookRepositoryImpl
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
abstract class RepositoryModule {
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindDataStore(
|
||||||
|
dataStoreImpl: DataStoreImpl
|
||||||
|
): DataStore
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
abstract fun bindBookRepository(
|
||||||
|
bookRepositoryImpl: BookRepositoryImpl
|
||||||
|
): BookRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
abstract fun bindBookMapper(
|
||||||
|
bookMapperImpl: BookMapperImpl
|
||||||
|
): BookMapper
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
abstract fun bindHistoryMapper(
|
||||||
|
historyMapperImpl: HistoryMapperImpl
|
||||||
|
): HistoryMapper
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.data.local.data_store
|
package ua.acclorite.book_story.data.local.data_store
|
||||||
|
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.data.local.data_store
|
package ua.acclorite.book_story.data.local.data_store
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.acclorite.books_history.data.local.dto
|
package ua.acclorite.book_story.data.local.dto
|
||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.acclorite.books_history.domain.model.Category
|
import ua.acclorite.book_story.domain.model.Category
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class BookEntity(
|
data class BookEntity(
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package ua.acclorite.book_story.data.local.dto
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class HistoryEntity(
|
||||||
|
@PrimaryKey(true)
|
||||||
|
val id: Int? = null,
|
||||||
|
val bookId: Int,
|
||||||
|
val time: Long
|
||||||
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.data.local.room
|
package ua.acclorite.book_story.data.local.room
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
import androidx.room.Delete
|
||||||
|
|
@ -6,7 +6,8 @@ import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
import androidx.room.Update
|
||||||
import com.acclorite.books_history.data.local.dto.BookEntity
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
|
import ua.acclorite.book_story.data.local.dto.HistoryEntity
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface BookDao {
|
interface BookDao {
|
||||||
|
|
@ -35,4 +36,22 @@ interface BookDao {
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
suspend fun updateBooks(books: List<BookEntity>)
|
suspend fun updateBooks(books: List<BookEntity>)
|
||||||
|
|
||||||
|
|
||||||
|
@Query("SELECT * FROM historyentity")
|
||||||
|
suspend fun getHistory(): List<HistoryEntity>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertHistory(
|
||||||
|
history: List<HistoryEntity>
|
||||||
|
)
|
||||||
|
|
||||||
|
@Query("DELETE FROM historyentity")
|
||||||
|
suspend fun deleteWholeHistory()
|
||||||
|
|
||||||
|
@Query("DELETE FROM historyentity WHERE bookId = :bookId")
|
||||||
|
suspend fun deleteBookHistory(bookId: Int)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun deleteHistory(history: List<HistoryEntity>)
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package ua.acclorite.book_story.data.local.room
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
|
import ua.acclorite.book_story.data.local.dto.HistoryEntity
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
entities = [
|
||||||
|
BookEntity::class,
|
||||||
|
HistoryEntity::class
|
||||||
|
],
|
||||||
|
version = 1,
|
||||||
|
exportSchema = false
|
||||||
|
)
|
||||||
|
abstract class BookDatabase : RoomDatabase() {
|
||||||
|
abstract val dao: BookDao
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ua.acclorite.book_story.data.mapper
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
|
||||||
|
interface BookMapper {
|
||||||
|
suspend fun toBookEntity(book: Book): BookEntity
|
||||||
|
|
||||||
|
suspend fun toBook(bookEntity: BookEntity): Book
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
package com.acclorite.books_history.data.mapper
|
package ua.acclorite.book_story.data.mapper
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.data.local.dto.BookEntity
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
import com.acclorite.books_history.data.parser.EpubFileParser
|
import ua.acclorite.book_story.data.parser.EpubFileParser
|
||||||
import com.acclorite.books_history.data.parser.PdfFileParser
|
import ua.acclorite.book_story.data.parser.PdfFileParser
|
||||||
import com.acclorite.books_history.data.parser.TxtFileParser
|
import ua.acclorite.book_story.data.parser.TxtFileParser
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.util.UIText
|
import ua.acclorite.book_story.util.UIText
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ua.acclorite.book_story.data.mapper
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.data.local.dto.HistoryEntity
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
|
||||||
|
interface HistoryMapper {
|
||||||
|
suspend fun toHistoryEntity(history: History): HistoryEntity
|
||||||
|
|
||||||
|
suspend fun toHistory(historyEntity: HistoryEntity, book: Book): History
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package ua.acclorite.book_story.data.mapper
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.data.local.dto.HistoryEntity
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class HistoryMapperImpl @Inject constructor() : HistoryMapper {
|
||||||
|
override suspend fun toHistoryEntity(history: History): HistoryEntity {
|
||||||
|
return HistoryEntity(
|
||||||
|
id = history.id,
|
||||||
|
bookId = history.book.id ?: 0,
|
||||||
|
time = history.time
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun toHistory(historyEntity: HistoryEntity, book: Book): History {
|
||||||
|
return History(
|
||||||
|
historyEntity.id,
|
||||||
|
book = book,
|
||||||
|
time = historyEntity.time
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import kotlinx.coroutines.Dispatchers
|
||||||
import com.acclorite.books_history.domain.model.Category
|
import kotlinx.coroutines.withContext
|
||||||
import com.acclorite.books_history.util.UIText
|
|
||||||
import nl.siegmann.epublib.epub.EpubReader
|
import nl.siegmann.epublib.epub.EpubReader
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.Category
|
||||||
|
import ua.acclorite.book_story.util.UIText
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -18,7 +20,9 @@ class EpubFileParser @Inject constructor() : FileParser {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val epubReader = EpubReader()
|
val epubReader = EpubReader()
|
||||||
val book = epubReader.readEpub(FileInputStream(file))
|
val book = withContext(Dispatchers.IO) {
|
||||||
|
epubReader.readEpub(FileInputStream(file))
|
||||||
|
}
|
||||||
|
|
||||||
val metadata = book.metadata
|
val metadata = book.metadata
|
||||||
val author = UIText.StringValue(metadata.authors.joinToString(", "))
|
val author = UIText.StringValue(metadata.authors.joinToString(", "))
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import nl.siegmann.epublib.epub.EpubReader
|
import nl.siegmann.epublib.epub.EpubReader
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
|
@ -18,7 +20,9 @@ class EpubTextParser @Inject constructor() : TextParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val book = EpubReader().readEpub(FileInputStream(file))
|
val book = withContext(Dispatchers.IO) {
|
||||||
|
EpubReader().readEpub(FileInputStream(file))
|
||||||
|
}
|
||||||
val unformattedText = StringBuilder()
|
val unformattedText = StringBuilder()
|
||||||
|
|
||||||
for (spineReference in book.spine.spineReferences) {
|
for (spineReference in book.spine.spineReferences) {
|
||||||
|
|
@ -28,7 +32,9 @@ class EpubTextParser @Inject constructor() : TextParser {
|
||||||
BufferedReader(InputStreamReader(inputStream, Charset.forName("UTF-8")))
|
BufferedReader(InputStreamReader(inputStream, Charset.forName("UTF-8")))
|
||||||
var line: String?
|
var line: String?
|
||||||
|
|
||||||
while (reader.readLine().also { line = it } != null) {
|
while (withContext(Dispatchers.IO) {
|
||||||
|
reader.readLine()
|
||||||
|
}.also { line = it } != null) {
|
||||||
unformattedText.append(line).append("\n")
|
unformattedText.append(line).append("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface FileParser {
|
||||||
|
|
||||||
|
suspend fun parse(file: File): Book?
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.acclorite.books_history.R
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.domain.model.Category
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import com.acclorite.books_history.util.UIText
|
|
||||||
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
|
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
|
||||||
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
||||||
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.Category
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
|
import ua.acclorite.book_story.util.UIText
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
|
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
|
||||||
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
||||||
import com.tom_roush.pdfbox.text.PDFTextStripper
|
import com.tom_roush.pdfbox.text.PDFTextStripper
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface TextParser {
|
||||||
|
suspend fun parse(file: File): List<StringWithId>
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.domain.model.Category
|
import ua.acclorite.book_story.domain.model.Category
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
import com.acclorite.books_history.util.UIText
|
import ua.acclorite.book_story.util.UIText
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.acclorite.books_history.data.parser
|
package ua.acclorite.book_story.data.parser
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
|
|
@ -16,11 +18,13 @@ class TxtTextParser @Inject constructor() : TextParser {
|
||||||
return try {
|
return try {
|
||||||
val formattedLines = mutableListOf<StringWithId>()
|
val formattedLines = mutableListOf<StringWithId>()
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
BufferedReader(FileReader(file)).forEachLine { line ->
|
BufferedReader(FileReader(file)).forEachLine { line ->
|
||||||
formattedLines.add(
|
formattedLines.add(
|
||||||
StringWithId(line)
|
StringWithId(line)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
formattedLines
|
formattedLines
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
@ -1,25 +1,27 @@
|
||||||
package com.acclorite.books_history.data.repository
|
package ua.acclorite.book_story.data.repository
|
||||||
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import com.acclorite.books_history.data.local.data_store.DataStore
|
|
||||||
import com.acclorite.books_history.data.local.dto.BookEntity
|
|
||||||
import com.acclorite.books_history.data.local.room.BookDao
|
|
||||||
import com.acclorite.books_history.data.mapper.BookMapper
|
|
||||||
import com.acclorite.books_history.data.parser.EpubFileParser
|
|
||||||
import com.acclorite.books_history.data.parser.EpubTextParser
|
|
||||||
import com.acclorite.books_history.data.parser.PdfFileParser
|
|
||||||
import com.acclorite.books_history.data.parser.PdfTextParser
|
|
||||||
import com.acclorite.books_history.data.parser.TxtFileParser
|
|
||||||
import com.acclorite.books_history.data.parser.TxtTextParser
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.domain.model.NullableBook
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import com.acclorite.books_history.util.Constants
|
|
||||||
import com.acclorite.books_history.util.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import ua.acclorite.book_story.data.local.data_store.DataStore
|
||||||
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
|
import ua.acclorite.book_story.data.local.room.BookDao
|
||||||
|
import ua.acclorite.book_story.data.mapper.BookMapper
|
||||||
|
import ua.acclorite.book_story.data.mapper.HistoryMapper
|
||||||
|
import ua.acclorite.book_story.data.parser.EpubFileParser
|
||||||
|
import ua.acclorite.book_story.data.parser.EpubTextParser
|
||||||
|
import ua.acclorite.book_story.data.parser.PdfFileParser
|
||||||
|
import ua.acclorite.book_story.data.parser.PdfTextParser
|
||||||
|
import ua.acclorite.book_story.data.parser.TxtFileParser
|
||||||
|
import ua.acclorite.book_story.data.parser.TxtTextParser
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import ua.acclorite.book_story.domain.model.NullableBook
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Constants
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -30,6 +32,7 @@ class BookRepositoryImpl @Inject constructor(
|
||||||
private val dataStore: DataStore,
|
private val dataStore: DataStore,
|
||||||
|
|
||||||
private val bookMapper: BookMapper,
|
private val bookMapper: BookMapper,
|
||||||
|
private val historyMapper: HistoryMapper,
|
||||||
|
|
||||||
private val txtFileParser: TxtFileParser,
|
private val txtFileParser: TxtFileParser,
|
||||||
private val pdfFileParser: PdfFileParser,
|
private val pdfFileParser: PdfFileParser,
|
||||||
|
|
@ -233,6 +236,38 @@ class BookRepositoryImpl @Inject constructor(
|
||||||
emit(Resource.Success(books))
|
emit(Resource.Success(books))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun insertHistory(history: List<History>) {
|
||||||
|
database.insertHistory(history.map { historyMapper.toHistoryEntity(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getHistory(): Flow<Resource<List<History>>> {
|
||||||
|
return flow {
|
||||||
|
emit(Resource.Loading(true))
|
||||||
|
|
||||||
|
val history = database.getHistory()
|
||||||
|
emit(
|
||||||
|
Resource.Success(
|
||||||
|
data = history.map {
|
||||||
|
val book = database.findBookById(it.bookId)
|
||||||
|
historyMapper.toHistory(it, bookMapper.toBook(book))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteWholeHistory() {
|
||||||
|
database.deleteWholeHistory()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteBookHistory(bookId: Int) {
|
||||||
|
database.deleteBookHistory(bookId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteHistory(history: List<History>) {
|
||||||
|
database.deleteHistory(history.map { historyMapper.toHistoryEntity(it) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -248,3 +283,4 @@ class BookRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.acclorite.books_history.util.UIText
|
import ua.acclorite.book_story.util.UIText
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
enum class Category {
|
enum class Category {
|
||||||
READING, ALREADY_READ, PLANNING, DROPPED
|
READING, ALREADY_READ, PLANNING, DROPPED
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import com.acclorite.books_history.util.UIText
|
import ua.acclorite.book_story.util.UIText
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class FontWithName(
|
data class FontWithName(
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class GroupedHistory(
|
||||||
|
val title: String,
|
||||||
|
val history: List<History>
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class History(
|
||||||
|
val id: Int?,
|
||||||
|
val book: Book,
|
||||||
|
val time: Long
|
||||||
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
sealed class NullableBook(val book: Pair<Book, Boolean>?, val fileName: String?) {
|
sealed class NullableBook(val book: Pair<Book, Boolean>?, val fileName: String?) {
|
||||||
class NotNull(book: Pair<Book, Boolean>) : NullableBook(book, null)
|
class NotNull(book: Pair<Book, Boolean>) : NullableBook(book, null)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.domain.model
|
package ua.acclorite.book_story.domain.model
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package com.acclorite.books_history.domain.repository
|
package ua.acclorite.book_story.domain.repository
|
||||||
|
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import com.acclorite.books_history.data.local.dto.BookEntity
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.domain.model.NullableBook
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import com.acclorite.books_history.util.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.data.local.dto.BookEntity
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import ua.acclorite.book_story.domain.model.NullableBook
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
interface BookRepository {
|
interface BookRepository {
|
||||||
|
|
@ -50,4 +51,17 @@ interface BookRepository {
|
||||||
suspend fun getBookTextFromFile(file: File): Flow<Resource<List<StringWithId>>>
|
suspend fun getBookTextFromFile(file: File): Flow<Resource<List<StringWithId>>>
|
||||||
|
|
||||||
suspend fun getBooksFromFiles(files: List<File>): Flow<Resource<List<NullableBook>>>
|
suspend fun getBooksFromFiles(files: List<File>): Flow<Resource<List<NullableBook>>>
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun insertHistory(history: List<History>)
|
||||||
|
|
||||||
|
suspend fun getHistory(): Flow<Resource<List<History>>>
|
||||||
|
|
||||||
|
suspend fun deleteWholeHistory()
|
||||||
|
|
||||||
|
suspend fun deleteBookHistory(bookId: Int)
|
||||||
|
|
||||||
|
suspend fun deleteHistory(
|
||||||
|
history: List<History>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import com.acclorite.books_history.util.DataStoreConstants
|
import ua.acclorite.book_story.util.DataStoreConstants
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ChangeLanguage @Inject constructor(private val repository: BookRepository) {
|
class ChangeLanguage @Inject constructor(private val repository: BookRepository) {
|
||||||
|
@SuppressLint("AppBundleLocaleChanges")
|
||||||
suspend fun execute(language: String, activity: ComponentActivity) {
|
suspend fun execute(language: String, activity: ComponentActivity) {
|
||||||
val config = activity.resources.configuration
|
val config = activity.resources.configuration
|
||||||
val resources = activity.resources
|
val resources = activity.resources
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class DeleteBooks @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
||||||
|
suspend fun execute(books: List<Book>) {
|
||||||
|
repository.deleteBooks(books)
|
||||||
|
books.forEach {
|
||||||
|
if (it.id != null) {
|
||||||
|
repository.deleteBookHistory(it.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class DeleteHistory @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
||||||
|
suspend fun execute(history: List<History>) {
|
||||||
|
repository.deleteHistory(history)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class DeleteWholeHistory @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
||||||
|
suspend fun execute() {
|
||||||
|
repository.deleteWholeHistory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FastGetBooks @Inject constructor(private val repository: BookRepository) {
|
class FastGetBooks @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
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 kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GetBooks @Inject constructor(private val repository: BookRepository) {
|
class GetBooks @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.NullableBook
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import com.acclorite.books_history.util.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.model.NullableBook
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GetDatastore @Inject constructor(private val repository: BookRepository) {
|
class GetDatastore @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import com.acclorite.books_history.util.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class GetHistory @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
||||||
|
suspend fun execute(): Flow<Resource<List<History>>> {
|
||||||
|
return repository.getHistory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.StringWithId
|
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
|
||||||
import com.acclorite.books_history.util.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import ua.acclorite.book_story.domain.model.StringWithId
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import ua.acclorite.book_story.util.Resource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class InsertBooks @Inject constructor(private val repository: BookRepository) {
|
class InsertBooks @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
|
import ua.acclorite.book_story.domain.model.History
|
||||||
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class InsertHistory @Inject constructor(private val repository: BookRepository) {
|
||||||
|
suspend fun execute(history: List<History>) {
|
||||||
|
repository.insertHistory(history)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SetDatastore @Inject constructor(private val repository: BookRepository) {
|
class SetDatastore @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.acclorite.books_history.domain.use_case
|
package ua.acclorite.book_story.domain.use_case
|
||||||
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.domain.repository.BookRepository
|
import ua.acclorite.book_story.domain.repository.BookRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class UpdateBooks @Inject constructor(private val repository: BookRepository) {
|
class UpdateBooks @Inject constructor(private val repository: BookRepository) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation
|
package ua.acclorite.book_story.presentation
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -20,7 +20,6 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.acclorite.books_history.ui.Transitions
|
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
|
@ -29,6 +28,7 @@ import dagger.hilt.android.lifecycle.withCreationCallback
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import ua.acclorite.book_story.ui.Transitions
|
||||||
|
|
||||||
|
|
||||||
private const val CURRENT_SCREEN = "current_screen"
|
private const val CURRENT_SCREEN = "current_screen"
|
||||||
|
|
@ -155,8 +155,8 @@ class Navigator @AssistedInject constructor(
|
||||||
@Composable
|
@Composable
|
||||||
fun composable(
|
fun composable(
|
||||||
screen: Screen,
|
screen: Screen,
|
||||||
enterAnim: EnterTransition = Transitions.DefaultTransitionIn,
|
enterAnim: EnterTransition = Transitions.FadeTransitionIn,
|
||||||
exitAnim: ExitTransition = Transitions.DefaultTransitionOut,
|
exitAnim: ExitTransition = Transitions.FadeTransitionOut,
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.animateColorAsState
|
||||||
|
import androidx.compose.animation.core.Spring
|
||||||
|
import androidx.compose.animation.core.spring
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.statusBars
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ua.acclorite.book_story.ui.DefaultTransition
|
||||||
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun AnimatedTopAppBar(
|
||||||
|
containerColor: Color = MaterialTheme.colorScheme.surface,
|
||||||
|
scrolledContainerColor: Color? = MaterialTheme.elevation(),
|
||||||
|
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior?,
|
||||||
|
isTopBarScrolled: Boolean?,
|
||||||
|
|
||||||
|
content1Visibility: Boolean? = null,
|
||||||
|
content1NavigationIcon: @Composable () -> Unit,
|
||||||
|
content1Title: @Composable () -> Unit,
|
||||||
|
content1Actions: @Composable RowScope.() -> Unit,
|
||||||
|
|
||||||
|
content2Visibility: Boolean? = null,
|
||||||
|
content2NavigationIcon: @Composable () -> Unit = {},
|
||||||
|
content2Title: @Composable () -> Unit = {},
|
||||||
|
content2Actions: @Composable RowScope.() -> Unit = {},
|
||||||
|
|
||||||
|
content3Visibility: Boolean? = null,
|
||||||
|
content3NavigationIcon: @Composable () -> Unit = {},
|
||||||
|
content3Title: @Composable () -> Unit = {},
|
||||||
|
content3Actions: @Composable RowScope.() -> Unit = {}
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
if ((scrollBehavior != null || isTopBarScrolled != null) && scrolledContainerColor != null) {
|
||||||
|
|
||||||
|
val fraction by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
scrollBehavior?.state?.overlappedFraction ?: 0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isScrolled = if (scrollBehavior != null) {
|
||||||
|
fraction > 0.01f
|
||||||
|
} else isTopBarScrolled ?: false
|
||||||
|
|
||||||
|
val color = if (isScrolled) scrolledContainerColor else containerColor
|
||||||
|
val animatedColor by animateColorAsState(
|
||||||
|
targetValue = color,
|
||||||
|
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
|
||||||
|
label = "TopAppBar color animation"
|
||||||
|
)
|
||||||
|
|
||||||
|
val statusBarPadding = with(LocalDensity.current) {
|
||||||
|
WindowInsets.statusBars.getTop(LocalDensity.current).toDp()
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(64.dp + statusBarPadding)
|
||||||
|
.background(
|
||||||
|
animatedColor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTransition(visible = content1Visibility ?: true) {
|
||||||
|
TopAppBar(
|
||||||
|
navigationIcon = content1NavigationIcon,
|
||||||
|
title = content1Title,
|
||||||
|
actions = content1Actions,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
scrolledContainerColor = Color.Transparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content2Visibility != null) {
|
||||||
|
DefaultTransition(visible = content2Visibility) {
|
||||||
|
TopAppBar(
|
||||||
|
navigationIcon = content2NavigationIcon,
|
||||||
|
title = content2Title,
|
||||||
|
actions = content2Actions,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
scrolledContainerColor = Color.Transparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content3Visibility != null) {
|
||||||
|
DefaultTransition(visible = content3Visibility) {
|
||||||
|
TopAppBar(
|
||||||
|
navigationIcon = content3NavigationIcon,
|
||||||
|
title = content3Title,
|
||||||
|
actions = content3Actions,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
scrolledContainerColor = Color.Transparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.domain.model.NavigationBarItem
|
import ua.acclorite.book_story.domain.model.NavigationBarItem
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
import ua.acclorite.book_story.presentation.Navigator
|
||||||
import com.acclorite.books_history.presentation.Screen
|
import ua.acclorite.book_story.presentation.Screen
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom navigation bar, uses default [NavigationBar].
|
* Bottom navigation bar, uses default [NavigationBar].
|
||||||
|
|
@ -20,7 +23,15 @@ import com.acclorite.books_history.ui.elevation
|
||||||
fun BottomNavigationBar(
|
fun BottomNavigationBar(
|
||||||
navigator: Navigator
|
navigator: Navigator
|
||||||
) {
|
) {
|
||||||
val currentScreen by navigator.getCurrentScreen().collectAsState()
|
var currentScreen: Screen? by remember { mutableStateOf(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
navigator.getCurrentScreen().collect {
|
||||||
|
if (it == Screen.LIBRARY || it == Screen.HISTORY || it == Screen.BROWSE) {
|
||||||
|
currentScreen = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NavigationBar(
|
NavigationBar(
|
||||||
containerColor = MaterialTheme.elevation()
|
containerColor = MaterialTheme.elevation()
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
|
@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.domain.model.NavigationBarItem
|
import ua.acclorite.book_story.domain.model.NavigationBarItem
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom Navigation Bar Item, uses default [NavigationBarItem].
|
* Bottom Navigation Bar Item, uses default [NavigationBarItem].
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
|
|
@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CustomCheckbox(selected: Boolean) {
|
fun CustomCheckbox(selected: Boolean) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
|
@ -31,9 +31,9 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import androidx.compose.ui.window.DialogWindowProvider
|
import androidx.compose.ui.window.DialogWindowProvider
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.ui.ElevationDefaults
|
import ua.acclorite.book_story.ui.ElevationDefaults
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -100,6 +100,8 @@ fun CustomDialogWithContent(
|
||||||
else Alignment.Start
|
else Alignment.Start
|
||||||
)
|
)
|
||||||
.padding(horizontal = 24.dp),
|
.padding(horizontal = 24.dp),
|
||||||
|
textAlign = if (drawableIcon != null || imageVectorIcon != null) TextAlign.Center
|
||||||
|
else TextAlign.Start,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
|
@ -32,9 +32,9 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import androidx.compose.ui.window.DialogWindowProvider
|
import androidx.compose.ui.window.DialogWindowProvider
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.ui.ElevationDefaults
|
import ua.acclorite.book_story.ui.ElevationDefaults
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -101,6 +101,8 @@ fun CustomDialogWithLazyColumn(
|
||||||
else Alignment.Start
|
else Alignment.Start
|
||||||
)
|
)
|
||||||
.padding(horizontal = 24.dp),
|
.padding(horizontal = 24.dp),
|
||||||
|
textAlign = if (drawableIcon != null || imageVectorIcon != null) TextAlign.Center
|
||||||
|
else TextAlign.Start,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.DismissValue
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.SwipeToDismiss
|
||||||
|
import androidx.compose.material.rememberDismissState
|
||||||
|
import androidx.compose.material3.Snackbar
|
||||||
|
import androidx.compose.material3.SnackbarHost
|
||||||
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
@Composable
|
||||||
|
fun CustomSnackbar(snackbarState: SnackbarHostState) {
|
||||||
|
val dismissState = rememberDismissState { value ->
|
||||||
|
if (value != DismissValue.Default) {
|
||||||
|
snackbarState.currentSnackbarData?.dismiss()
|
||||||
|
true
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(dismissState.currentValue) {
|
||||||
|
if (dismissState.currentValue != DismissValue.Default) {
|
||||||
|
dismissState.reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SwipeToDismiss(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 4.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
state = dismissState,
|
||||||
|
background = {}
|
||||||
|
) {
|
||||||
|
SnackbarHost(
|
||||||
|
hostState = snackbarState,
|
||||||
|
snackbar = { data ->
|
||||||
|
Snackbar(
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
|
@ -20,9 +20,9 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
import ua.acclorite.book_story.presentation.Navigator
|
||||||
import com.acclorite.books_history.presentation.Screen
|
import ua.acclorite.book_story.presentation.Screen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MoreDropDown(navigator: Navigator) {
|
fun MoreDropDown(navigator: Navigator) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.components
|
package ua.acclorite.book_story.presentation.components
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.data
|
package ua.acclorite.book_story.presentation.data
|
||||||
|
|
||||||
fun String.removeTrailingZero(): String {
|
fun String.removeTrailingZero(): String {
|
||||||
if (!this.contains('.'))
|
if (!this.contains('.'))
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.data
|
package ua.acclorite.book_story.presentation.data
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.data
|
package ua.acclorite.book_story.presentation.data
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -6,15 +6,6 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.acclorite.books_history.domain.use_case.ChangeLanguage
|
|
||||||
import com.acclorite.books_history.domain.use_case.GetDatastore
|
|
||||||
import com.acclorite.books_history.domain.use_case.SetDatastore
|
|
||||||
import com.acclorite.books_history.ui.DarkTheme
|
|
||||||
import com.acclorite.books_history.ui.Theme
|
|
||||||
import com.acclorite.books_history.ui.toDarkTheme
|
|
||||||
import com.acclorite.books_history.ui.toTheme
|
|
||||||
import com.acclorite.books_history.util.Constants
|
|
||||||
import com.acclorite.books_history.util.DataStoreConstants
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -25,6 +16,15 @@ import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import ua.acclorite.book_story.domain.use_case.ChangeLanguage
|
||||||
|
import ua.acclorite.book_story.domain.use_case.GetDatastore
|
||||||
|
import ua.acclorite.book_story.domain.use_case.SetDatastore
|
||||||
|
import ua.acclorite.book_story.ui.DarkTheme
|
||||||
|
import ua.acclorite.book_story.ui.Theme
|
||||||
|
import ua.acclorite.book_story.ui.toDarkTheme
|
||||||
|
import ua.acclorite.book_story.ui.toTheme
|
||||||
|
import ua.acclorite.book_story.util.Constants
|
||||||
|
import ua.acclorite.book_story.util.DataStoreConstants
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info
|
package ua.acclorite.book_story.presentation.screens.book_info
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -33,7 +33,6 @@ import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -51,34 +50,39 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.acclorite.books_history.R
|
|
||||||
import com.acclorite.books_history.domain.model.Book
|
|
||||||
import com.acclorite.books_history.presentation.Argument
|
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
|
||||||
import com.acclorite.books_history.presentation.Screen
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoBackground
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoChangeCoverBottomSheet
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoDeleteDialog
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoDescriptionSection
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoDetailsBottomSheet
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoInfoSection
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoMoreDropDown
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoMoveDialog
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.components.BookInfoStatisticSection
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryEvent
|
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryViewModel
|
|
||||||
import com.acclorite.books_history.ui.DefaultTransition
|
|
||||||
import com.acclorite.books_history.ui.Transitions
|
|
||||||
import com.acclorite.books_history.ui.elevation
|
|
||||||
import com.acclorite.books_history.util.Constants
|
|
||||||
import dagger.hilt.android.lifecycle.withCreationCallback
|
import dagger.hilt.android.lifecycle.withCreationCallback
|
||||||
|
import ua.acclorite.book_story.R
|
||||||
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
import ua.acclorite.book_story.presentation.Argument
|
||||||
|
import ua.acclorite.book_story.presentation.Navigator
|
||||||
|
import ua.acclorite.book_story.presentation.Screen
|
||||||
|
import ua.acclorite.book_story.presentation.components.AnimatedTopAppBar
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoChangeCoverBottomSheet
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDeleteDialog
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDescriptionSection
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoDetailsBottomSheet
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoInfoSection
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoMoreDropDown
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoMoveDialog
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoStatisticSection
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
import ua.acclorite.book_story.ui.DefaultTransition
|
||||||
|
import ua.acclorite.book_story.ui.Transitions
|
||||||
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
import ua.acclorite.book_story.util.Constants
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoScreen(
|
fun BookInfoScreen(
|
||||||
libraryViewModel: LibraryViewModel = hiltViewModel(),
|
libraryViewModel: LibraryViewModel = hiltViewModel(),
|
||||||
|
browseViewModel: BrowseViewModel = hiltViewModel(),
|
||||||
|
historyViewModel: HistoryViewModel = hiltViewModel(),
|
||||||
navigator: Navigator
|
navigator: Navigator
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
@ -120,7 +124,11 @@ fun BookInfoScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.showChangeCoverBottomSheet) {
|
if (state.showChangeCoverBottomSheet) {
|
||||||
BookInfoChangeCoverBottomSheet(libraryViewModel = libraryViewModel, viewModel = viewModel)
|
BookInfoChangeCoverBottomSheet(
|
||||||
|
libraryViewModel = libraryViewModel,
|
||||||
|
historyViewModel = historyViewModel,
|
||||||
|
viewModel = viewModel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (state.showDetailsBottomSheet) {
|
if (state.showDetailsBottomSheet) {
|
||||||
BookInfoDetailsBottomSheet(viewModel = viewModel)
|
BookInfoDetailsBottomSheet(viewModel = viewModel)
|
||||||
|
|
@ -128,6 +136,8 @@ fun BookInfoScreen(
|
||||||
if (state.showDeleteDialog) {
|
if (state.showDeleteDialog) {
|
||||||
BookInfoDeleteDialog(
|
BookInfoDeleteDialog(
|
||||||
libraryViewModel = libraryViewModel,
|
libraryViewModel = libraryViewModel,
|
||||||
|
browseViewModel = browseViewModel,
|
||||||
|
historyViewModel = historyViewModel,
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
navigator = navigator
|
navigator = navigator
|
||||||
)
|
)
|
||||||
|
|
@ -147,9 +157,13 @@ fun BookInfoScreen(
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars),
|
.windowInsetsPadding(WindowInsets.navigationBars),
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
AnimatedTopAppBar(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
scrolledContainerColor = MaterialTheme.elevation(),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
isTopBarScrolled = null,
|
||||||
|
|
||||||
|
content1NavigationIcon = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
navigator.navigateBack()
|
navigator.navigateBack()
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -160,7 +174,7 @@ fun BookInfoScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
title = {
|
content1Title = {
|
||||||
DefaultTransition(visible = firstVisibleItemIndex > 0) {
|
DefaultTransition(visible = firstVisibleItemIndex > 0) {
|
||||||
Text(
|
Text(
|
||||||
state.book.title,
|
state.book.title,
|
||||||
|
|
@ -171,7 +185,7 @@ fun BookInfoScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
content1Actions = {
|
||||||
Box {
|
Box {
|
||||||
DefaultTransition(
|
DefaultTransition(
|
||||||
visible = !state.editTitle
|
visible = !state.editTitle
|
||||||
|
|
@ -214,11 +228,7 @@ fun BookInfoScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = Color.Transparent,
|
|
||||||
scrolledContainerColor = MaterialTheme.elevation()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
|
@ -22,18 +22,21 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryViewModel
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
|
||||||
import com.acclorite.books_history.ui.ElevationDefaults
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
import ua.acclorite.book_story.ui.ElevationDefaults
|
||||||
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoChangeCoverBottomSheet(
|
fun BookInfoChangeCoverBottomSheet(
|
||||||
libraryViewModel: LibraryViewModel,
|
libraryViewModel: LibraryViewModel,
|
||||||
|
historyViewModel: HistoryViewModel,
|
||||||
viewModel: BookInfoViewModel
|
viewModel: BookInfoViewModel
|
||||||
) {
|
) {
|
||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
|
|
@ -50,6 +53,7 @@ fun BookInfoChangeCoverBottomSheet(
|
||||||
context,
|
context,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
libraryViewModel.onEvent(LibraryEvent.OnLoadList)
|
libraryViewModel.onEvent(LibraryEvent.OnLoadList)
|
||||||
|
historyViewModel.onEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -91,6 +95,7 @@ fun BookInfoChangeCoverBottomSheet(
|
||||||
viewModel.onEvent(BookInfoEvent.OnDeleteCover(
|
viewModel.onEvent(BookInfoEvent.OnDeleteCover(
|
||||||
refreshList = {
|
refreshList = {
|
||||||
libraryViewModel.onEvent(LibraryEvent.OnLoadList)
|
libraryViewModel.onEvent(LibraryEvent.OnLoadList)
|
||||||
|
historyViewModel.onEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
|
@ -6,17 +6,23 @@ import androidx.compose.material.icons.outlined.DeleteOutline
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
import ua.acclorite.book_story.presentation.Navigator
|
||||||
import com.acclorite.books_history.presentation.components.CustomDialogWithContent
|
import ua.acclorite.book_story.presentation.components.CustomDialogWithContent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryViewModel
|
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewModel
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoDeleteDialog(
|
fun BookInfoDeleteDialog(
|
||||||
libraryViewModel: LibraryViewModel,
|
libraryViewModel: LibraryViewModel,
|
||||||
|
browseViewModel: BrowseViewModel,
|
||||||
|
historyViewModel: HistoryViewModel,
|
||||||
viewModel: BookInfoViewModel,
|
viewModel: BookInfoViewModel,
|
||||||
navigator: Navigator
|
navigator: Navigator
|
||||||
) {
|
) {
|
||||||
|
|
@ -37,9 +43,9 @@ fun BookInfoDeleteDialog(
|
||||||
BookInfoEvent.OnDeleteBook(
|
BookInfoEvent.OnDeleteBook(
|
||||||
navigator = navigator,
|
navigator = navigator,
|
||||||
refreshList = {
|
refreshList = {
|
||||||
libraryViewModel.onEvent(
|
libraryViewModel.onEvent(LibraryEvent.OnLoadList)
|
||||||
LibraryEvent.OnLoadList
|
browseViewModel.onEvent(BrowseEvent.OnLoadList)
|
||||||
)
|
historyViewModel.onEvent(HistoryEvent.OnLoadList)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
|
@ -11,8 +11,8 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoDescriptionSection(book: Book) {
|
fun BookInfoDescriptionSection(book: Book) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -16,11 +16,11 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
import com.acclorite.books_history.ui.ElevationDefaults
|
import ua.acclorite.book_story.ui.ElevationDefaults
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
|
@ -41,10 +41,10 @@ import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
import com.acclorite.books_history.ui.elevation
|
import ua.acclorite.book_story.ui.elevation
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -117,8 +117,8 @@ fun BookInfoInfoSection(viewModel: BookInfoViewModel, book: Book) {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
|
maxLines = 4,
|
||||||
value = state.titleValue,
|
value = state.titleValue,
|
||||||
singleLine = true,
|
|
||||||
textStyle = TextStyle(
|
textStyle = TextStyle(
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
fontSize = MaterialTheme.typography.headlineSmall.fontSize,
|
fontSize = MaterialTheme.typography.headlineSmall.fontSize,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
|
@ -18,10 +18,10 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.presentation.components.CustomDropDownMenuItem
|
import ua.acclorite.book_story.presentation.components.CustomDropDownMenuItem
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoMoreDropDown(viewModel: BookInfoViewModel) {
|
fun BookInfoMoreDropDown(viewModel: BookInfoViewModel) {
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
|
@ -11,15 +11,15 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.domain.model.Category
|
import ua.acclorite.book_story.domain.model.Category
|
||||||
import com.acclorite.books_history.presentation.Navigator
|
import ua.acclorite.book_story.presentation.Navigator
|
||||||
import com.acclorite.books_history.presentation.components.CustomDialogWithLazyColumn
|
import ua.acclorite.book_story.presentation.components.CustomDialogWithLazyColumn
|
||||||
import com.acclorite.books_history.presentation.components.SelectableDialogItem
|
import ua.acclorite.book_story.presentation.components.SelectableDialogItem
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoEvent
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
|
||||||
import com.acclorite.books_history.presentation.screens.book_info.data.BookInfoViewModel
|
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryEvent
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
|
||||||
import com.acclorite.books_history.presentation.screens.library.data.LibraryViewModel
|
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoMoveDialog(
|
fun BookInfoMoveDialog(
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.acclorite.books_history.presentation.screens.book_info.components
|
package ua.acclorite.book_story.presentation.screens.book_info.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -14,10 +14,10 @@ import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.acclorite.books_history.R
|
import ua.acclorite.book_story.R
|
||||||
import com.acclorite.books_history.domain.model.Book
|
import ua.acclorite.book_story.domain.model.Book
|
||||||
import com.acclorite.books_history.presentation.data.removeDigits
|
import ua.acclorite.book_story.presentation.data.removeDigits
|
||||||
import com.acclorite.books_history.presentation.data.removeTrailingZero
|
import ua.acclorite.book_story.presentation.data.removeTrailingZero
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookInfoStatisticSection(book: Book) {
|
fun BookInfoStatisticSection(book: Book) {
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue