1.0.0 - Minor bug fixes + Some performance improvements

This commit is contained in:
acclorite 2024-04-26 17:32:28 +03:00
parent 43da347ae0
commit 085cd81464
35 changed files with 193 additions and 71 deletions

View file

@ -16,7 +16,7 @@ android {
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionCode = 1 versionCode = 1
versionName = "0.9.9" versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {

View file

@ -47,6 +47,7 @@
<activity <activity
android:name=".Activity" android:name=".Activity"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize|locale|density"
android:exported="true" android:exported="true"
android:theme="@style/Theme.Start.Splash"> android:theme="@style/Theme.Start.Splash">
<intent-filter> <intent-filter>

View file

@ -30,6 +30,7 @@ import ua.acclorite.book_story.presentation.screens.about.nested.credits.Credits
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.LicenseInfoScreenRoot import ua.acclorite.book_story.presentation.screens.about.nested.license_info.LicenseInfoScreenRoot
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoViewModel
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.LicensesScreenRoot import ua.acclorite.book_story.presentation.screens.about.nested.licenses.LicensesScreenRoot
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.data.LicensesViewModel
import ua.acclorite.book_story.presentation.screens.book_info.BookInfoScreenRoot import ua.acclorite.book_story.presentation.screens.book_info.BookInfoScreenRoot
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewModel
import ua.acclorite.book_story.presentation.screens.browse.BrowseScreenRoot import ua.acclorite.book_story.presentation.screens.browse.BrowseScreenRoot
@ -70,6 +71,7 @@ class Activity : AppCompatActivity() {
private val helpViewModel: HelpViewModel by viewModels() private val helpViewModel: HelpViewModel by viewModels()
private val aboutViewModel: AboutViewModel by viewModels() private val aboutViewModel: AboutViewModel by viewModels()
private val licenseInfoViewModel: LicenseInfoViewModel by viewModels() private val licenseInfoViewModel: LicenseInfoViewModel by viewModels()
private val licensesViewModel: LicensesViewModel by viewModels()
private val settingsViewModel: SettingsViewModel by viewModels() private val settingsViewModel: SettingsViewModel by viewModels()
private val startViewModel: StartViewModel by viewModels() private val startViewModel: StartViewModel by viewModels()

View file

@ -0,0 +1,12 @@
package ua.acclorite.book_story.presentation.components
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.runtime.Composable
fun LazyGridScope.header(
content: @Composable LazyGridItemScope.() -> Unit
) {
item(span = { GridItemSpan(this.maxLineSpan) }, content = content)
}

View file

@ -0,0 +1,43 @@
package ua.acclorite.book_story.presentation.components
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.runtime.Composable
fun <T> LazyListScope.customItems(
items: List<T>,
key: (T) -> Any?,
content: @Composable LazyItemScope.(T) -> Unit
) {
items.forEach {
item(key = key(it)) {
content(it)
}
}
}
fun <T> LazyListScope.customItemsIndexed(
items: List<T>,
key: (T) -> Any?,
content: @Composable LazyItemScope.(Int, T) -> Unit
) {
items.forEachIndexed { index, item ->
item(key = key(item)) {
content(index, item)
}
}
}
fun <T> LazyGridScope.customItems(
items: List<T>,
key: (T) -> Any?,
content: @Composable LazyGridItemScope.(T) -> Unit
) {
items.forEach {
item(key = key(it)) {
content(it)
}
}
}

View file

@ -16,7 +16,6 @@ import ua.acclorite.book_story.presentation.data.Screen
/** /**
* Bottom navigation bar, uses default [NavigationBar]. * Bottom navigation bar, uses default [NavigationBar].
*
*/ */
@Composable @Composable
fun BottomNavigationBar() { fun BottomNavigationBar() {

View file

@ -21,6 +21,9 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.model.Credit import ua.acclorite.book_story.domain.model.Credit
/**
* Credit Item.
*/
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun CreditItem( fun CreditItem(

View file

@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Language import androidx.compose.material.icons.outlined.Language
@ -52,6 +51,7 @@ import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomIconButton
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoEvent import ua.acclorite.book_story.presentation.screens.about.nested.license_info.data.LicenseInfoEvent
@ -154,10 +154,14 @@ private fun LicenseInfoScreen(
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second, state = scrollState.second,
contentPadding = PaddingValues(vertical = 12.dp, horizontal = 16.dp), contentPadding = PaddingValues(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp) verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
items(licenses, key = { it.name }) { license -> item {
Spacer(modifier = Modifier.height(12.dp))
}
customItems(licenses, key = { it.name }) { license ->
val showed = remember { val showed = remember {
mutableStateOf(licenses.size == 1) mutableStateOf(licenses.size == 1)
} }
@ -206,6 +210,10 @@ private fun LicenseInfoScreen(
} }
} }
} }
item {
Spacer(modifier = Modifier.height(12.dp))
}
} }
} }
} else { } else {

View file

@ -3,14 +3,14 @@ package ua.acclorite.book_story.presentation.screens.about.nested.licenses
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -31,6 +31,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.GoBackButton import ua.acclorite.book_story.presentation.components.GoBackButton
import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.components.collapsibleUntilExitScrollBehaviorWithLazyListState
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Argument
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Navigator
@ -96,10 +97,13 @@ private fun LicensesScreen(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second, state = scrollState.second
contentPadding = PaddingValues(vertical = 12.dp)
) { ) {
items(state.value.licenses, key = { it.uniqueId }) { item {
Spacer(modifier = Modifier.height(12.dp))
}
customItems(state.value.licenses, key = { it.uniqueId }) {
LicenseItem(library = it) { LicenseItem(library = it) {
navigator.navigate( navigator.navigate(
Screen.LICENSES_INFO, Screen.LICENSES_INFO,
@ -108,6 +112,10 @@ private fun LicensesScreen(
) )
} }
} }
item {
Spacer(modifier = Modifier.height(12.dp))
}
} }
} }
} }

