🚀 Small UI changes & Code reformat

* Reformatted code (naming, packages)
* Small UI changes
This commit is contained in:
Acclorite 2024-10-19 21:41:39 +03:00
parent 2875baf5ce
commit aa68ba3ae8
156 changed files with 611 additions and 672 deletions

View file

@ -19,8 +19,8 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import ua.acclorite.book_story.presentation.core.components.bottom_navigation_bar.BottomNavigationBar import ua.acclorite.book_story.presentation.core.components.navigation_bar.NavigationBar
import ua.acclorite.book_story.presentation.core.components.custom_navigation_rail.CustomNavigationRail import ua.acclorite.book_story.presentation.core.components.navigation_rail.NavigationRail
import ua.acclorite.book_story.presentation.core.navigation.NavigationHost import ua.acclorite.book_story.presentation.core.navigation.NavigationHost
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.data.MainEvent import ua.acclorite.book_story.presentation.data.MainEvent
@ -131,10 +131,10 @@ class Activity : AppCompatActivity() {
Screen.Browse.getRoute() Screen.Browse.getRoute()
), ),
bottomBar = { bottomBar = {
BottomNavigationBar() NavigationBar()
}, },
navigationRail = { navigationRail = {
CustomNavigationRail() NavigationRail()
} }
) { ) {
// Library // Library

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.util package ua.acclorite.book_story.domain.util
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
@ -8,18 +8,18 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
abstract class UiViewModel<S, E> : ViewModel() { abstract class UIViewModel<S, E> : ViewModel() {
abstract val state: StateFlow<S> abstract val state: StateFlow<S>
abstract fun onEvent(event: E) abstract fun onEvent(event: E)
companion object { companion object {
@Composable @Composable
inline fun <reified V : UiViewModel<S, E>, S, E> getState(): State<S> { inline fun <reified V : UIViewModel<S, E>, S, E> getState(): State<S> {
return hiltViewModel<V>().state.collectAsStateWithLifecycle() return hiltViewModel<V>().state.collectAsStateWithLifecycle()
} }
@Composable @Composable
inline fun <reified V : UiViewModel<S, E>, S, E> getEvent(): (E) -> Unit { inline fun <reified V : UIViewModel<S, E>, S, E> getEvent(): (E) -> Unit {
return hiltViewModel<V>()::onEvent return hiltViewModel<V>()::onEvent
} }
} }

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition import androidx.compose.animation.EnterTransition
@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier
* FIXED: This bug was fixed. I preserved initial code, if the bug happens again. * FIXED: This bug was fixed. I preserved initial code, if the bug happens again.
*/ */
@Composable @Composable
fun CustomAnimatedVisibility( fun AnimatedVisibility(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
visible: Boolean, visible: Boolean,
enter: EnterTransition, enter: EnterTransition,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -14,7 +14,7 @@ import ua.acclorite.book_story.R
* Custom Cover Image. Has smooth appearing. * Custom Cover Image. Has smooth appearing.
*/ */
@Composable @Composable
fun CustomCoverImage( fun AsyncImage(
uri: Uri, uri: Uri,
animationDurationMillis: Int = 100, animationDurationMillis: Int = 100,
contentDescription: String? = stringResource(id = R.string.cover_image_content_desc), contentDescription: String? = stringResource(id = R.string.cover_image_content_desc),

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@ -18,7 +18,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
/** /**
* Custom Checkbox. Has a Circle shape. * Checkbox. Has a Circle shape.
* *
* @param modifier Modifier. * @param modifier Modifier.
* @param selected Whether checked or not. * @param selected Whether checked or not.
@ -26,7 +26,7 @@ import ua.acclorite.book_story.R
* @param size Size of the checkbox icon(not the whole checkbox). * @param size Size of the checkbox icon(not the whole checkbox).
*/ */
@Composable @Composable
fun CustomCheckbox( fun CircularCheckbox(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
selected: Boolean, selected: Boolean,
containerColor: Color, containerColor: Color,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material.icons.automirrored.outlined.ArrowBack
@ -8,15 +8,19 @@ import ua.acclorite.book_story.domain.util.OnNavigate
/** /**
* Go back arrow button. * Go back arrow button.
* Prevents double or triple clicking on it while going back action is performed. * Prevents double or triple clicking while going back action is performed.
* *
* @param onNavigate [OnNavigate]. * @param onNavigate [OnNavigate].
* @param enabled Whether this button is enabled. * @param enabled Whether this button is enabled.
* @param customOnClick Call before going back. * @param customOnClick Call before going back.
*/ */
@Composable @Composable
fun GoBackButton(onNavigate: OnNavigate, enabled: Boolean = true, customOnClick: () -> Unit = {}) { fun GoBackButton(
CustomIconButton( onNavigate: OnNavigate,
enabled: Boolean = true,
customOnClick: () -> Unit = {}
) {
IconButton(
icon = Icons.AutoMirrored.Outlined.ArrowBack, icon = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = R.string.go_back_content_desc, contentDescription = R.string.go_back_content_desc,
disableOnClick = true, disableOnClick = true,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
@ -18,7 +18,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
/** /**
* Custom Icon Button. * Icon Button.
* Can be disabled after click, so user can't press button fast 2 or 3 times. * Can be disabled after click, so user can't press button fast 2 or 3 times.
* *
* @param modifier [Modifier]. * @param modifier [Modifier].
@ -30,7 +30,7 @@ import androidx.compose.ui.res.stringResource
* @param onClick OnClick callback. * @param onClick OnClick callback.
*/ */
@Composable @Composable
fun CustomIconButton( fun IconButton(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
icon: ImageVector, icon: ImageVector,
@StringRes contentDescription: Int, @StringRes contentDescription: Int,
@ -40,7 +40,7 @@ fun CustomIconButton(
onClick: () -> Unit onClick: () -> Unit
) { ) {
var isClicked by remember { mutableStateOf(false) } var isClicked by remember { mutableStateOf(false) }
CustomTooltip(text = stringResource(id = contentDescription), enabled = enabled) { Tooltip(text = stringResource(id = contentDescription), enabled = enabled) {
IconButton( IconButton(
enabled = enabled && !isClicked, enabled = enabled && !isClicked,
modifier = Modifier.focusProperties { modifier = Modifier.focusProperties {
@ -64,7 +64,7 @@ fun CustomIconButton(
} }
/** /**
* Custom Icon Button. * Icon Button.
* Can be disabled after click, so user can't press button fast 2 or 3 times. * Can be disabled after click, so user can't press button fast 2 or 3 times.
* *
* @param modifier [Modifier]. * @param modifier [Modifier].
@ -76,7 +76,7 @@ fun CustomIconButton(
* @param onClick OnClick callback. * @param onClick OnClick callback.
*/ */
@Composable @Composable
fun CustomIconButton( fun IconButton(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@DrawableRes icon: Int, @DrawableRes icon: Int,
@StringRes contentDescription: Int, @StringRes contentDescription: Int,
@ -86,7 +86,7 @@ fun CustomIconButton(
onClick: () -> Unit onClick: () -> Unit
) { ) {
var isClicked by remember { mutableStateOf(false) } var isClicked by remember { mutableStateOf(false) }
CustomTooltip(text = stringResource(id = contentDescription)) { Tooltip(text = stringResource(id = contentDescription)) {
IconButton( IconButton(
enabled = enabled && !isClicked, enabled = enabled && !isClicked,
modifier = Modifier.focusProperties { modifier = Modifier.focusProperties {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -18,8 +18,8 @@ import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideSecondaryScrollbar import ua.acclorite.book_story.presentation.core.constants.provideSecondaryScrollbar
/** /**
* Custom Lazy Column. * Lazy Column.
* Has scrollbar. * Has a scrollbar.
* *
* @param modifier Modifier. * @param modifier Modifier.
* @param state [LazyListState]. * @param state [LazyListState].
@ -30,7 +30,7 @@ import ua.acclorite.book_story.presentation.core.constants.provideSecondaryScrol
* @param content Content of the column. * @param content Content of the column.
*/ */
@Composable @Composable
fun CustomLazyColumn( fun LazyColumnWithScrollbar(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(), state: LazyListState = rememberLazyListState(),
scrollbarSettings: ScrollbarSettings = Constants.provideSecondaryScrollbar(), scrollbarSettings: ScrollbarSettings = Constants.provideSecondaryScrollbar(),

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyGridItemScope import androidx.compose.foundation.lazy.grid.LazyGridItemScope

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@ -12,21 +12,28 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
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 ua.acclorite.book_story.R
/** /**
* Custom Search Text Field. Used in main screens for searching. * Search Text Field.
* Used in main screens for searching.
*
* @param modifier Modifier to apply.
* @param query Search query.
* @param onQueryChange Callback to change [query].
* @param onSearch Search action (refresh list, fetch filtered books etc..).
*/ */
@Composable @Composable
fun CustomSearchTextField( fun SearchTextField(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
query: String, query: String,
onQueryChange: (String) -> Unit, onQueryChange: (String) -> Unit,
onSearch: () -> Unit, onSearch: () -> Unit
placeholder: String
) { ) {
val keyboardManager = LocalSoftwareKeyboardController.current val keyboardManager = LocalSoftwareKeyboardController.current
@ -59,7 +66,7 @@ fun CustomSearchTextField(
) { ) {
if (query.isEmpty()) { if (query.isEmpty()) {
Text( Text(
placeholder, text = stringResource(id = R.string.search_field_empty),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
maxLines = 1, maxLines = 1,

View file

@ -1,6 +1,6 @@
@file:Suppress("DEPRECATION") @file:Suppress("DEPRECATION")
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
@ -35,9 +35,10 @@ private const val MENU_ITEM_TRANSLATE = 3
private const val MENU_ITEM_DICTIONARY = 4 private const val MENU_ITEM_DICTIONARY = 4
/** /**
* Custom Text ActionMode callback. Used in pair with [CustomSelectionToolbar]. Follow [TextToolbar] for more info. * Text ActionMode callback.
* Used in pair with [SelectionToolbar]. Follow [TextToolbar] for more info.
*/ */
private class CustomTextActionModeCallback( private class TextActionModeCallback(
private val context: Context, private val context: Context,
var rect: Rect = Rect.Zero, var rect: Rect = Rect.Zero,
var onCopyRequested: (() -> Unit)? = null, var onCopyRequested: (() -> Unit)? = null,
@ -99,10 +100,10 @@ private class CustomTextActionModeCallback(
} }
/** /**
* Floating [CustomTextActionModeCallback]. * Floating [TextActionModeCallback].
*/ */
private class FloatingTextActionModeCallback( private class FloatingTextActionModeCallback(
val callback: CustomTextActionModeCallback val callback: TextActionModeCallback
) : ActionMode.Callback2() { ) : ActionMode.Callback2() {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return callback.onActionItemClicked(mode, item) return callback.onActionItemClicked(mode, item)
@ -132,10 +133,10 @@ private class FloatingTextActionModeCallback(
} }
/** /**
* Custom Selection Toolbar. * Selection Toolbar.
* Used in pair with [CustomSelectionContainer] to display custom toolbar. * Used in pair with [SelectionContainer] to display custom toolbar.
*/ */
private class CustomSelectionToolbar( private class SelectionToolbar(
private val view: View, private val view: View,
context: Context, context: Context,
private val onCopyRequest: (() -> Unit)?, private val onCopyRequest: (() -> Unit)?,
@ -145,7 +146,7 @@ private class CustomSelectionToolbar(
private val onDictionaryRequest: ((String) -> Unit)? private val onDictionaryRequest: ((String) -> Unit)?
) : TextToolbar { ) : TextToolbar {
private var actionMode: ActionMode? = null private var actionMode: ActionMode? = null
private val callback = CustomTextActionModeCallback(context = context) private val callback = TextActionModeCallback(context = context)
val clipboardManager = val clipboardManager =
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
@ -244,7 +245,7 @@ private class CustomSelectionToolbar(
} }
/** /**
* Custom selection container. * Selection container.
* *
* @param onCopyRequested Callback for when the copy option is clicked. * @param onCopyRequested Callback for when the copy option is clicked.
* @param onTranslateRequested Callback for when the translate option is clicked. * @param onTranslateRequested Callback for when the translate option is clicked.
@ -252,7 +253,7 @@ private class CustomSelectionToolbar(
* @param content Selection container content. * @param content Selection container content.
*/ */
@Composable @Composable
fun CustomSelectionContainer( fun SelectionContainer(
onCopyRequested: (() -> Unit), onCopyRequested: (() -> Unit),
onShareRequested: ((String) -> Unit), onShareRequested: ((String) -> Unit),
onWebSearchRequested: ((String) -> Unit), onWebSearchRequested: ((String) -> Unit),
@ -263,8 +264,8 @@ fun CustomSelectionContainer(
val view = LocalView.current val view = LocalView.current
val context = LocalContext.current val context = LocalContext.current
val customSelectionToolbar = remember { val selectionToolbar = remember {
CustomSelectionToolbar( SelectionToolbar(
view = view, view = view,
context = context, context = context,
@ -285,17 +286,17 @@ fun CustomSelectionContainer(
} }
) )
} }
val isToolbarHidden = remember(customSelectionToolbar.status) { val isToolbarHidden = remember(selectionToolbar.status) {
derivedStateOf { derivedStateOf {
customSelectionToolbar.status == TextToolbarStatus.Hidden selectionToolbar.status == TextToolbarStatus.Hidden
} }
} }
CompositionLocalProvider( CompositionLocalProvider(
LocalTextToolbar provides customSelectionToolbar LocalTextToolbar provides selectionToolbar
) { ) {
SelectionContainer(Modifier.fillMaxSize()) { SelectionContainer(Modifier.fillMaxSize()) {
content(isToolbarHidden.value) content(isToolbarHidden.value)
} }
} }
} }

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
@ -34,18 +34,18 @@ import androidx.compose.ui.unit.dp
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** /**
* Custom Snackbar with vertical Swipe-To-Dismiss and animation. * Snackbar with vertical Swipe-To-Dismiss and animation.
* It is recommended to put it in Scaffold bottomBar(this way padding is the same at all sides) * It is recommended to put it in Scaffold bottomBar(this way padding is the same at all sides)
* *
* @param modifier Modifier to be applied.
* @param snackbarState Regular [SnackbarHostState], use ..remember { SnackbarHostState() } * @param snackbarState Regular [SnackbarHostState], use ..remember { SnackbarHostState() }
*/ */
@Composable @Composable
fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostState) { fun Snackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostState) {
var showSnackbar by remember { mutableStateOf(false) } var showSnackbar by remember { mutableStateOf(false) }
var snackbarData by remember { mutableStateOf(snackbarState.currentSnackbarData) } var snackbarData by remember { mutableStateOf(snackbarState.currentSnackbarData) }
var offset by remember { mutableFloatStateOf(0f) } var offset by remember { mutableFloatStateOf(0f) }
val density = LocalDensity.current val density = LocalDensity.current
val mutableInteractionSource = remember { MutableInteractionSource() } val mutableInteractionSource = remember { MutableInteractionSource() }
val isDragged by mutableInteractionSource.collectIsDraggedAsState() val isDragged by mutableInteractionSource.collectIsDraggedAsState()
@ -56,7 +56,6 @@ fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostSta
} }
} }
LaunchedEffect(offset, isDragged) { LaunchedEffect(offset, isDragged) {
val offsetDp = with(density) { offset.toDp() } val offsetDp = with(density) { offset.toDp() }
if (offsetDp > 35.dp && !isDragged) { if (offsetDp > 35.dp && !isDragged) {
@ -81,7 +80,7 @@ fun CustomSnackbar(modifier: Modifier = Modifier, snackbarState: SnackbarHostSta
showSnackbar = true showSnackbar = true
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = showSnackbar, visible = showSnackbar,
enter = slideInVertically(tween(350)) { it } + fadeIn(tween(350)), enter = slideInVertically(tween(350)) { it } + fadeIn(tween(350)),
exit = slideOutVertically(tween(200)) { it } + fadeOut(tween(100)) exit = slideOutVertically(tween(200)) { it } + fadeOut(tween(100))

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.common
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.PlainTooltip import androidx.compose.material3.PlainTooltip
@ -11,7 +11,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
/** /**
* Custom Tooltip. * Tooltip.
* Shows [text] on long press. * Shows [text] on long press.
* *
* @param text Text to show. * @param text Text to show.
@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CustomTooltip( fun Tooltip(
text: String, text: String,
padding: Dp = 14.dp, padding: Dp = 14.dp,
enabled: Boolean = true, enabled: Boolean = true,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_dialog package ua.acclorite.book_story.presentation.core.components.dialog
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -38,7 +38,7 @@ import androidx.compose.ui.window.DialogWindowProvider
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
/** /**
* Custom Dialog with custom content. * Dialog with custom content.
* *
* @param modifier Modifier to be applied. * @param modifier Modifier to be applied.
* @param drawableIcon Drawable icon to show(1/2). * @param drawableIcon Drawable icon to show(1/2).
@ -56,7 +56,7 @@ import ua.acclorite.book_story.R
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CustomDialogWithContent( fun DialogWithContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
drawableIcon: Painter? = null, drawableIcon: Painter? = null,
imageVectorIcon: ImageVector? = null, imageVectorIcon: ImageVector? = null,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_dialog package ua.acclorite.book_story.presentation.core.components.dialog
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -40,7 +40,7 @@ import ua.acclorite.book_story.R
/** /**
* Custom Dialog with lazy column. * Dialog with lazy column.
* *
* @param modifier Modifier to be applied. * @param modifier Modifier to be applied.
* @param drawableIcon Drawable icon to show(1/2). * @param drawableIcon Drawable icon to show(1/2).
@ -58,7 +58,7 @@ import ua.acclorite.book_story.R
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CustomDialogWithLazyColumn( fun DialogWithLazyColumn(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
drawableIcon: Painter? = null, drawableIcon: Painter? = null,
imageVectorIcon: ImageVector? = null, imageVectorIcon: ImageVector? = null,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_dialog package ua.acclorite.book_story.presentation.core.components.dialog
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -19,7 +19,13 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
/** /**
* Selectable dialog item. Perfectly combines with [CustomDialogWithLazyColumn]. * Selectable dialog item.
* Perfectly combines with [DialogWithLazyColumn].
*
* @param selected Whether item is selected.
* @param title Title of the item.
* @param horizontalPadding Horizontal padding of the item.
* @param onClick OnClick callback.
*/ */
@Composable @Composable
fun SelectableDialogItem( fun SelectableDialogItem(
@ -53,11 +59,4 @@ fun SelectableDialogItem(
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} }
} }

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet package ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
@ -16,7 +16,8 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.Shape
/** /**
* Custom Bottom Sheet. Fixes bugs with [ModalBottomSheet]. * Bottom Sheet.
* Fixes bugs with [ModalBottomSheet].
* *
* @param modifier [Modifier]. * @param modifier [Modifier].
* @param hasFixedHeight Whether the bottom sheet has fixed height passed through [modifier] or not. * @param hasFixedHeight Whether the bottom sheet has fixed height passed through [modifier] or not.
@ -29,7 +30,7 @@ import androidx.compose.ui.graphics.Shape
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CustomBottomSheet( fun ModalBottomSheet(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
hasFixedHeight: Boolean = false, hasFixedHeight: Boolean = false,
scrimColor: Color = BottomSheetDefaults.ScrimColor, scrimColor: Color = BottomSheetDefaults.ScrimColor,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet package ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
/** /**
* Custom Primary Row. Used in BottomSheet in pair with HorizontalPager. * Primary Tab Row. Used in BottomSheet in pair with HorizontalPager.
* Better to not use too many tabs, as they will overflow. * Better to not use too many tabs, as they will overflow.
* *
* @param selectedTabIndex Selected index, typically pager.currentPage. * @param selectedTabIndex Selected index, typically pager.currentPage.
@ -21,7 +21,7 @@ import androidx.compose.ui.text.style.TextOverflow
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun CustomBottomSheetTabRow( fun ModalBottomSheetTabRow(
selectedTabIndex: Int, selectedTabIndex: Int,
tabs: List<String>, tabs: List<String>,
onClick: (index: Int) -> Unit onClick: (index: Int) -> Unit

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_drawer package ua.acclorite.book_story.presentation.core.components.modal_drawer
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateDpAsState
@ -31,14 +31,14 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.providePrimaryScrollbar import ua.acclorite.book_story.presentation.core.constants.providePrimaryScrollbar
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
/** /**
* Custom Modal Drawer. * Modal Drawer.
* Follows Material3 guidelines. Does not require to wrap screen's content and works independently. * Follows Material3 guidelines. Does not require to wrap screen's content and works independently.
* Do not wrap in if(show) { ... }, use [show]. * Do not wrap in if(show) { ... }, use [show].
* Should be placed at the bottom of the composable to be shown at top. * Should be placed at the bottom of the composable to be shown at top.
@ -50,7 +50,7 @@ import ua.acclorite.book_story.presentation.core.util.noRippleClickable
* @param content Content inside drawer. * @param content Content inside drawer.
*/ */
@Composable @Composable
fun CustomModalDrawer( fun ModalDrawer(
show: Boolean, show: Boolean,
startIndex: Int = 0, startIndex: Int = 0,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
@ -85,7 +85,7 @@ fun CustomModalDrawer(
else Modifier.noRippleClickable(onClick = onDismissRequest) else Modifier.noRippleClickable(onClick = onDismissRequest)
) )
) { ) {
CustomAnimatedVisibility( AnimatedVisibility(
visible = show, visible = show,
enter = slideInHorizontally { (-it + with(density) { -20.dp.toPx() }).toInt() }, enter = slideInHorizontally { (-it + with(density) { -20.dp.toPx() }).toInt() },
exit = slideOutHorizontally { (-it + with(density) { -20.dp.toPx() }).toInt() } exit = slideOutHorizontally { (-it + with(density) { -20.dp.toPx() }).toInt() }
@ -125,7 +125,7 @@ fun CustomModalDrawer(
.systemBarsPadding() .systemBarsPadding()
) { ) {
header() header()
CustomLazyColumn( LazyColumnWithScrollbar(
state = rememberLazyListState(startIndex), state = rememberLazyListState(startIndex),
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
scrollbarSettings = Constants.providePrimaryScrollbar(), scrollbarSettings = Constants.providePrimaryScrollbar(),

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_drawer package ua.acclorite.book_story.presentation.core.components.modal_drawer
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.domain.util.Selected
/** /**
* Custom Modal Drawer Selectable Item. * Modal Drawer Selectable Item.
* Can be selected. * Can be selected.
* *
* @param modifier Modifier to be applied. * @param modifier Modifier to be applied.
@ -29,7 +29,7 @@ import ua.acclorite.book_story.domain.util.Selected
* @param content Content of the item. * @param content Content of the item.
*/ */
@Composable @Composable
fun CustomModalDrawerSelectableItem( fun ModalDrawerSelectableItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
selected: Selected, selected: Selected,
enabled: Boolean = true, enabled: Boolean = true,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_drawer package ua.acclorite.book_story.presentation.core.components.modal_drawer
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -14,14 +14,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
/** /**
* Custom Modal Drawer Title Item. * Modal Drawer Title Item.
* Usually displayed at the top of the drawer. * Usually displayed at the top of the drawer.
* *
* @param modifier Modifier to be applied. * @param modifier Modifier to be applied.
* @param title Title to be shown. * @param title Title to be shown.
*/ */
@Composable @Composable
fun CustomModalDrawerTitleItem( fun ModalDrawerTitleItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: String title: String
) { ) {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.bottom_navigation_bar package ua.acclorite.book_story.presentation.core.components.navigation_bar
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -13,10 +13,10 @@ import ua.acclorite.book_story.presentation.core.constants.provideNavigationItem
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance
/** /**
* Bottom navigation bar, uses default [NavigationBar]. * Navigation bar, uses default [NavigationBar].
*/ */
@Composable @Composable
fun BottomNavigationBar() { fun NavigationBar() {
var currentScreen: Route? by remember { mutableStateOf(null) } var currentScreen: Route? by remember { mutableStateOf(null) }
val navigator = LocalNavigatorInstance.current val navigator = LocalNavigatorInstance.current
@ -34,7 +34,7 @@ fun BottomNavigationBar() {
NavigationBar { NavigationBar {
Constants.provideNavigationItems().forEach { Constants.provideNavigationItems().forEach {
BottomNavigationBarItem( NavigationBarItem(
item = it, item = it,
isSelected = currentScreen == navigator.run { it.screen.getRoute() } isSelected = currentScreen == navigator.run { it.screen.getRoute() }
) { ) {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.bottom_navigation_bar package ua.acclorite.book_story.presentation.core.components.navigation_bar
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
@ -14,10 +14,10 @@ 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 ua.acclorite.book_story.domain.model.NavigationItem import ua.acclorite.book_story.domain.model.NavigationItem
import ua.acclorite.book_story.presentation.core.components.CustomTooltip import ua.acclorite.book_story.presentation.core.components.common.Tooltip
/** /**
* Bottom Navigation Bar Item, uses default [NavigationBarItem]. * Navigation Bar Item.
* *
* @param modifier Modifier. * @param modifier Modifier.
* @param item [NavigationItem]. * @param item [NavigationItem].
@ -25,7 +25,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomTooltip
* @param onClick OnClick callback. * @param onClick OnClick callback.
*/ */
@Composable @Composable
fun RowScope.BottomNavigationBarItem( fun RowScope.NavigationBarItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
item: NavigationItem, item: NavigationItem,
isSelected: Boolean, isSelected: Boolean,
@ -33,7 +33,7 @@ fun RowScope.BottomNavigationBarItem(
) { ) {
NavigationBarItem( NavigationBarItem(
label = { label = {
CustomTooltip( Tooltip(
text = stringResource(id = item.tooltip), text = stringResource(id = item.tooltip),
padding = 64.dp padding = 64.dp
) { ) {
@ -47,7 +47,7 @@ fun RowScope.BottomNavigationBarItem(
selected = isSelected, selected = isSelected,
onClick = { onClick() }, onClick = { onClick() },
icon = { icon = {
CustomTooltip( Tooltip(
text = stringResource(id = item.tooltip), text = stringResource(id = item.tooltip),
padding = 32.dp padding = 32.dp
) { ) {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_navigation_rail package ua.acclorite.book_story.presentation.core.components.navigation_rail
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -29,10 +29,10 @@ import ua.acclorite.book_story.presentation.core.constants.provideNavigationItem
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance import ua.acclorite.book_story.presentation.core.navigation.LocalNavigatorInstance
/** /**
* Custom Navigation Rail. It is used to be shown on Tablets. * Navigation Rail. It is used to be shown on Tablets.
*/ */
@Composable @Composable
fun CustomNavigationRail() { fun NavigationRail() {
var currentScreen: Route? by remember { mutableStateOf(null) } var currentScreen: Route? by remember { mutableStateOf(null) }
val navigator = LocalNavigatorInstance.current val navigator = LocalNavigatorInstance.current
val layoutDirection = LocalLayoutDirection.current val layoutDirection = LocalLayoutDirection.current
@ -72,7 +72,7 @@ fun CustomNavigationRail() {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
Constants.provideNavigationItems().forEach { Constants.provideNavigationItems().forEach {
CustomNavigationRailItem( NavigationRailItem(
item = it, item = it,
isSelected = currentScreen == navigator.run { it.screen.getRoute() } isSelected = currentScreen == navigator.run { it.screen.getRoute() }
) { ) {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components.custom_navigation_rail package ua.acclorite.book_story.presentation.core.components.navigation_rail
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
@ -13,10 +13,10 @@ 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 ua.acclorite.book_story.domain.model.NavigationItem import ua.acclorite.book_story.domain.model.NavigationItem
import ua.acclorite.book_story.presentation.core.components.CustomTooltip import ua.acclorite.book_story.presentation.core.components.common.Tooltip
/** /**
* Custom Navigation Rail item. * Navigation Rail item.
* *
* @param modifier Modifier. * @param modifier Modifier.
* @param item [NavigationItem]. * @param item [NavigationItem].
@ -24,7 +24,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomTooltip
* @param onClick OnClick callback. * @param onClick OnClick callback.
*/ */
@Composable @Composable
fun CustomNavigationRailItem( fun NavigationRailItem(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
item: NavigationItem, item: NavigationItem,
isSelected: Boolean, isSelected: Boolean,
@ -32,7 +32,7 @@ fun CustomNavigationRailItem(
) { ) {
NavigationRailItem( NavigationRailItem(
label = { label = {
CustomTooltip( Tooltip(
text = stringResource(id = item.tooltip), text = stringResource(id = item.tooltip),
padding = 48.dp padding = 48.dp
) { ) {
@ -46,7 +46,7 @@ fun CustomNavigationRailItem(
selected = isSelected, selected = isSelected,
onClick = { onClick() }, onClick = { onClick() },
icon = { icon = {
CustomTooltip( Tooltip(
text = stringResource(id = item.tooltip), text = stringResource(id = item.tooltip),
padding = 16.dp padding = 16.dp
) { ) {

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.screens.settings.components package ua.acclorite.book_story.presentation.core.components.settings
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp 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.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
/** /**
* Chips with title. Use list of [ButtonItem]s to display chips. * Chips with title. Use list of [ButtonItem]s to display chips.
@ -35,7 +35,7 @@ fun ChipsWithTitle(
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = horizontalPadding, vertical = verticalPadding) .padding(horizontal = horizontalPadding, vertical = verticalPadding)
) { ) {
CategoryTitle(title = title, padding = 0.dp) SettingsCategoryTitle(title = title, padding = 0.dp)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
FlowRow( FlowRow(

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.screens.settings.components package ua.acclorite.book_story.presentation.core.components.settings
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -30,8 +30,8 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.debounce
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
/** /**
* Color picker with title. * Color picker with title.
@ -71,7 +71,7 @@ fun ColorPickerWithTitle(
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = verticalPadding, horizontal = horizontalPadding) .padding(vertical = verticalPadding, horizontal = horizontalPadding)
) { ) {
CategoryTitle( SettingsCategoryTitle(
title = title, title = title,
padding = 0.dp padding = 0.dp
) )
@ -133,7 +133,7 @@ private fun RevertibleSlider(
) )
Spacer(modifier = Modifier.width(10.dp)) Spacer(modifier = Modifier.width(10.dp))
CustomIconButton( IconButton(
modifier = Modifier.size(28.dp), modifier = Modifier.size(28.dp),
icon = Icons.Default.History, icon = Icons.Default.History,
contentDescription = R.string.revert_content_desc, contentDescription = R.string.revert_content_desc,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.screens.settings.components package ua.acclorite.book_story.presentation.core.components.settings
import androidx.compose.animation.expandHorizontally import androidx.compose.animation.expandHorizontally
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
@ -39,8 +39,8 @@ import androidx.compose.ui.unit.Dp
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.ButtonItem import ua.acclorite.book_story.domain.model.ButtonItem
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
/** /**
* Segmented Button with Title. * Segmented Button with Title.
@ -70,7 +70,7 @@ fun SegmentedButtonWithTitle(
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = horizontalPadding, vertical = verticalPadding) .padding(horizontal = horizontalPadding, vertical = verticalPadding)
) { ) {
CategoryTitle(title = title, padding = 0.dp) SettingsCategoryTitle(title = title, padding = 0.dp)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
@ -151,7 +151,7 @@ private fun SegmentedButton(
.padding(horizontal = 18.dp), .padding(horizontal = 18.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
CustomAnimatedVisibility( AnimatedVisibility(
visible = button.selected, visible = button.selected,
enter = expandHorizontally() enter = expandHorizontally()
+ slideInVertically(initialOffsetY = { it / 2 }) + slideInVertically(initialOffsetY = { it / 2 })

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.screens.settings.components package ua.acclorite.book_story.presentation.core.components.settings
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -24,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** /**
@ -69,7 +70,7 @@ fun SliderWithTitle(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Column(Modifier.fillMaxWidth(0.2f)) { Column(Modifier.fillMaxWidth(0.2f)) {
CategoryTitle(title = title, padding = 0.dp) SettingsCategoryTitle(title = title, padding = 0.dp)
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Text( Text(
text = placeholder.value, text = placeholder.value,
@ -157,7 +158,7 @@ fun SliderWithTitle(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Column(Modifier.fillMaxWidth(0.2f)) { Column(Modifier.fillMaxWidth(0.2f)) {
CategoryTitle(title = title, padding = 0.dp) SettingsCategoryTitle(title = title, padding = 0.dp)
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Text( Text(
text = placeholder.value, text = placeholder.value,

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.screens.settings.components package ua.acclorite.book_story.presentation.core.components.settings
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.top_bar
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.collectLatest
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState( fun TopAppBarDefaults.collapsibleTopAppBarScrollBehavior(
listState: LazyListState? = null listState: LazyListState? = null
): Pair<TopAppBarScrollBehavior, LazyListState> { ): Pair<TopAppBarScrollBehavior, LazyListState> {
val lazyListState = listState ?: rememberLazyListState() val lazyListState = listState ?: rememberLazyListState()
@ -40,19 +40,4 @@ fun TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState(
} }
return scrollBehavior to lazyListState return scrollBehavior to lazyListState
} }

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.core.components.top_bar
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
@ -23,8 +23,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp import androidx.compose.ui.graphics.lerp
import ua.acclorite.book_story.domain.util.ID import ua.acclorite.book_story.domain.util.ID
import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
data class AnimatedTopAppBarData( data class TopAppBarData(
val contentID: ID, val contentID: ID,
val contentNavigationIcon: @Composable () -> Unit, val contentNavigationIcon: @Composable () -> Unit,
val contentTitle: @Composable () -> Unit, val contentTitle: @Composable () -> Unit,
@ -32,7 +33,7 @@ data class AnimatedTopAppBarData(
) )
/** /**
* Animated top app bar. * Top app bar.
* Has up to 3 different top bars inside it. Follow [TopAppBar] for more info. * Has up to 3 different top bars inside it. Follow [TopAppBar] for more info.
* *
* @param containerColor Container color of the TopBar. * @param containerColor Container color of the TopBar.
@ -40,12 +41,12 @@ data class AnimatedTopAppBarData(
* @param scrollBehavior [TopAppBarScrollBehavior]. * @param scrollBehavior [TopAppBarScrollBehavior].
* @param isTopBarScrolled Whether isScrolled state should be forced or not. * @param isTopBarScrolled Whether isScrolled state should be forced or not.
* @param shownTopBar [ID] of the top bar to show. * @param shownTopBar [ID] of the top bar to show.
* @param topBars Pass a list of all [AnimatedTopAppBarData] to show. * @param topBars Pass a list of all [TopAppBarData] to show.
* @param customContent Custom content below [TopAppBar]. * @param customContent Custom content below [TopAppBar].
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun AnimatedTopAppBar( fun TopAppBar(
containerColor: Color = MaterialTheme.colorScheme.surface, containerColor: Color = MaterialTheme.colorScheme.surface,
scrolledContainerColor: Color = MaterialTheme.colorScheme.surfaceContainer, scrolledContainerColor: Color = MaterialTheme.colorScheme.surfaceContainer,
@ -53,7 +54,7 @@ fun AnimatedTopAppBar(
isTopBarScrolled: Boolean?, isTopBarScrolled: Boolean?,
shownTopBar: ID, shownTopBar: ID,
topBars: List<AnimatedTopAppBarData>, topBars: List<TopAppBarData>,
customContent: @Composable ColumnScope.() -> Unit = {} customContent: @Composable ColumnScope.() -> Unit = {}
) { ) {
val animatedContainerColor = lerp( val animatedContainerColor = lerp(
@ -74,7 +75,7 @@ fun AnimatedTopAppBar(
) { ) {
Box(modifier = Modifier.fillMaxWidth()) { Box(modifier = Modifier.fillMaxWidth()) {
topBars.forEach { data -> topBars.forEach { data ->
CustomAnimatedVisibility( AnimatedVisibility(
visible = data.contentID == shownTopBar, visible = data.contentID == shownTopBar,
enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)), enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)),
exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow)) exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow))
@ -97,11 +98,4 @@ fun AnimatedTopAppBar(
} }
customContent() customContent()
} }
} }

View file

@ -49,7 +49,7 @@ import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import ua.acclorite.book_story.domain.util.OnNavigate import ua.acclorite.book_story.domain.util.OnNavigate
import ua.acclorite.book_story.domain.util.Route import ua.acclorite.book_story.domain.util.Route
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.ui.Transitions import ua.acclorite.book_story.presentation.ui.Transitions
private const val CURRENT_SCREEN = "current_screen" private const val CURRENT_SCREEN = "current_screen"
@ -320,7 +320,7 @@ class Navigator @AssistedInject constructor(
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = shouldShow, visible = shouldShow,
enter = if (!useBackAnimation) enterAnim else backEnterAnim, enter = if (!useBackAnimation) enterAnim else backEnterAnim,
exit = if (!useBackAnimation) exitAnim else backExitAnim exit = if (!useBackAnimation) exitAnim else backExitAnim
@ -372,7 +372,7 @@ class Navigator @AssistedInject constructor(
} }
val showNavigationBottomSheet = showNavigationBottomSheet.collectAsState() val showNavigationBottomSheet = showNavigationBottomSheet.collectAsState()
CustomAnimatedVisibility( AnimatedVisibility(
visible = showNavigation.value, visible = showNavigation.value,
enter = if (useBackAnimation) backEnterBarAnim enter = if (useBackAnimation) backEnterBarAnim
else enterBarAnim, else enterBarAnim,
@ -428,7 +428,7 @@ class Navigator @AssistedInject constructor(
/** /**
* Custom Navigation Host. Contains [Navigator.composable]s in [content]. * Custom Navigation Host. Contains [Navigator.composable]s in [content].
* Based on [CustomAnimatedVisibility]. * Based on [AnimatedVisibility].
* *
* @param startScreen Start Screen. Be sure to pass [Screen] that uses in one of your [Navigator.composable]s. * @param startScreen Start Screen. Be sure to pass [Screen] that uses in one of your [Navigator.composable]s.
* @param colorBetweenAnimations The color, that using between animations, recommended to set this to background or navigation bar color. * @param colorBetweenAnimations The color, that using between animations, recommended to set this to background or navigation bar color.

View file

@ -10,7 +10,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.util.Position import ua.acclorite.book_story.domain.util.Position
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
/** /**
* Navigation Bottom Sheet. * Navigation Bottom Sheet.
@ -23,7 +23,7 @@ import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.
fun NavigationBottomSheet(onDismissRequest: () -> Unit) { fun NavigationBottomSheet(onDismissRequest: () -> Unit) {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
CustomBottomSheet( ModalBottomSheet(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onDismissRequest = onDismissRequest onDismissRequest = onDismissRequest
) { ) {

View file

@ -4,7 +4,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
/** /**
* Navigation Icon Button. * Navigation Icon Button.
@ -15,7 +15,7 @@ fun NavigationIconButton(
onClick: Navigator.() -> Unit = { showNavigationBottomSheet() } onClick: Navigator.() -> Unit = { showNavigationBottomSheet() }
) { ) {
val navigator = LocalNavigatorInstance.current val navigator = LocalNavigatorInstance.current
CustomIconButton( IconButton(
icon = Icons.Default.MoreVert, icon = Icons.Default.MoreVert,
contentDescription = R.string.more_content_desc, contentDescription = R.string.more_content_desc,
disableOnClick = false, disableOnClick = false,

View file

@ -0,0 +1,5 @@
package ua.acclorite.book_story.presentation.core.util
fun <T> MutableList<T>.addAll(calculation: () -> List<T>) {
addAll(calculation())
}

View file

@ -1,75 +0,0 @@
package ua.acclorite.book_story.presentation.core.util
import android.content.Intent
import androidx.activity.ComponentActivity
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.ui.Modifier
fun String.removeTrailingZero(): String {
if (!this.contains('.'))
return this
return this
.dropLastWhile { it == '0' }
.dropLastWhile { it == '.' }
}
fun Double.removeDigits(digits: Int) = "%.${digits}f".format(this).replace(",", ".")
fun Intent.launchActivity(
activity: ComponentActivity,
createChooser: Boolean = false,
openInNewWindow: Boolean = true,
error: () -> Unit
) {
val intent = if (createChooser) Intent.createChooser(this, "") else this
if (openInNewWindow) {
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
try {
activity.baseContext.startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
error()
return
}
}
fun Float.calculateProgress(digits: Int): String {
return (this * 100)
.toDouble()
.removeDigits(digits)
.removeTrailingZero()
.dropWhile { it == '-' }
}
fun Float.coerceAndPreventNaN(): Float {
if (isNaN()) return 0f
return this.coerceIn(0f, 1f)
}
@OptIn(ExperimentalFoundationApi::class)
fun Modifier.noRippleClickable(
enabled: Boolean = true,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
): Modifier {
return this.combinedClickable(
indication = null,
interactionSource = null,
enabled = enabled,
onLongClick = onLongClick,
onDoubleClick = onDoubleClick,
onClick = onClick
)
}
fun String.clearMarkdown(): String {
return replace(Regex("_|\\*\\*"), "")
}
fun <T> MutableList<T>.addAll(calculation: () -> List<T>) {
addAll(calculation())
}

View file

@ -0,0 +1,24 @@
package ua.acclorite.book_story.presentation.core.util
import android.content.Intent
import androidx.activity.ComponentActivity
fun Intent.launchActivity(
activity: ComponentActivity,
createChooser: Boolean = false,
openInNewWindow: Boolean = true,
error: () -> Unit
) {
val intent = if (createChooser) Intent.createChooser(this, "") else this
if (openInNewWindow) {
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
try {
activity.baseContext.startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
error()
return
}
}

View file

@ -0,0 +1,22 @@
package ua.acclorite.book_story.presentation.core.util
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.ui.Modifier
@OptIn(ExperimentalFoundationApi::class)
fun Modifier.noRippleClickable(
enabled: Boolean = true,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
): Modifier {
return this.combinedClickable(
indication = null,
interactionSource = null,
enabled = enabled,
onLongClick = onLongClick,
onDoubleClick = onDoubleClick,
onClick = onClick
)
}

View file

@ -0,0 +1,28 @@
package ua.acclorite.book_story.presentation.core.util
fun String.removeTrailingZero(): String {
if (!this.contains('.'))
return this
return this
.dropLastWhile { it == '0' }
.dropLastWhile { it == '.' }
}
fun Double.removeDigits(digits: Int) = "%.${digits}f".format(this).replace(",", ".")
fun Float.calculateProgress(digits: Int): String {
return (this * 100)
.toDouble()
.removeDigits(digits)
.removeTrailingZero()
.dropWhile { it == '-' }
}
fun Float.coerceAndPreventNaN(): Float {
if (isNaN()) return 0f
return this.coerceIn(0f, 1f)
}
fun String.clearMarkdown(): String {
return replace(Regex("_|\\*\\*"), "")
}

View file

@ -17,11 +17,11 @@ import ua.acclorite.book_story.domain.use_case.data_store.ChangeLanguage
import ua.acclorite.book_story.domain.use_case.data_store.GetAllSettings import ua.acclorite.book_story.domain.use_case.data_store.GetAllSettings
import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore import ua.acclorite.book_story.domain.use_case.data_store.SetDatastore
import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants import ua.acclorite.book_story.presentation.core.constants.DataStoreConstants
import ua.acclorite.book_story.presentation.core.constants.provideFonts import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.core.constants.provideMainState import ua.acclorite.book_story.presentation.core.constants.provideMainState
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseFilesStructure
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseLayout import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseLayout
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseSortOrder import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.toBrowseSortOrder
@ -42,7 +42,7 @@ class MainViewModel @Inject constructor(
private val changeLanguage: ChangeLanguage, private val changeLanguage: ChangeLanguage,
private val checkForUpdates: CheckForUpdates, private val checkForUpdates: CheckForUpdates,
private val getAllSettings: GetAllSettings private val getAllSettings: GetAllSettings
) : UiViewModel<MainState, MainEvent>() { ) : UIViewModel<MainState, MainEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -28,9 +28,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
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.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideContributorsPage import ua.acclorite.book_story.presentation.core.constants.provideContributorsPage
import ua.acclorite.book_story.presentation.core.constants.provideIssuesPage import ua.acclorite.book_story.presentation.core.constants.provideIssuesPage
@ -58,7 +58,7 @@ private fun AboutScreen() {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
if (state.value.showUpdateDialog) { if (state.value.showUpdateDialog) {
AboutUpdateDialog() AboutUpdateDialog()
@ -67,7 +67,7 @@ private fun AboutScreen() {
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -78,7 +78,7 @@ private fun AboutScreen() {
navigationIcon = { navigationIcon = {
GoBackButton(onNavigate = onNavigate) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -86,11 +86,11 @@ private fun AboutScreen() {
) )
} }
) { paddingValues -> ) { paddingValues ->
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second state = lazyListState
) { ) {
item { item {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))

View file

@ -7,7 +7,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideReleasesPage import ua.acclorite.book_story.presentation.core.constants.provideReleasesPage
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
@ -27,7 +27,7 @@ fun AboutUpdateDialog() {
state.value.updateInfo!! state.value.updateInfo!!
} }
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.update_query, update.tagName), title = stringResource(id = R.string.update_query, update.tagName),
imageVectorIcon = Icons.Default.Update, imageVectorIcon = Icons.Default.Update,
description = stringResource( description = stringResource(

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.model.Badge import ua.acclorite.book_story.domain.model.Badge
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
/** /**
* About Badge Item. * About Badge Item.
@ -20,7 +20,7 @@ fun AboutBadgeItem(
onClick: () -> Unit onClick: () -> Unit
) { ) {
if (badge.imageVector == null && badge.drawable != null) { if (badge.imageVector == null && badge.drawable != null) {
CustomIconButton( IconButton(
modifier = Modifier.size(22.dp), modifier = Modifier.size(22.dp),
icon = badge.drawable, icon = badge.drawable,
contentDescription = badge.contentDescription, contentDescription = badge.contentDescription,
@ -30,7 +30,7 @@ fun AboutBadgeItem(
onClick() onClick()
} }
} else if (badge.imageVector != null && badge.drawable == null) { } else if (badge.imageVector != null && badge.drawable == null) {
CustomIconButton( IconButton(
modifier = Modifier.size(22.dp), modifier = Modifier.size(22.dp),
icon = badge.imageVector, icon = badge.imageVector,
contentDescription = badge.contentDescription, contentDescription = badge.contentDescription,

View file

@ -12,14 +12,14 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates import ua.acclorite.book_story.domain.use_case.remote.CheckForUpdates
import ua.acclorite.book_story.presentation.core.util.UiViewModel import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class AboutViewModel @Inject constructor( class AboutViewModel @Inject constructor(
private val checkForUpdates: CheckForUpdates, private val checkForUpdates: CheckForUpdates,
) : UiViewModel<AboutState, AboutEvent>() { ) : UIViewModel<AboutState, AboutEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -18,9 +18,9 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideCredits import ua.acclorite.book_story.presentation.core.constants.provideCredits
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
@ -41,12 +41,12 @@ private fun CreditsScreen() {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -57,7 +57,7 @@ private fun CreditsScreen() {
navigationIcon = { navigationIcon = {
GoBackButton(onNavigate = onNavigate) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -65,11 +65,11 @@ private fun CreditsScreen() {
) )
} }
) { paddingValues -> ) { paddingValues ->
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second state = lazyListState
) { ) {
items(Constants.provideCredits(), key = { it.name }) { items(Constants.provideCredits(), key = { it.name }) {
CreditItem(credit = it) { CreditItem(credit = it) {

View file

@ -33,10 +33,10 @@ import androidx.compose.ui.platform.LocalContext
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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
@ -76,7 +76,7 @@ private fun LicenseInfoScreen() {
val context = LocalContext.current val context = LocalContext.current
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
val licenses = remember(state.value.license?.licenses) { val licenses = remember(state.value.license?.licenses) {
state.value.license?.licenses?.toList() state.value.license?.licenses?.toList()
} }
@ -84,7 +84,7 @@ private fun LicenseInfoScreen() {
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -105,7 +105,7 @@ private fun LicenseInfoScreen() {
}, },
actions = { actions = {
if (state.value.license?.website?.isNotBlank() == true) { if (state.value.license?.website?.isNotBlank() == true) {
CustomIconButton( IconButton(
icon = Icons.Outlined.Language, icon = Icons.Outlined.Language,
contentDescription = R.string.open_in_web_content_desc, contentDescription = R.string.open_in_web_content_desc,
disableOnClick = false disableOnClick = false
@ -130,7 +130,7 @@ private fun LicenseInfoScreen() {
} }
} }
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -141,11 +141,11 @@ private fun LicenseInfoScreen() {
DefaultTransition( DefaultTransition(
visible = state.value.license != null visible = state.value.license != null
) { ) {
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second, state = lazyListState,
contentPadding = PaddingValues(horizontal = 16.dp), contentPadding = PaddingValues(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp) verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {

View file

@ -13,14 +13,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ua.acclorite.book_story.presentation.core.util.UiViewModel import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LicenseInfoViewModel @Inject constructor( class LicenseInfoViewModel @Inject constructor(
) : UiViewModel<LicenseInfoState, LicenseInfoEvent>() { ) : UIViewModel<LicenseInfoState, LicenseInfoEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -25,10 +25,10 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.about.nested.licenses.components.LicenseItem import ua.acclorite.book_story.presentation.screens.about.nested.licenses.components.LicenseItem
@ -53,14 +53,14 @@ private fun LicensesScreen() {
val state = LicensesViewModel.getState() val state = LicensesViewModel.getState()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState( val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior(
state.value.listState listState = state.value.listState
) )
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -71,7 +71,7 @@ private fun LicensesScreen() {
navigationIcon = { navigationIcon = {
GoBackButton(onNavigate = onNavigate) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -79,16 +79,16 @@ private fun LicensesScreen() {
) )
} }
) { paddingValues -> ) { paddingValues ->
CustomAnimatedVisibility( AnimatedVisibility(
visible = state.value.licenses.isNotEmpty(), visible = state.value.licenses.isNotEmpty(),
enter = fadeIn(tween(300)), enter = fadeIn(tween(300)),
exit = fadeOut(tween(300)) exit = fadeOut(tween(300))
) { ) {
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second state = lazyListState
) { ) {
item { item {
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))

View file

@ -11,13 +11,13 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.util.UiViewModel import ua.acclorite.book_story.domain.util.UIViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LicensesViewModel @Inject constructor( class LicensesViewModel @Inject constructor(
) : UiViewModel<LicensesState, LicensesEvent>() { ) : UIViewModel<LicensesState, LicensesEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -44,8 +44,8 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomSnackbar import ua.acclorite.book_story.presentation.core.components.common.Snackbar
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground import ua.acclorite.book_story.presentation.screens.book_info.components.BookInfoBackground
@ -146,7 +146,7 @@ private fun BookInfoScreen(snackbarState: SnackbarHostState) {
) )
}, },
bottomBar = { bottomBar = {
CustomSnackbar( Snackbar(
modifier = Modifier.padding(bottom = 70.dp), modifier = Modifier.padding(bottom = 70.dp),
snackbarState = snackbarState snackbarState = snackbarState
) )
@ -212,7 +212,7 @@ private fun BookInfoScreen(snackbarState: SnackbarHostState) {
contentDescription = stringResource(id = R.string.continue_reading_content_desc), contentDescription = stringResource(id = R.string.continue_reading_content_desc),
Modifier.size(24.dp) Modifier.size(24.dp)
) )
CustomAnimatedVisibility( AnimatedVisibility(
visible = !listState.canScrollBackward, visible = !listState.canScrollBackward,
enter = fadeIn() + expandHorizontally(), enter = fadeIn() + expandHorizontally(),
exit = fadeOut() + shrinkHorizontally() exit = fadeOut() + shrinkHorizontally()

View file

@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Brush
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 androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CustomCoverImage import ua.acclorite.book_story.presentation.core.components.common.AsyncImage
/** /**
* Background of the BookInfoScreen. * Background of the BookInfoScreen.
@ -21,7 +21,7 @@ import ua.acclorite.book_story.presentation.core.components.CustomCoverImage
fun BookInfoBackground(height: Dp, image: Uri) { fun BookInfoBackground(height: Dp, image: Uri) {
val background = MaterialTheme.colorScheme.surface val background = MaterialTheme.colorScheme.surface
CustomCoverImage( AsyncImage(
uri = image, uri = image,
animationDurationMillis = 300, animationDurationMillis = 300,
contentDescription = null, contentDescription = null,

View file

@ -35,7 +35,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomCoverImage import ua.acclorite.book_story.presentation.core.components.common.AsyncImage
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent 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.book_info.data.BookInfoViewModel
@ -73,7 +73,7 @@ fun BookInfoInfoSection() {
) )
) { ) {
if (state.value.book.coverImage != null) { if (state.value.book.coverImage != null) {
CustomCoverImage( AsyncImage(
uri = state.value.book.coverImage!!, uri = state.value.book.coverImage!!,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()

View file

@ -11,7 +11,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.util.Position import ua.acclorite.book_story.domain.util.Position
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
import ua.acclorite.book_story.presentation.core.navigation.NavigationItem import ua.acclorite.book_story.presentation.core.navigation.NavigationItem
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent 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.book_info.data.BookInfoViewModel
@ -26,7 +26,7 @@ import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoViewM
fun BookInfoMoreBottomSheet(snackbarState: SnackbarHostState) { fun BookInfoMoreBottomSheet(snackbarState: SnackbarHostState) {
val onEvent = BookInfoViewModel.getEvent() val onEvent = BookInfoViewModel.getEvent()
CustomBottomSheet( ModalBottomSheet(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onDismissRequest = { onDismissRequest = {
onEvent(BookInfoEvent.OnShowHideMoreBottomSheet(false)) onEvent(BookInfoEvent.OnShowHideMoreBottomSheet(false))

View file

@ -19,11 +19,11 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBar
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
@ -56,14 +56,14 @@ fun BookInfoTopBar(
val firstVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex } } val firstVisibleItemIndex by remember { derivedStateOf { listState.firstVisibleItemIndex } }
AnimatedTopAppBar( TopAppBar(
containerColor = MaterialTheme.colorScheme.surface.copy(0f), containerColor = MaterialTheme.colorScheme.surface.copy(0f),
scrollBehavior = null, scrollBehavior = null,
isTopBarScrolled = listState.canScrollBackward, isTopBarScrolled = listState.canScrollBackward,
shownTopBar = 0, shownTopBar = 0,
topBars = listOf( topBars = listOf(
AnimatedTopAppBarData( TopAppBarData(
contentID = 0, contentID = 0,
contentNavigationIcon = { contentNavigationIcon = {
if ( if (
@ -71,7 +71,7 @@ fun BookInfoTopBar(
state.value.editAuthor || state.value.editAuthor ||
state.value.editDescription state.value.editDescription
) { ) {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Outlined.ArrowBack, icon = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = R.string.exit_editing_content_desc, contentDescription = R.string.exit_editing_content_desc,
disableOnClick = true disableOnClick = true
@ -108,7 +108,7 @@ fun BookInfoTopBar(
} }
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Outlined.Refresh, icon = Icons.Outlined.Refresh,
contentDescription = R.string.refresh_book_content_desc, contentDescription = R.string.refresh_book_content_desc,
disableOnClick = false, disableOnClick = false,
@ -132,14 +132,14 @@ fun BookInfoTopBar(
onEvent(BookInfoEvent.OnShowHideMoreBottomSheet(true)) onEvent(BookInfoEvent.OnShowHideMoreBottomSheet(true))
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = state.value.editTitle || visible = state.value.editTitle ||
state.value.editAuthor || state.value.editAuthor ||
state.value.editDescription, state.value.editDescription,
enter = Transitions.DefaultTransitionIn, enter = Transitions.DefaultTransitionIn,
exit = fadeOut(tween(200)) exit = fadeOut(tween(200))
) { ) {
CustomIconButton( IconButton(
icon = Icons.Outlined.Done, icon = Icons.Outlined.Done,
contentDescription = R.string.apply_changes_content_desc, contentDescription = R.string.apply_changes_content_desc,
disableOnClick = true, disableOnClick = true,

View file

@ -18,7 +18,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent 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.book_info.data.BookInfoViewModel
@ -62,7 +62,7 @@ fun BookInfoChangeCoverBottomSheet() {
onEvent(BookInfoEvent.OnCheckCoverReset) onEvent(BookInfoEvent.OnCheckCoverReset)
} }
CustomBottomSheet( ModalBottomSheet(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onDismissRequest = { onDismissRequest = {
onEvent(BookInfoEvent.OnShowHideChangeCoverBottomSheet) onEvent(BookInfoEvent.OnShowHideChangeCoverBottomSheet)

View file

@ -10,7 +10,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent 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.book_info.data.BookInfoViewModel
@ -55,7 +55,7 @@ fun BookInfoDetailsBottomSheet() {
else "" else ""
} }
CustomBottomSheet( ModalBottomSheet(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onDismissRequest = { onDismissRequest = {
onEvent(BookInfoEvent.OnShowHideDetailsBottomSheet) onEvent(BookInfoEvent.OnShowHideDetailsBottomSheet)

View file

@ -7,7 +7,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent 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.book_info.data.BookInfoViewModel
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
@ -28,7 +28,7 @@ fun BookInfoConfirmUpdateDialog(snackbarHostState: SnackbarHostState) {
val onHistoryEvent = HistoryViewModel.getEvent() val onHistoryEvent = HistoryViewModel.getEvent()
val context = LocalContext.current val context = LocalContext.current
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.confirm_update), title = stringResource(id = R.string.confirm_update),
imageVectorIcon = Icons.Default.Update, imageVectorIcon = Icons.Default.Update,
description = stringResource( description = stringResource(

View file

@ -6,7 +6,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
@ -30,7 +30,7 @@ fun BookInfoDeleteDialog() {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.delete_book), title = stringResource(id = R.string.delete_book),
imageVectorIcon = Icons.Outlined.DeleteOutline, imageVectorIcon = Icons.Outlined.DeleteOutline,
description = stringResource( description = stringResource(

View file

@ -10,8 +10,8 @@ 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.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.core.components.dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent import ua.acclorite.book_story.presentation.screens.book_info.data.BookInfoEvent
@ -42,7 +42,7 @@ fun BookInfoMoveDialog() {
onEvent(BookInfoEvent.OnSelectCategory(categories[0])) onEvent(BookInfoEvent.OnSelectCategory(categories[0]))
} }
CustomDialogWithLazyColumn( DialogWithLazyColumn(
title = stringResource(id = R.string.move_book), title = stringResource(id = R.string.move_book),
imageVectorIcon = Icons.AutoMirrored.Outlined.DriveFileMove, imageVectorIcon = Icons.AutoMirrored.Outlined.DriveFileMove,
description = stringResource( description = stringResource(

View file

@ -35,8 +35,8 @@ import ua.acclorite.book_story.domain.use_case.book.UpdateCoverImageOfBook
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -53,7 +53,7 @@ class BookInfoViewModel @Inject constructor(
private val canResetCover: CanResetCover, private val canResetCover: CanResetCover,
private val resetCoverImage: ResetCoverImage, private val resetCoverImage: ResetCoverImage,
private val checkForTextUpdate: CheckForTextUpdate, private val checkForTextUpdate: CheckForTextUpdate,
) : UiViewModel<BookInfoState, BookInfoEvent>() { ) : UIViewModel<BookInfoState, BookInfoEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -9,9 +9,9 @@ import androidx.compose.ui.res.stringResource
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.core.components.placeholder.EmptyPlaceholder
import ua.acclorite.book_story.presentation.core.components.is_messages.IsError import ua.acclorite.book_story.presentation.core.components.placeholder.ErrorPlaceholder
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
@ -35,13 +35,13 @@ fun BoxScope.BrowseEmptyPlaceholder(
val onEvent = BrowseViewModel.getEvent() val onEvent = BrowseViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
CustomAnimatedVisibility( AnimatedVisibility(
visible = state.value.isError, visible = state.value.isError,
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
enter = Transitions.DefaultTransitionIn, enter = Transitions.DefaultTransitionIn,
exit = Transitions.NoExitAnimation exit = Transitions.NoExitAnimation
) { ) {
IsError( ErrorPlaceholder(
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
errorMessage = stringResource(id = R.string.error_permission), errorMessage = stringResource(id = R.string.error_permission),
icon = painterResource(id = R.drawable.error), icon = painterResource(id = R.drawable.error),
@ -53,7 +53,7 @@ fun BoxScope.BrowseEmptyPlaceholder(
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = !state.value.isLoading visible = !state.value.isLoading
&& isFilesEmpty && isFilesEmpty
&& !state.value.isError && !state.value.isError
@ -63,7 +63,7 @@ fun BoxScope.BrowseEmptyPlaceholder(
enter = Transitions.DefaultTransitionIn, enter = Transitions.DefaultTransitionIn,
exit = Transitions.NoExitAnimation exit = Transitions.NoExitAnimation
) { ) {
IsEmpty( EmptyPlaceholder(
message = stringResource(id = R.string.browse_empty), message = stringResource(id = R.string.browse_empty),
icon = painterResource(id = R.drawable.empty_browse), icon = painterResource(id = R.drawable.empty_browse),
actionTitle = stringResource(id = R.string.get_help), actionTitle = stringResource(id = R.string.get_help),

View file

@ -9,7 +9,7 @@ import androidx.compose.ui.res.stringResource
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionState
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent 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.browse.data.BrowseViewModel
@ -26,7 +26,7 @@ fun BrowseStoragePermissionDialog(
val activity = LocalContext.current as ComponentActivity val activity = LocalContext.current as ComponentActivity
val onEvent = BrowseViewModel.getEvent() val onEvent = BrowseViewModel.getEvent()
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.storage_permission), title = stringResource(id = R.string.storage_permission),
description = stringResource(id = R.string.storage_permission_description), description = stringResource(id = R.string.storage_permission_description),
actionText = stringResource(id = R.string.grant), actionText = stringResource(id = R.string.grant),

View file

@ -18,7 +18,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.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
@ -39,7 +39,7 @@ fun BrowseAddingDialog() {
val onLibraryEvent = LibraryViewModel.getEvent() val onLibraryEvent = LibraryViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
CustomDialogWithLazyColumn( DialogWithLazyColumn(
title = stringResource(id = R.string.add_books), title = stringResource(id = R.string.add_books),
imageVectorIcon = Icons.Default.AddChart, imageVectorIcon = Icons.Default.AddChart,
description = stringResource(id = R.string.add_books_description), description = stringResource(id = R.string.add_books_description),

View file

@ -22,7 +22,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.NullableBook import ua.acclorite.book_story.domain.model.NullableBook
import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.domain.util.Selected
import ua.acclorite.book_story.presentation.core.components.CustomCheckbox import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
/** /**
* Adding dialog item. * Adding dialog item.
@ -62,7 +62,7 @@ fun BrowseAddingDialogItem(result: Pair<NullableBook, Selected>, onClick: (Boole
} }
Row { Row {
Spacer(modifier = Modifier.width(24.dp)) Spacer(modifier = Modifier.width(24.dp))
CustomCheckbox( CircularCheckbox(
selected = result.second, selected = result.second,
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
) )

View file

@ -9,8 +9,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent 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.browse.data.BrowseViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory import ua.acclorite.book_story.presentation.screens.settings.nested.browse.components.subcategories.BrowseFilterSubcategory
@ -37,7 +37,7 @@ fun BrowseFilterBottomSheet() {
) )
} }
CustomBottomSheet( ModalBottomSheet(
hasFixedHeight = true, hasFixedHeight = true,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -55,7 +55,7 @@ fun BrowseFilterBottomSheet() {
HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize()) { page -> HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize()) { page ->
when (page) { when (page) {
0 -> { 0 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
BrowseGeneralSubcategory( BrowseGeneralSubcategory(
showTitle = false, showTitle = false,
showDivider = false, showDivider = false,
@ -66,7 +66,7 @@ fun BrowseFilterBottomSheet() {
} }
1 -> { 1 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
BrowseFilterSubcategory( BrowseFilterSubcategory(
showTitle = false, showTitle = false,
showDivider = false, showDivider = false,
@ -77,7 +77,7 @@ fun BrowseFilterBottomSheet() {
} }
2 -> { 2 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
BrowseSortSubcategory( BrowseSortSubcategory(
showTitle = false, showTitle = false,
showDivider = false, showDivider = false,

View file

@ -4,7 +4,7 @@ import androidx.compose.foundation.pager.PagerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.presentation.core.components.custom_bottom_sheet.CustomBottomSheetTabRow import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheetTabRow
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
/** /**
@ -25,7 +25,7 @@ fun BrowseFilterBottomSheetTabRow(
stringResource(id = R.string.sort_tab) stringResource(id = R.string.sort_tab)
) )
CustomBottomSheetTabRow( ModalBottomSheetTabRow(
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,
tabs = tabItems tabs = tabItems
) { index -> ) { index ->

View file

@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.CustomCheckbox import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.DefaultTransition
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -73,7 +73,7 @@ fun BrowseGridDirectoryItem(
.align(Alignment.TopStart) .align(Alignment.TopStart)
.padding(12.dp) .padding(12.dp)
) { ) {
CustomCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp size = 18.dp

View file

@ -24,7 +24,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.CustomCheckbox import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.DefaultTransition
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@ -76,7 +76,7 @@ fun BrowseGridFileItem(file: SelectableFile, hasSelectedFiles: Boolean) {
visible = hasSelectedFiles, visible = hasSelectedFiles,
modifier = Modifier.align(Alignment.TopStart) modifier = Modifier.align(Alignment.TopStart)
) { ) {
CustomCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp, size = 18.dp,

View file

@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.header import ua.acclorite.book_story.presentation.core.components.common.header
import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem import ua.acclorite.book_story.presentation.screens.browse.components.layout.BrowseItem
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel import ua.acclorite.book_story.presentation.screens.browse.data.BrowseViewModel
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout

View file

@ -25,7 +25,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.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.CustomCheckbox import ua.acclorite.book_story.presentation.core.components.common.CircularCheckbox
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace
@ -68,7 +68,7 @@ fun BrowseListItem(
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
CustomCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp size = 18.dp
@ -87,7 +87,7 @@ fun BrowseListItem(
Box(contentAlignment = Alignment.Center) { Box(contentAlignment = Alignment.Center) {
FadeTransitionPreservingSpace(hasSelectedFiles) { FadeTransitionPreservingSpace(hasSelectedFiles) {
CustomCheckbox( CircularCheckbox(
selected = file.isSelected, selected = file.isSelected,
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
size = 18.dp size = 18.dp

View file

@ -25,10 +25,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.SelectableFile import ua.acclorite.book_story.domain.model.SelectableFile
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.common.SearchTextField
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBar
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
@ -76,7 +76,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
} }
} }
AnimatedTopAppBar( TopAppBar(
scrollBehavior = null, scrollBehavior = null,
isTopBarScrolled = isScrolled.value || state.value.hasSelectedItems, isTopBarScrolled = isScrolled.value || state.value.hasSelectedItems,
@ -87,7 +87,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
else -> 0 else -> 0
}, },
topBars = listOf( topBars = listOf(
AnimatedTopAppBarData( TopAppBarData(
contentID = 0, contentID = 0,
contentNavigationIcon = {}, contentNavigationIcon = {},
contentTitle = { contentTitle = {
@ -98,14 +98,14 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
) )
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Default.Search, icon = Icons.Default.Search,
contentDescription = R.string.search_content_desc, contentDescription = R.string.search_content_desc,
disableOnClick = true disableOnClick = true
) { ) {
onEvent(BrowseEvent.OnSearchShowHide) onEvent(BrowseEvent.OnSearchShowHide)
} }
CustomIconButton( IconButton(
icon = Icons.Default.FilterList, icon = Icons.Default.FilterList,
contentDescription = R.string.filter_content_desc, contentDescription = R.string.filter_content_desc,
disableOnClick = false, disableOnClick = false,
@ -123,10 +123,10 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
} }
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 1, contentID = 1,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.go_back_content_desc, contentDescription = R.string.go_back_content_desc,
disableOnClick = false, disableOnClick = false,
@ -143,14 +143,14 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
) )
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Default.Search, icon = Icons.Default.Search,
contentDescription = R.string.search_content_desc, contentDescription = R.string.search_content_desc,
disableOnClick = true disableOnClick = true
) { ) {
onEvent(BrowseEvent.OnSearchShowHide) onEvent(BrowseEvent.OnSearchShowHide)
} }
CustomIconButton( IconButton(
icon = Icons.Default.FilterList, icon = Icons.Default.FilterList,
contentDescription = R.string.filter_content_desc, contentDescription = R.string.filter_content_desc,
disableOnClick = false, disableOnClick = false,
@ -168,10 +168,10 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
} }
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 2, contentID = 2,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.exit_search_content_desc, contentDescription = R.string.exit_search_content_desc,
disableOnClick = true disableOnClick = true
@ -180,7 +180,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
} }
}, },
contentTitle = { contentTitle = {
CustomSearchTextField( SearchTextField(
modifier = Modifier modifier = Modifier
.focusRequester(focusRequester) .focusRequester(focusRequester)
.onGloballyPositioned { .onGloballyPositioned {
@ -192,11 +192,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
}, },
onSearch = { onSearch = {
onEvent(BrowseEvent.OnSearch) onEvent(BrowseEvent.OnSearch)
}, }
placeholder = stringResource(
id = R.string.search_query,
stringResource(id = R.string.files)
)
) )
}, },
contentActions = { contentActions = {
@ -204,10 +200,10 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
} }
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 3, contentID = 3,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.Default.Clear, icon = Icons.Default.Clear,
contentDescription = R.string.clear_selected_items_content_desc, contentDescription = R.string.clear_selected_items_content_desc,
disableOnClick = true disableOnClick = true
@ -226,7 +222,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
) )
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Default.SelectAll, icon = Icons.Default.SelectAll,
contentDescription = R.string.select_all_files_content_desc, contentDescription = R.string.select_all_files_content_desc,
disableOnClick = false, disableOnClick = false,
@ -238,7 +234,7 @@ fun BrowseTopBar(filteredFiles: List<SelectableFile>) {
) )
) )
} }
CustomIconButton( IconButton(
icon = Icons.Default.Check, icon = Icons.Default.Check,
contentDescription = R.string.add_files_content_desc, contentDescription = R.string.add_files_content_desc,
disableOnClick = false, disableOnClick = false,

View file

@ -26,7 +26,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent
@ -84,7 +84,7 @@ fun BrowseTopBarDirectoryPath() {
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = !state.value.hasSelectedItems visible = !state.value.hasSelectedItems
&& !state.value.hasSearched && !state.value.hasSearched
&& !state.value.isError && !state.value.isError

View file

@ -29,8 +29,8 @@ import ua.acclorite.book_story.domain.use_case.book.InsertBook
import ua.acclorite.book_story.domain.use_case.favorite_directory.UpdateFavoriteDirectory import ua.acclorite.book_story.domain.use_case.favorite_directory.UpdateFavoriteDirectory
import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile import ua.acclorite.book_story.domain.use_case.file_system.GetBookFromFile
import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice import ua.acclorite.book_story.domain.use_case.file_system.GetFilesFromDevice
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import ua.acclorite.book_story.presentation.data.MainState import ua.acclorite.book_story.presentation.data.MainState
import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure
@ -44,7 +44,7 @@ class BrowseViewModel @Inject constructor(
private val getFilesFromDevice: GetFilesFromDevice, private val getFilesFromDevice: GetFilesFromDevice,
private val insertBook: InsertBook, private val insertBook: InsertBook,
private val updateFavoriteDirectory: UpdateFavoriteDirectory, private val updateFavoriteDirectory: UpdateFavoriteDirectory,
) : UiViewModel<BrowseState, BrowseEvent>() { ) : UIViewModel<BrowseState, BrowseEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -29,10 +29,10 @@ 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.util.Position import ua.acclorite.book_story.domain.util.Position
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideHelpTips import ua.acclorite.book_story.presentation.core.constants.provideHelpTips
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
@ -74,12 +74,12 @@ private fun HelpScreen() {
val onStartEvent = StartViewModel.getEvent() val onStartEvent = StartViewModel.getEvent()
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -94,7 +94,7 @@ private fun HelpScreen() {
}, },
actions = { actions = {
if (!state.value.fromStart) { if (!state.value.fromStart) {
CustomIconButton( IconButton(
icon = Icons.Outlined.RestartAlt, icon = Icons.Outlined.RestartAlt,
contentDescription = R.string.reset_start_content_desc, contentDescription = R.string.reset_start_content_desc,
disableOnClick = false disableOnClick = false
@ -108,7 +108,7 @@ private fun HelpScreen() {
} }
} }
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -140,11 +140,11 @@ private fun HelpScreen() {
} }
} }
) { paddingValues -> ) { paddingValues ->
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(paddingValues), .padding(paddingValues),
state = scrollState.second state = lazyListState
) { ) {
item { item {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))

View file

@ -18,7 +18,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
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.presentation.core.components.CustomTooltip import ua.acclorite.book_story.presentation.core.components.common.Tooltip
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.ui.ExpandingTransition import ua.acclorite.book_story.presentation.ui.ExpandingTransition
@ -33,7 +33,7 @@ fun HelpClickableNote(text: AnnotatedString) {
val showNote = rememberSaveable { mutableStateOf(true) } val showNote = rememberSaveable { mutableStateOf(true) }
Column(Modifier.padding(horizontal = 18.dp)) { Column(Modifier.padding(horizontal = 18.dp)) {
CustomTooltip(text = stringResource(R.string.note_content_desc)) { Tooltip(text = stringResource(R.string.note_content_desc)) {
Icon( Icon(
imageVector = Icons.Outlined.Info, imageVector = Icons.Outlined.Info,
modifier = Modifier modifier = Modifier

View file

@ -5,13 +5,13 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import ua.acclorite.book_story.presentation.core.util.UiViewModel import ua.acclorite.book_story.domain.util.UIViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class HelpViewModel @Inject constructor( class HelpViewModel @Inject constructor(
) : UiViewModel<HelpState, HelpEvent>() { ) : UIViewModel<HelpState, HelpEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -36,14 +36,13 @@ import androidx.compose.ui.res.painterResource
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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.common.SearchTextField
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.Snackbar
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.placeholder.EmptyPlaceholder
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBar
import ua.acclorite.book_story.presentation.core.components.CustomSnackbar import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
@ -53,6 +52,7 @@ 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.history.data.HistoryViewModel
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent 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.presentation.screens.library.data.LibraryViewModel
import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryTitle
import ua.acclorite.book_story.presentation.ui.DefaultTransition import ua.acclorite.book_story.presentation.ui.DefaultTransition
import ua.acclorite.book_story.presentation.ui.Transitions import ua.acclorite.book_story.presentation.ui.Transitions
@ -98,7 +98,7 @@ private fun HistoryScreen() {
.pullRefresh(refreshState), .pullRefresh(refreshState),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
AnimatedTopAppBar( TopAppBar(
scrollBehavior = null, scrollBehavior = null,
isTopBarScrolled = state.value.listState.canScrollBackward, isTopBarScrolled = state.value.listState.canScrollBackward,
@ -107,21 +107,21 @@ private fun HistoryScreen() {
else -> 0 else -> 0
}, },
topBars = listOf( topBars = listOf(
AnimatedTopAppBarData( TopAppBarData(
contentID = 0, contentID = 0,
contentNavigationIcon = {}, contentNavigationIcon = {},
contentTitle = { contentTitle = {
Text(stringResource(id = R.string.history_screen)) Text(stringResource(id = R.string.history_screen))
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Default.Search, icon = Icons.Default.Search,
contentDescription = R.string.search_content_desc, contentDescription = R.string.search_content_desc,
disableOnClick = true, disableOnClick = true,
) { ) {
onEvent(HistoryEvent.OnSearchShowHide) onEvent(HistoryEvent.OnSearchShowHide)
} }
CustomIconButton( IconButton(
icon = Icons.Outlined.DeleteSweep, icon = Icons.Outlined.DeleteSweep,
contentDescription = R.string.delete_whole_history_content_desc, contentDescription = R.string.delete_whole_history_content_desc,
disableOnClick = false, disableOnClick = false,
@ -136,10 +136,10 @@ private fun HistoryScreen() {
} }
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 1, contentID = 1,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.exit_search_content_desc, contentDescription = R.string.exit_search_content_desc,
disableOnClick = true disableOnClick = true
@ -148,7 +148,7 @@ private fun HistoryScreen() {
} }
}, },
contentTitle = { contentTitle = {
CustomSearchTextField( SearchTextField(
modifier = Modifier modifier = Modifier
.focusRequester(focusRequester) .focusRequester(focusRequester)
.onGloballyPositioned { .onGloballyPositioned {
@ -160,11 +160,7 @@ private fun HistoryScreen() {
}, },
onSearch = { onSearch = {
onEvent(HistoryEvent.OnSearch) onEvent(HistoryEvent.OnSearch)
}, }
placeholder = stringResource(
id = R.string.search_query,
stringResource(id = R.string.history)
)
) )
}, },
contentActions = { contentActions = {
@ -175,7 +171,7 @@ private fun HistoryScreen() {
) )
}, },
bottomBar = { bottomBar = {
CustomSnackbar(snackbarState = snackbarState) Snackbar(snackbarState = snackbarState)
} }
) { paddingValues -> ) { paddingValues ->
Box( Box(
@ -199,7 +195,7 @@ private fun HistoryScreen() {
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
} }
CategoryTitle( SettingsCategoryTitle(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
title = when (groupedHistory.title) { title = when (groupedHistory.title) {
"today" -> stringResource(id = R.string.today) "today" -> stringResource(id = R.string.today)
@ -263,7 +259,7 @@ private fun HistoryScreen() {
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = !state.value.isLoading visible = !state.value.isLoading
&& state.value.history.isEmpty() && state.value.history.isEmpty()
&& !state.value.isRefreshing, && !state.value.isRefreshing,
@ -271,7 +267,7 @@ private fun HistoryScreen() {
enter = Transitions.DefaultTransitionIn, enter = Transitions.DefaultTransitionIn,
exit = fadeOut(tween(0)) exit = fadeOut(tween(0))
) { ) {
IsEmpty( EmptyPlaceholder(
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
message = stringResource(id = R.string.history_empty), message = stringResource(id = R.string.history_empty),
icon = painterResource(id = R.drawable.empty_history) icon = painterResource(id = R.drawable.empty_history)

View file

@ -6,7 +6,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent 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.history.data.HistoryViewModel
@ -22,7 +22,7 @@ fun HistoryDeleteWholeHistoryDialog() {
val onEvent = HistoryViewModel.getEvent() val onEvent = HistoryViewModel.getEvent()
val onLibraryEvent = LibraryViewModel.getEvent() val onLibraryEvent = LibraryViewModel.getEvent()
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.delete_history), title = stringResource(id = R.string.delete_history),
imageVectorIcon = Icons.Outlined.DeleteOutline, imageVectorIcon = Icons.Outlined.DeleteOutline,
description = stringResource( description = stringResource(

View file

@ -32,8 +32,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.History import ua.acclorite.book_story.domain.model.History
import ua.acclorite.book_story.presentation.core.components.CustomCoverImage import ua.acclorite.book_story.presentation.core.components.common.AsyncImage
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@ -88,7 +88,7 @@ fun HistoryItem(
) )
) { ) {
if (history.book?.coverImage != null) { if (history.book?.coverImage != null) {
CustomCoverImage( AsyncImage(
uri = history.book.coverImage, uri = history.book.coverImage,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -141,7 +141,7 @@ fun HistoryItem(
} }
} }
Box(modifier = Modifier.weight(0.11f), contentAlignment = Alignment.CenterEnd) { Box(modifier = Modifier.weight(0.11f), contentAlignment = Alignment.CenterEnd) {
CustomIconButton( IconButton(
icon = Icons.Outlined.Delete, icon = Icons.Outlined.Delete,
contentDescription = R.string.delete_history_element_content_desc, contentDescription = R.string.delete_history_element_content_desc,
disableOnClick = true, disableOnClick = true,

View file

@ -21,8 +21,8 @@ import ua.acclorite.book_story.domain.use_case.history.DeleteHistory
import ua.acclorite.book_story.domain.use_case.history.DeleteWholeHistory import ua.acclorite.book_story.domain.use_case.history.DeleteWholeHistory
import ua.acclorite.book_story.domain.use_case.history.GetHistory import ua.acclorite.book_story.domain.use_case.history.GetHistory
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
@ -36,7 +36,7 @@ class HistoryViewModel @Inject constructor(
private val deleteWholeHistory: DeleteWholeHistory, private val deleteWholeHistory: DeleteWholeHistory,
private val deleteHistory: DeleteHistory, private val deleteHistory: DeleteHistory,
private val getBooksById: GetBooksById private val getBooksById: GetBooksById
) : UiViewModel<HistoryState, HistoryEvent>() { ) : UIViewModel<HistoryState, HistoryEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -46,9 +46,9 @@ import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.model.Category import ua.acclorite.book_story.domain.model.Category
import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.domain.util.Selected
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.header import ua.acclorite.book_story.presentation.core.components.common.header
import ua.acclorite.book_story.presentation.core.components.is_messages.IsEmpty import ua.acclorite.book_story.presentation.core.components.placeholder.EmptyPlaceholder
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
@ -208,7 +208,7 @@ private fun LibraryScreen(
} }
} }
CustomAnimatedVisibility( AnimatedVisibility(
visible = !state.value.isLoading visible = !state.value.isLoading
&& !state.value.isRefreshing && !state.value.isRefreshing
&& books.isEmpty(), && books.isEmpty(),
@ -216,7 +216,7 @@ private fun LibraryScreen(
enter = Transitions.DefaultTransitionIn, enter = Transitions.DefaultTransitionIn,
exit = fadeOut(tween(0)) exit = fadeOut(tween(0))
) { ) {
IsEmpty( EmptyPlaceholder(
message = stringResource(id = R.string.library_empty), message = stringResource(id = R.string.library_empty),
icon = painterResource(id = R.drawable.empty_library), icon = painterResource(id = R.drawable.empty_library),
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),

View file

@ -34,7 +34,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.Book import ua.acclorite.book_story.domain.model.Book
import ua.acclorite.book_story.domain.util.Selected import ua.acclorite.book_story.domain.util.Selected
import ua.acclorite.book_story.presentation.core.components.CustomCoverImage import ua.acclorite.book_story.presentation.core.components.common.AsyncImage
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
/** /**
@ -101,7 +101,7 @@ fun LibraryBookItem(
) )
) { ) {
if (book.first.coverImage != null) { if (book.first.coverImage != null) {
CustomCoverImage( AsyncImage(
uri = book.first.coverImage!!, uri = book.first.coverImage!!,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()

View file

@ -31,17 +31,17 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.common.SearchTextField
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBar
import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.top_bar.TopAppBarData
import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton import ua.acclorite.book_story.presentation.core.navigation.NavigationIconButton
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent 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.presentation.screens.library.data.LibraryViewModel
/** /**
* Library Top Bar. * Library Top Bar.
* Contains [AnimatedTopAppBar] and [LibraryTabRow]. * Contains [TopAppBar] and [LibraryTabRow].
* *
* @param pagerState [PagerState]. * @param pagerState [PagerState].
*/ */
@ -52,7 +52,7 @@ fun LibraryTopBar(pagerState: PagerState) {
val onEvent = LibraryViewModel.getEvent() val onEvent = LibraryViewModel.getEvent()
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
AnimatedTopAppBar( TopAppBar(
scrollBehavior = null, scrollBehavior = null,
isTopBarScrolled = state.value.hasSelectedItems, isTopBarScrolled = state.value.hasSelectedItems,
@ -62,7 +62,7 @@ fun LibraryTopBar(pagerState: PagerState) {
else -> 0 else -> 0
}, },
topBars = listOf( topBars = listOf(
AnimatedTopAppBarData( TopAppBarData(
contentID = 0, contentID = 0,
contentNavigationIcon = {}, contentNavigationIcon = {},
contentTitle = { contentTitle = {
@ -83,7 +83,7 @@ fun LibraryTopBar(pagerState: PagerState) {
} }
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.Default.Search, icon = Icons.Default.Search,
contentDescription = R.string.search_content_desc, contentDescription = R.string.search_content_desc,
disableOnClick = true, disableOnClick = true,
@ -94,10 +94,10 @@ fun LibraryTopBar(pagerState: PagerState) {
} }
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 1, contentID = 1,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.exit_search_content_desc, contentDescription = R.string.exit_search_content_desc,
disableOnClick = true disableOnClick = true
@ -108,7 +108,7 @@ fun LibraryTopBar(pagerState: PagerState) {
} }
}, },
contentTitle = { contentTitle = {
CustomSearchTextField( SearchTextField(
modifier = Modifier modifier = Modifier
.focusRequester(focusRequester) .focusRequester(focusRequester)
.onGloballyPositioned { .onGloballyPositioned {
@ -120,11 +120,7 @@ fun LibraryTopBar(pagerState: PagerState) {
}, },
onSearch = { onSearch = {
onEvent(LibraryEvent.OnSearch) onEvent(LibraryEvent.OnSearch)
}, }
placeholder = stringResource(
id = R.string.search_query,
stringResource(id = R.string.books)
)
) )
}, },
contentActions = { contentActions = {
@ -132,10 +128,10 @@ fun LibraryTopBar(pagerState: PagerState) {
}, },
), ),
AnimatedTopAppBarData( TopAppBarData(
contentID = 2, contentID = 2,
contentNavigationIcon = { contentNavigationIcon = {
CustomIconButton( IconButton(
icon = Icons.Default.Clear, icon = Icons.Default.Clear,
contentDescription = R.string.clear_selected_items_content_desc, contentDescription = R.string.clear_selected_items_content_desc,
disableOnClick = true disableOnClick = true
@ -154,7 +150,7 @@ fun LibraryTopBar(pagerState: PagerState) {
) )
}, },
contentActions = { contentActions = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Outlined.DriveFileMove, icon = Icons.AutoMirrored.Outlined.DriveFileMove,
contentDescription = R.string.move_books_content_desc, contentDescription = R.string.move_books_content_desc,
enabled = !state.value.isLoading enabled = !state.value.isLoading
@ -165,7 +161,7 @@ fun LibraryTopBar(pagerState: PagerState) {
) { ) {
onEvent(LibraryEvent.OnShowHideMoveDialog) onEvent(LibraryEvent.OnShowHideMoveDialog)
} }
CustomIconButton( IconButton(
icon = Icons.Outlined.Delete, icon = Icons.Outlined.Delete,
contentDescription = R.string.delete_books_content_desc, contentDescription = R.string.delete_books_content_desc,
enabled = !state.value.isLoading enabled = !state.value.isLoading

View file

@ -6,7 +6,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent 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.browse.data.BrowseViewModel
@ -26,7 +26,7 @@ fun LibraryDeleteDialog() {
val onBrowseEvent = BrowseViewModel.getEvent() val onBrowseEvent = BrowseViewModel.getEvent()
val onHistoryEvent = HistoryViewModel.getEvent() val onHistoryEvent = HistoryViewModel.getEvent()
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.delete_books), title = stringResource(id = R.string.delete_books),
imageVectorIcon = Icons.Outlined.DeleteOutline, imageVectorIcon = Icons.Outlined.DeleteOutline,
description = stringResource( description = stringResource(

View file

@ -9,8 +9,8 @@ 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.core.components.custom_dialog.CustomDialogWithLazyColumn import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithLazyColumn
import ua.acclorite.book_story.presentation.core.components.custom_dialog.SelectableDialogItem import ua.acclorite.book_story.presentation.core.components.dialog.SelectableDialogItem
import ua.acclorite.book_story.presentation.core.util.showToast import ua.acclorite.book_story.presentation.core.util.showToast
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent 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.history.data.HistoryViewModel
@ -27,7 +27,7 @@ fun LibraryMoveDialog(pagerState: PagerState) {
val onEvent = LibraryViewModel.getEvent() val onEvent = LibraryViewModel.getEvent()
val onHistoryEvent = HistoryViewModel.getEvent() val onHistoryEvent = HistoryViewModel.getEvent()
CustomDialogWithLazyColumn( DialogWithLazyColumn(
title = stringResource(id = R.string.move_books), title = stringResource(id = R.string.move_books),
imageVectorIcon = Icons.AutoMirrored.Outlined.DriveFileMove, imageVectorIcon = Icons.AutoMirrored.Outlined.DriveFileMove,
description = stringResource( description = stringResource(

View file

@ -18,8 +18,8 @@ import ua.acclorite.book_story.domain.use_case.book.DeleteBooks
import ua.acclorite.book_story.domain.use_case.book.GetBooks import ua.acclorite.book_story.domain.use_case.book.GetBooks
import ua.acclorite.book_story.domain.use_case.book.UpdateBook import ua.acclorite.book_story.domain.use_case.book.UpdateBook
import ua.acclorite.book_story.domain.use_case.history.InsertHistory import ua.acclorite.book_story.domain.use_case.history.InsertHistory
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
@ -29,7 +29,7 @@ class LibraryViewModel @Inject constructor(
private val updateBook: UpdateBook, private val updateBook: UpdateBook,
private val deleteBooks: DeleteBooks, private val deleteBooks: DeleteBooks,
private val insertHistory: InsertHistory private val insertHistory: InsertHistory
) : UiViewModel<LibraryState, LibraryEvent>() { ) : UIViewModel<LibraryState, LibraryEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -59,9 +59,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.domain.model.Chapter import ua.acclorite.book_story.domain.model.Chapter
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomSelectionContainer import ua.acclorite.book_story.presentation.core.components.common.SelectionContainer
import ua.acclorite.book_story.presentation.core.components.is_messages.IsError import ua.acclorite.book_story.presentation.core.components.placeholder.ErrorPlaceholder
import ua.acclorite.book_story.presentation.core.constants.Constants import ua.acclorite.book_story.presentation.core.constants.Constants
import ua.acclorite.book_story.presentation.core.constants.provideFonts import ua.acclorite.book_story.presentation.core.constants.provideFonts
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
@ -381,7 +381,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
.nestedScroll(nestedScrollConnection), .nestedScroll(nestedScrollConnection),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
CustomAnimatedVisibility( AnimatedVisibility(
visible = state.value.showMenu, visible = state.value.showMenu,
enter = slideInVertically { -it }, enter = slideInVertically { -it },
exit = slideOutVertically { -it } exit = slideOutVertically { -it }
@ -390,7 +390,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
} }
}, },
bottomBar = { bottomBar = {
CustomAnimatedVisibility( AnimatedVisibility(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
visible = state.value.showMenu, visible = state.value.showMenu,
enter = slideInVertically { it }, enter = slideInVertically { it },
@ -400,7 +400,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
} }
} }
) { ) {
CustomSelectionContainer( SelectionContainer(
onCopyRequested = { onCopyRequested = {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
context.getString(R.string.copied) context.getString(R.string.copied)
@ -537,7 +537,7 @@ private fun ReaderScreen(lazyListState: LazyListState) {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
if (!state.value.loading) { if (!state.value.loading) {
IsError( ErrorPlaceholder(
errorMessage = state.value.errorMessage!!.asString(), errorMessage = state.value.errorMessage!!.asString(),
icon = painterResource(id = R.drawable.error), icon = painterResource(id = R.drawable.error),
actionTitle = stringResource(id = R.string.go_back), actionTitle = stringResource(id = R.string.go_back),

View file

@ -11,9 +11,9 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawer import ua.acclorite.book_story.presentation.core.components.modal_drawer.ModalDrawer
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerSelectableItem import ua.acclorite.book_story.presentation.core.components.modal_drawer.ModalDrawerSelectableItem
import ua.acclorite.book_story.presentation.core.components.custom_drawer.CustomModalDrawerTitleItem import ua.acclorite.book_story.presentation.core.components.modal_drawer.ModalDrawerTitleItem
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent 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.history.data.HistoryViewModel
@ -33,12 +33,12 @@ fun ReaderChaptersDrawer() {
val onLibraryEvent = LibraryViewModel.getEvent() val onLibraryEvent = LibraryViewModel.getEvent()
val onHistoryEvent = HistoryViewModel.getEvent() val onHistoryEvent = HistoryViewModel.getEvent()
CustomModalDrawer( ModalDrawer(
show = state.value.showChaptersDrawer, show = state.value.showChaptersDrawer,
startIndex = state.value.currentChapter?.index ?: 0, startIndex = state.value.currentChapter?.index ?: 0,
onDismissRequest = { onEvent(ReaderEvent.OnShowHideChaptersDrawer(false)) }, onDismissRequest = { onEvent(ReaderEvent.OnShowHideChaptersDrawer(false)) },
header = { header = {
CustomModalDrawerTitleItem( ModalDrawerTitleItem(
title = stringResource(id = R.string.chapters) title = stringResource(id = R.string.chapters)
) )
} }
@ -48,7 +48,7 @@ fun ReaderChaptersDrawer() {
chapter.index == state.value.currentChapter?.index chapter.index == state.value.currentChapter?.index
} }
CustomModalDrawerSelectableItem( ModalDrawerSelectableItem(
selected = selected, selected = selected,
onClick = { onClick = {
onEvent( onEvent(

View file

@ -7,7 +7,7 @@ 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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.custom_dialog.CustomDialogWithContent import ua.acclorite.book_story.presentation.core.components.dialog.DialogWithContent
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
@ -22,7 +22,7 @@ fun ReaderUpdateDialog() {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val context = LocalContext.current val context = LocalContext.current
CustomDialogWithContent( DialogWithContent(
title = stringResource(id = R.string.update_book), title = stringResource(id = R.string.update_book),
imageVectorIcon = Icons.Rounded.Upgrade, imageVectorIcon = Icons.Rounded.Upgrade,
description = stringResource( description = stringResource(

View file

@ -30,7 +30,7 @@ import androidx.compose.ui.draw.clip
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.util.Direction import ua.acclorite.book_story.domain.util.Direction
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.util.calculateProgress import ua.acclorite.book_story.presentation.core.util.calculateProgress
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent import ua.acclorite.book_story.presentation.screens.history.data.HistoryEvent
@ -112,7 +112,7 @@ fun ReaderBottomBar() {
visible = arrowDirection == Direction.START, visible = arrowDirection == Direction.START,
startDirection = true startDirection = true
) { ) {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowBack, icon = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = R.string.checkpoint_back_content_desc, contentDescription = R.string.checkpoint_back_content_desc,
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
@ -143,7 +143,7 @@ fun ReaderBottomBar() {
visible = arrowDirection == Direction.END, visible = arrowDirection == Direction.END,
startDirection = false startDirection = false
) { ) {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Default.ArrowForward, icon = Icons.AutoMirrored.Default.ArrowForward,
contentDescription = R.string.checkpoint_forward_content_desc, contentDescription = R.string.checkpoint_forward_content_desc,
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),

View file

@ -36,8 +36,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.common.AnimatedVisibility
import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.common.IconButton
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.noRippleClickable import ua.acclorite.book_story.presentation.core.util.noRippleClickable
@ -91,7 +91,7 @@ fun ReaderTopBar() {
) { ) {
TopAppBar( TopAppBar(
navigationIcon = { navigationIcon = {
CustomIconButton( IconButton(
icon = Icons.AutoMirrored.Outlined.ArrowBack, icon = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = R.string.go_back_content_desc, contentDescription = R.string.go_back_content_desc,
disableOnClick = true disableOnClick = true
@ -167,7 +167,7 @@ fun ReaderTopBar() {
} }
}, },
actions = { actions = {
CustomAnimatedVisibility( AnimatedVisibility(
visible = state.value.checkingForUpdate || state.value.updateFound, visible = state.value.checkingForUpdate || state.value.updateFound,
enter = fadeIn(), enter = fadeIn(),
exit = shrinkHorizontally() + fadeOut() exit = shrinkHorizontally() + fadeOut()
@ -177,7 +177,7 @@ fun ReaderTopBar() {
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
if (state.value.updateFound) { if (state.value.updateFound) {
CustomIconButton( IconButton(
icon = Icons.Rounded.Upgrade, icon = Icons.Rounded.Upgrade,
contentDescription = R.string.update_text_content_desc, contentDescription = R.string.update_text_content_desc,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
@ -202,7 +202,7 @@ fun ReaderTopBar() {
} }
if (state.value.currentChapter != null) { if (state.value.currentChapter != null) {
CustomIconButton( IconButton(
icon = Icons.Rounded.Menu, icon = Icons.Rounded.Menu,
contentDescription = R.string.chapters_content_desc, contentDescription = R.string.chapters_content_desc,
disableOnClick = false, disableOnClick = false,
@ -214,7 +214,7 @@ fun ReaderTopBar() {
} }
} }
CustomIconButton( IconButton(
icon = Icons.Default.Settings, icon = Icons.Default.Settings,
contentDescription = R.string.open_reader_settings_content_desc, contentDescription = R.string.open_reader_settings_content_desc,
disableOnClick = false, disableOnClick = false,

View file

@ -19,8 +19,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.custom_bottom_sheet.CustomBottomSheet import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheet
import ua.acclorite.book_story.presentation.data.MainViewModel import ua.acclorite.book_story.presentation.data.MainViewModel
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
@ -73,7 +73,7 @@ fun ReaderSettingsBottomSheet() {
) )
} }
CustomBottomSheet( ModalBottomSheet(
hasFixedHeight = true, hasFixedHeight = true,
scrimColor = animatedScrimColor, scrimColor = animatedScrimColor,
modifier = Modifier modifier = Modifier
@ -89,7 +89,7 @@ fun ReaderSettingsBottomSheet() {
HorizontalPager(state = pagerState) { page -> HorizontalPager(state = pagerState) { page ->
when (page) { when (page) {
0 -> { 0 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
PaddingSubcategory( PaddingSubcategory(
titleColor = { MaterialTheme.colorScheme.onSurface }, titleColor = { MaterialTheme.colorScheme.onSurface },
topPadding = 22.dp, topPadding = 22.dp,
@ -115,7 +115,7 @@ fun ReaderSettingsBottomSheet() {
} }
1 -> { 1 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
FontSubcategory( FontSubcategory(
titleColor = { MaterialTheme.colorScheme.onSurface }, titleColor = { MaterialTheme.colorScheme.onSurface },
topPadding = 16.dp, topPadding = 16.dp,
@ -136,7 +136,7 @@ fun ReaderSettingsBottomSheet() {
} }
2 -> { 2 -> {
CustomLazyColumn(Modifier.fillMaxSize()) { LazyColumnWithScrollbar(Modifier.fillMaxSize()) {
ColorsSubcategory( ColorsSubcategory(
showTitle = false, showTitle = false,
showDivider = false, showDivider = false,

View file

@ -4,7 +4,7 @@ import androidx.compose.foundation.pager.PagerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
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.presentation.core.components.custom_bottom_sheet.CustomBottomSheetTabRow import ua.acclorite.book_story.presentation.core.components.modal_bottom_sheet.ModalBottomSheetTabRow
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel
@ -23,7 +23,7 @@ fun ReaderSettingsBottomSheetTabRow(pagerState: PagerState) {
stringResource(id = R.string.color_tab) stringResource(id = R.string.color_tab)
) )
CustomBottomSheetTabRow( ModalBottomSheetTabRow(
selectedTabIndex = pagerState.currentPage, selectedTabIndex = pagerState.currentPage,
tabs = tabItems tabs = tabItems
) { index -> ) { index ->

View file

@ -34,8 +34,8 @@ import ua.acclorite.book_story.domain.use_case.book.UpdateBook
import ua.acclorite.book_story.domain.use_case.history.GetLatestHistory import ua.acclorite.book_story.domain.use_case.history.GetLatestHistory
import ua.acclorite.book_story.domain.util.Resource import ua.acclorite.book_story.domain.util.Resource
import ua.acclorite.book_story.domain.util.UIText import ua.acclorite.book_story.domain.util.UIText
import ua.acclorite.book_story.domain.util.UIViewModel
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.core.util.UiViewModel
import ua.acclorite.book_story.presentation.core.util.coerceAndPreventNaN import ua.acclorite.book_story.presentation.core.util.coerceAndPreventNaN
import ua.acclorite.book_story.presentation.core.util.launchActivity import ua.acclorite.book_story.presentation.core.util.launchActivity
import javax.inject.Inject import javax.inject.Inject
@ -49,7 +49,7 @@ class ReaderViewModel @Inject constructor(
private val getLatestHistory: GetLatestHistory, private val getLatestHistory: GetLatestHistory,
private val getBookById: GetBookById, private val getBookById: GetBookById,
private val checkForTextUpdate: CheckForTextUpdate private val checkForTextUpdate: CheckForTextUpdate
) : UiViewModel<ReaderState, ReaderEvent>() { ) : UIViewModel<ReaderState, ReaderEvent>() {
companion object { companion object {
@Composable @Composable

View file

@ -24,9 +24,9 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
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 ua.acclorite.book_story.R import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.core.components.CustomLazyColumn import ua.acclorite.book_story.presentation.core.components.common.GoBackButton
import ua.acclorite.book_story.presentation.core.components.GoBackButton import ua.acclorite.book_story.presentation.core.components.common.LazyColumnWithScrollbar
import ua.acclorite.book_story.presentation.core.components.collapsibleUntilExitScrollBehaviorWithLazyListState import ua.acclorite.book_story.presentation.core.components.top_bar.collapsibleTopAppBarScrollBehavior
import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator import ua.acclorite.book_story.presentation.core.navigation.LocalNavigator
import ua.acclorite.book_story.presentation.core.navigation.Screen import ua.acclorite.book_story.presentation.core.navigation.Screen
import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryItem import ua.acclorite.book_story.presentation.screens.settings.components.SettingsCategoryItem
@ -40,12 +40,12 @@ fun SettingsScreenRoot() {
@Composable @Composable
private fun SettingsScreen() { private fun SettingsScreen() {
val onNavigate = LocalNavigator.current val onNavigate = LocalNavigator.current
val scrollState = TopAppBarDefaults.collapsibleUntilExitScrollBehaviorWithLazyListState() val (scrollBehavior, lazyListState) = TopAppBarDefaults.collapsibleTopAppBarScrollBehavior()
Scaffold( Scaffold(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.nestedScroll(scrollState.first.nestedScrollConnection) .nestedScroll(scrollBehavior.nestedScrollConnection)
.windowInsetsPadding(WindowInsets.navigationBars), .windowInsetsPadding(WindowInsets.navigationBars),
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
topBar = { topBar = {
@ -56,7 +56,7 @@ private fun SettingsScreen() {
navigationIcon = { navigationIcon = {
GoBackButton(onNavigate = onNavigate) GoBackButton(onNavigate = onNavigate)
}, },
scrollBehavior = scrollState.first, scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors( colors = TopAppBarDefaults.largeTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface, containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer
@ -64,11 +64,11 @@ private fun SettingsScreen() {
) )
} }
) { paddingValues -> ) { paddingValues ->
CustomLazyColumn( LazyColumnWithScrollbar(
Modifier Modifier
.fillMaxSize() .fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()), .padding(top = paddingValues.calculateTopPadding()),
state = scrollState.second state = lazyListState
) { ) {
item { item {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))

View file

@ -1,4 +1,4 @@
package ua.acclorite.book_story.presentation.core.components package ua.acclorite.book_story.presentation.screens.settings.components
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -15,10 +15,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
/** /**
* Category Title. Used to name a category. * Settings Category Title. Used to name a category.
*/ */
@Composable @Composable
fun CategoryTitle( fun SettingsCategoryTitle(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: String, title: String,
color: Color = MaterialTheme.colorScheme.onSurfaceVariant, color: Color = MaterialTheme.colorScheme.onSurfaceVariant,

View file

@ -13,7 +13,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.coerceAtLeast import androidx.compose.ui.unit.coerceAtLeast
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.core.components.CategoryTitle
/** /**
* Settings Subcategory. * Settings Subcategory.
@ -38,7 +37,7 @@ fun LazyListScope.SettingsSubcategory(
) { ) {
item { item {
if (showTitle) { if (showTitle) {
CategoryTitle( SettingsCategoryTitle(
title = title.invoke(), title = title.invoke(),
color = titleColor.invoke(), color = titleColor.invoke(),
modifier = Modifier modifier = Modifier

Some files were not shown because too many files have changed in this diff Show more