View file

@ -25,6 +25,9 @@ import androidx.compose.ui.unit.dp
import com.mikepenz.aboutlibraries.entity.Library import com.mikepenz.aboutlibraries.entity.Library
import com.mikepenz.aboutlibraries.ui.compose.m3.util.author import com.mikepenz.aboutlibraries.ui.compose.m3.util.author
/**
* License Item.
*/
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun LicenseItem( fun LicenseItem(

View file

@ -1,7 +1,6 @@
package ua.acclorite.book_story.presentation.screens.book_info.components.dialog package ua.acclorite.book_story.presentation.screens.book_info.components.dialog
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -12,6 +11,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
@ -71,7 +71,7 @@ fun BookInfoMoveDialog(
}, },
withDivider = false, withDivider = false,
items = { items = {
items(categories) { customItems(categories, key = { it.name }) {
val category = when (it) { val category = when (it) {
Category.READING -> stringResource(id = R.string.reading_tab) Category.READING -> stringResource(id = R.string.reading_tab)
Category.ALREADY_READ -> stringResource(id = R.string.already_read_tab) Category.ALREADY_READ -> stringResource(id = R.string.already_read_tab)

View file

@ -6,11 +6,11 @@ import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
@ -51,6 +51,7 @@ import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomIconButton
import ua.acclorite.book_story.presentation.components.CustomSearchTextField import ua.acclorite.book_story.presentation.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.MoreDropDown
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.components.is_messages.IsError import ua.acclorite.book_story.presentation.components.is_messages.IsError
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
@ -233,10 +234,13 @@ private fun BrowseScreen(
LazyColumn( LazyColumn(
state = state.value.listState, state = state.value.listState,
modifier = Modifier modifier = Modifier
.fillMaxSize(), .fillMaxSize()
contentPadding = PaddingValues(vertical = 8.dp)
) { ) {
items( item {
Spacer(modifier = Modifier.height(8.dp))
}
customItems(
state.value.selectableFiles, state.value.selectableFiles,
key = { it.first.path } key = { it.first.path }
) { selectableFile -> ) { selectableFile ->
@ -259,6 +263,10 @@ private fun BrowseScreen(
} }
) )
} }
item {
Spacer(modifier = Modifier.height(8.dp))
}
} }
} }

View file

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddChart import androidx.compose.material.icons.filled.AddChart
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
@ -20,6 +19,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.NullableBook import ua.acclorite.book_story.domain.model.NullableBook
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
@ -90,7 +90,7 @@ fun BrowseAddingDialog(
} }
} }
} else { } else {
items(state.value.selectedBooks) { book -> customItems(state.value.selectedBooks, key = { it.first.fileName }) { book ->
BrowseAddingDialogItem( BrowseAddingDialogItem(
result = book result = book
) { ) {

View file

@ -78,7 +78,7 @@ class BrowseViewModel @Inject constructor(
} }
if (legacyStoragePermission) { if (legacyStoragePermission) {
if (event.storagePermissionState.status.shouldShowRationale) { if (!event.storagePermissionState.status.shouldShowRationale) {
event.storagePermissionState.launchPermissionRequest() event.storagePermissionState.launchPermissionRequest()
} else { } else {
val uri = Uri.parse("package:${event.activity.packageName}") val uri = Uri.parse("package:${event.activity.packageName}")

View file

@ -41,6 +41,8 @@ import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.data.Navigator import ua.acclorite.book_story.presentation.data.Navigator
import ua.acclorite.book_story.presentation.data.Screen import ua.acclorite.book_story.presentation.data.Screen
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
import ua.acclorite.book_story.presentation.screens.help.components.items.HelpAddBooksItem import ua.acclorite.book_story.presentation.screens.help.components.items.HelpAddBooksItem
import ua.acclorite.book_story.presentation.screens.help.components.items.HelpClickMeNoteItem import ua.acclorite.book_story.presentation.screens.help.components.items.HelpClickMeNoteItem
import ua.acclorite.book_story.presentation.screens.help.components.items.HelpCustomizeApp import ua.acclorite.book_story.presentation.screens.help.components.items.HelpCustomizeApp
@ -61,6 +63,7 @@ import ua.acclorite.book_story.presentation.screens.start.data.StartViewModel
fun HelpScreenRoot() { fun HelpScreenRoot() {
val navigator = LocalNavigator.current val navigator = LocalNavigator.current
val helpViewModel: HelpViewModel = hiltViewModel() val helpViewModel: HelpViewModel = hiltViewModel()
val browseViewModel: BrowseViewModel = hiltViewModel()
val mainViewModel: MainViewModel = hiltViewModel() val mainViewModel: MainViewModel = hiltViewModel()
val startViewModel: StartViewModel = hiltViewModel() val startViewModel: StartViewModel = hiltViewModel()
@ -75,6 +78,7 @@ fun HelpScreenRoot() {
navigator = navigator, navigator = navigator,
onEvent = helpViewModel::onEvent, onEvent = helpViewModel::onEvent,
onMainEvent = mainViewModel::onEvent, onMainEvent = mainViewModel::onEvent,
onBrowseEvent = browseViewModel::onEvent,
onStartEvent = startViewModel::onEvent onStartEvent = startViewModel::onEvent
) )
} }
@ -88,6 +92,7 @@ private fun HelpScreen(
navigator: Navigator, navigator: Navigator,
onEvent: (HelpEvent) -> Unit, onEvent: (HelpEvent) -> Unit,
onMainEvent: (MainEvent) -> Unit, onMainEvent: (MainEvent) -> Unit,
onBrowseEvent: (BrowseEvent) -> Unit,
onStartEvent: (StartEvent) -> Unit onStartEvent: (StartEvent) -> Unit
) { ) {
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState()
@ -117,6 +122,7 @@ private fun HelpScreen(
) { ) {
onStartEvent(StartEvent.OnResetStartScreen) onStartEvent(StartEvent.OnResetStartScreen)
onMainEvent(MainEvent.OnChangeShowStartScreen(true)) onMainEvent(MainEvent.OnChangeShowStartScreen(true))
onBrowseEvent(BrowseEvent.OnLoadList)
navigator.navigateWithoutBackStack(Screen.START, false) navigator.navigateWithoutBackStack(Screen.START, false)
navigator.clearBackStack() navigator.clearBackStack()
} }
@ -142,6 +148,7 @@ private fun HelpScreen(
shape = RoundedCornerShape(100), shape = RoundedCornerShape(100),
onClick = { onClick = {
navigator.clearArgument("from_start") navigator.clearArgument("from_start")
onMainEvent(MainEvent.OnChangeShowStartScreen(false)) onMainEvent(MainEvent.OnChangeShowStartScreen(false))
navigator.navigateWithoutBackStack(Screen.BROWSE, false) navigator.navigateWithoutBackStack(Screen.BROWSE, false)
} }

View file

@ -51,11 +51,15 @@ fun LazyItemScope.HelpAddBooksItem(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"browse" -> { "browse" -> {
navigator.navigate(Screen.BROWSE, true) if (!state.value.fromStart) {
navigator.navigate(Screen.BROWSE, true)
}
} }
"library" -> { "library" -> {
navigator.navigate(Screen.LIBRARY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpCustomizeApp(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"settings" -> { "settings" -> {
navigator.navigate(Screen.SETTINGS, true) if (!state.value.fromStart) {
navigator.navigate(Screen.SETTINGS, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpCustomizeReader(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"settings" -> { "settings" -> {
navigator.navigate(Screen.SETTINGS, true) if (!state.value.fromStart) {
navigator.navigate(Screen.SETTINGS, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpEditBook(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"library" -> { "library" -> {
navigator.navigate(Screen.LIBRARY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpManageHistory(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"history" -> { "history" -> {
navigator.navigate(Screen.HISTORY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.HISTORY, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpMoveOrDeleteBooks(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"library" -> { "library" -> {
navigator.navigate(Screen.LIBRARY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpReadBook(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"library" -> { "library" -> {
navigator.navigate(Screen.LIBRARY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true)
}
} }
} }
} }

View file

@ -46,7 +46,9 @@ fun LazyItemScope.HelpUpdateBook(
onTagClick = { tag -> onTagClick = { tag ->
when (tag) { when (tag) {
"library" -> { "library" -> {
navigator.navigate(Screen.LIBRARY, true) if (!state.value.fromStart) {
navigator.navigate(Screen.LIBRARY, true)
}
} }
} }
} }

View file

@ -4,13 +4,11 @@ import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
@ -47,6 +45,7 @@ import ua.acclorite.book_story.presentation.components.CustomIconButton
import ua.acclorite.book_story.presentation.components.CustomSearchTextField import ua.acclorite.book_story.presentation.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.components.CustomSnackbar import ua.acclorite.book_story.presentation.components.CustomSnackbar
import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.MoreDropDown
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Argument
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
@ -199,8 +198,11 @@ private fun HistoryScreen(
Modifier Modifier
.fillMaxSize(), .fillMaxSize(),
state = state.value.listState, state = state.value.listState,
contentPadding = PaddingValues(vertical = 12.dp)
) { ) {
item {
Spacer(modifier = Modifier.height(12.dp))
}
state.value.history.forEachIndexed { index, groupedHistory -> state.value.history.forEachIndexed { index, groupedHistory ->
item(key = groupedHistory.title) { item(key = groupedHistory.title) {
if (index > 0) { if (index > 0) {
@ -220,7 +222,7 @@ private fun HistoryScreen(
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
} }
items( customItems(
groupedHistory.history, key = { it.id } groupedHistory.history, key = { it.id }
) { ) {
HistoryItem( HistoryItem(
@ -260,6 +262,10 @@ private fun HistoryScreen(
) )
} }
} }
item {
Spacer(modifier = Modifier.height(12.dp))
}
} }
} }

View file

@ -13,11 +13,11 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
@ -69,6 +69,8 @@ import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomIconButton import ua.acclorite.book_story.presentation.components.CustomIconButton
import ua.acclorite.book_story.presentation.components.CustomSearchTextField import ua.acclorite.book_story.presentation.components.CustomSearchTextField
import ua.acclorite.book_story.presentation.components.MoreDropDown import ua.acclorite.book_story.presentation.components.MoreDropDown
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.header
import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.data.Argument import ua.acclorite.book_story.presentation.data.Argument
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
@ -318,12 +320,13 @@ private fun LibraryScreen(
columns = GridCells.Adaptive(120.dp), columns = GridCells.Adaptive(120.dp),
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
state = listState, state = listState,
contentPadding = PaddingValues(8.dp) contentPadding = PaddingValues(horizontal = 8.dp)
) { ) {
items( header {
books, Spacer(modifier = Modifier.height(8.dp))
key = { it.first.id } }
) {
customItems(books, key = { it.first.id }) {
LibraryBookItem( LibraryBookItem(
book = it, book = it,
modifier = Modifier.animateItem( modifier = Modifier.animateItem(
@ -356,6 +359,10 @@ private fun LibraryScreen(
} }
) )
} }
header {
Spacer(modifier = Modifier.height(8.dp))
}
} }
} }

View file

@ -1,7 +1,6 @@
package ua.acclorite.book_story.presentation.screens.library.components.dialog package ua.acclorite.book_story.presentation.screens.library.components.dialog
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.PagerState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.DriveFileMove import androidx.compose.material.icons.automirrored.outlined.DriveFileMove
@ -11,6 +10,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.components.custom_dialog.CustomDialogWithLazyColumn
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
@ -56,7 +56,7 @@ fun LibraryMoveDialog(
}, },
withDivider = false, withDivider = false,
items = { items = {
items(state.value.categories) { customItems(state.value.categories, key = { it.name }) {
val category = when (it) { val category = when (it) {
Category.READING -> stringResource(id = R.string.reading_tab) Category.READING -> stringResource(id = R.string.reading_tab)
Category.ALREADY_READ -> stringResource(id = R.string.already_read_tab) Category.ALREADY_READ -> stringResource(id = R.string.already_read_tab)

View file

@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
@ -59,6 +58,7 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.Constants
import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.components.CustomAnimatedVisibility
import ua.acclorite.book_story.presentation.components.CustomSelectionContainer import ua.acclorite.book_story.presentation.components.CustomSelectionContainer
import ua.acclorite.book_story.presentation.components.customItemsIndexed
import ua.acclorite.book_story.presentation.components.is_messages.IsError import ua.acclorite.book_story.presentation.components.is_messages.IsError
import ua.acclorite.book_story.presentation.data.LocalNavigator import ua.acclorite.book_story.presentation.data.LocalNavigator
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
@ -346,8 +346,8 @@ private fun ReaderScreen(
} }
} }
itemsIndexed( customItemsIndexed(
state.value.book.text, key = { _, key -> key.id } state.value.book.text, key = { key -> key.id }
) { index, line -> ) { index, line ->
val text = remember(mainState.value.paragraphIndentation) { val text = remember(mainState.value.paragraphIndentation) {
"${if (mainState.value.paragraphIndentation!!) " " else ""}${line.line}" "${if (mainState.value.paragraphIndentation!!) " " else ""}${line.line}"

View file

@ -420,21 +420,15 @@ class ReaderViewModel @Inject constructor(
return@launch return@launch
} }
if (_state.value.book.id != bookId) { val book = getBooksById.execute(listOf(bookId))
val book = getBooksById.execute(listOf(bookId))
if (book.isEmpty()) { if (book.isEmpty()) {
navigator.navigateBack() navigator.navigateBack()
return@launch return@launch
} }
_state.update { _state.update {
ReaderState(book = book.first()) ReaderState(book = book.first())
}
} else {
_state.update {
ReaderState(book = it.book)
}
} }
viewModelScope.launch { viewModelScope.launch {

View file

@ -18,6 +18,9 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CategoryTitle
/**
* Segmented Button with Title. Contains [buttons].
*/
@Composable @Composable
fun SegmentedButtonWithTitle( fun SegmentedButtonWithTitle(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,

View file

@ -42,7 +42,7 @@ class SettingsViewModel @Inject constructor(
return return
} }
if (event.notificationsPermissionState.status.shouldShowRationale) { if (!event.notificationsPermissionState.status.shouldShowRationale) {
event.notificationsPermissionState.launchPermissionRequest() event.notificationsPermissionState.launchPermissionRequest()
} else { } else {
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)

View file

@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -20,6 +19,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.util.Constants import ua.acclorite.book_story.domain.util.Constants
import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CategoryTitle
import ua.acclorite.book_story.presentation.components.customItemsIndexed
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.ui.Theme import ua.acclorite.book_story.presentation.ui.Theme
@ -54,7 +54,7 @@ fun AppearanceSettingsThemeSwitcher(
Modifier Modifier
.fillMaxWidth(), .fillMaxWidth(),
) { ) {
itemsIndexed(themes) { index, themeEntry -> customItemsIndexed(themes, key = { it.first.name }) { index, themeEntry ->
if (index == 0) { if (index == 0) {
Spacer(modifier = Modifier.width(18.dp)) Spacer(modifier = Modifier.width(18.dp))
} else { } else {

View file

@ -3,7 +3,6 @@ package ua.acclorite.book_story.presentation.screens.start.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
import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -11,6 +10,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.components.CategoryTitle import ua.acclorite.book_story.presentation.components.CategoryTitle
import ua.acclorite.book_story.presentation.components.customItems
import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.components.custom_dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
@ -30,7 +30,7 @@ fun LazyListScope.startLanguageScreen(
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
} }
items(languages) { customItems(languages, key = { it.id }) {
SelectableDialogItem( SelectableDialogItem(
selected = it.selected, selected = it.selected,
title = it.title, title = it.title,

View file

@ -132,7 +132,7 @@ class StartViewModel @Inject constructor(
} }
if (legacyStoragePermission) { if (legacyStoragePermission) {
if (event.legacyStoragePermissionState.status.shouldShowRationale) { if (!event.legacyStoragePermissionState.status.shouldShowRationale) {
event.legacyStoragePermissionState.launchPermissionRequest() event.legacyStoragePermissionState.launchPermissionRequest()
} else { } else {
val uri = Uri.parse("package:${event.activity.packageName}") val uri = Uri.parse("package:${event.activity.packageName}")
@ -198,7 +198,7 @@ class StartViewModel @Inject constructor(
return return
} }
if (event.notificationsPermissionState.status.shouldShowRationale) { if (!event.notificationsPermissionState.status.shouldShowRationale) {
event.notificationsPermissionState.launchPermissionRequest() event.notificationsPermissionState.launchPermissionRequest()
} else { } else {
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)

View file

@ -101,7 +101,7 @@
</string> </string>
<string name="error_check_internet"> <string name="error_check_internet">
Щось пішло не так. Щось пішло не так.
Будь ласка, перевірте ваше підключення до інтернету та спробуйте ще раз. Спробуйте пізніше.
</string> </string>
<!-- Is Empty messages --> <!-- Is Empty messages -->
@ -292,8 +292,8 @@
<string name="support_option">Підтримати мою роботу</string> <string name="support_option">Підтримати мою роботу</string>
<string name="licenses_option">Ліцензії з відкритим кодом</string> <string name="licenses_option">Ліцензії з відкритим кодом</string>
<string name="credits_option">Заслуги</string> <string name="credits_option">Заслуги</string>
<string name="slava_ukraini_option">Слава Україні! 🇺🇦</string> <string name="slava_ukraini_option">Слава Україні!</string>
<string name="slava_ukraini_option_desc">Героям Слава! 🐉</string> <string name="slava_ukraini_option_desc">Героям Слава! 🇺🇦🐉</string>
<!-- Credits --> <!-- Credits -->
<string name="credits_design">Дизайн</string> <string name="credits_design">Дизайн</string>

View file

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="InconsistentArrays"> <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="InconsistentArrays">
<!-- Basic Strings --> <!-- Basic Strings -->
<string name="app_version" translatable="false">0.9.9</string> <string name="app_version" translatable="false">1.0.0</string>
<string name="app_name">Book\'s Story</string> <string name="app_name">Book\'s Story</string>
<!-- Notifications --> <!-- Notifications -->
@ -121,7 +121,7 @@
</string> </string>
<string name="error_check_internet"> <string name="error_check_internet">
Something went wrong. Something went wrong.
Please check your internet connection and try again. Try again later.
</string> </string>
<!-- Is Empty messages --> <!-- Is Empty messages -->
@ -311,8 +311,8 @@
<string name="support_option">Support my work</string> <string name="support_option">Support my work</string>
<string name="licenses_option">Open source licenses</string> <string name="licenses_option">Open source licenses</string>
<string name="credits_option">Credits</string> <string name="credits_option">Credits</string>
<string name="slava_ukraini_option">Slava Ukraini! 🇺🇦</string> <string name="slava_ukraini_option">Slava Ukraini!</string>
<string name="slava_ukraini_option_desc">Heroyam Slava! 🐉</string> <string name="slava_ukraini_option_desc">Heroyam Slava! 🇺🇦🐉</string>
<!-- Credits --> <!-- Credits -->
<string name="credits_design">Design</string> <string name="credits_design">Design</string>