diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/core/components/AnimatedTopAppBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/core/components/AnimatedTopAppBar.kt index 7ac1a41d..0a1960de 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/core/components/AnimatedTopAppBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/core/components/AnimatedTopAppBar.kt @@ -23,6 +23,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.lerp +data class AnimatedTopAppBarData( + val contentVisibility: Boolean? = null, + val contentNavigationIcon: @Composable () -> Unit, + val contentTitle: @Composable () -> Unit, + val contentActions: @Composable RowScope.() -> Unit +) + /** * Animated top app bar. * Has up to 3 different top bars inside it. Follow [TopAppBar] for more info. @@ -31,9 +38,7 @@ import androidx.compose.ui.graphics.lerp * @param scrolledContainerColor Scrolled container color of the TopBar. * @param scrollBehavior [TopAppBarScrollBehavior]. * @param isTopBarScrolled Whether isScrolled state should be forced or not. - * @param content1Visibility Whether first top app bar should be shown. - * @param content2Visibility Whether second top app bar should be shown. - * @param content3Visibility Whether third top app bar should be shown. + * @param animatedTopBars Pass a list of all [AnimatedTopAppBarData] to show. * @param customContent Custom content below [TopAppBar]. */ @OptIn(ExperimentalMaterial3Api::class) @@ -45,21 +50,7 @@ fun AnimatedTopAppBar( scrollBehavior: TopAppBarScrollBehavior?, isTopBarScrolled: Boolean?, - content1Visibility: Boolean? = null, - content1NavigationIcon: @Composable () -> Unit, - content1Title: @Composable () -> Unit, - content1Actions: @Composable RowScope.() -> Unit, - - content2Visibility: Boolean? = null, - content2NavigationIcon: @Composable () -> Unit = {}, - content2Title: @Composable () -> Unit = {}, - content2Actions: @Composable RowScope.() -> Unit = {}, - - content3Visibility: Boolean? = null, - content3NavigationIcon: @Composable () -> Unit = {}, - content3Title: @Composable () -> Unit = {}, - content3Actions: @Composable RowScope.() -> Unit = {}, - + animatedTopBars: List, customContent: @Composable ColumnScope.() -> Unit = {} ) { val animatedContainerColor = lerp( @@ -79,59 +70,17 @@ fun AnimatedTopAppBar( .background(animatedContainerColor) ) { Box(modifier = Modifier.fillMaxWidth()) { - CustomAnimatedVisibility( - visible = content1Visibility ?: true, - enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)), - exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow)) - ) { - TopAppBar( - windowInsets = WindowInsets.statusBars, - navigationIcon = content1NavigationIcon, - title = content1Title, - actions = content1Actions, - scrollBehavior = scrollBehavior, - modifier = Modifier.fillMaxWidth(), - colors = TopAppBarDefaults.topAppBarColors( - containerColor = if (isTopBarScrolled != null) Color.Transparent - else containerColor, - scrolledContainerColor = scrolledContainerColor - ) - ) - } - - if (content2Visibility != null) { + animatedTopBars.forEach { data -> CustomAnimatedVisibility( - visible = content2Visibility, + visible = data.contentVisibility ?: false, enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)), exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow)) ) { TopAppBar( windowInsets = WindowInsets.statusBars, - navigationIcon = content2NavigationIcon, - title = content2Title, - actions = content2Actions, - scrollBehavior = scrollBehavior, - modifier = Modifier.fillMaxWidth(), - colors = TopAppBarDefaults.topAppBarColors( - containerColor = if (isTopBarScrolled != null) Color.Transparent - else containerColor, - scrolledContainerColor = scrolledContainerColor - ) - ) - } - } - - if (content3Visibility != null) { - CustomAnimatedVisibility( - visible = content3Visibility, - enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)), - exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow)) - ) { - TopAppBar( - windowInsets = WindowInsets.statusBars, - navigationIcon = content3NavigationIcon, - title = content3Title, - actions = content3Actions, + navigationIcon = data.contentNavigationIcon, + title = data.contentTitle, + actions = data.contentActions, scrollBehavior = scrollBehavior, modifier = Modifier.fillMaxWidth(), colors = TopAppBarDefaults.topAppBarColors( diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt index d3f8f4eb..a1fb655e 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/book_info/components/BookInfoTopBar.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextOverflow import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar +import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.GoBackButton @@ -59,120 +60,125 @@ fun BookInfoTopBar( scrollBehavior = null, isTopBarScrolled = listState.canScrollBackward, - content1NavigationIcon = { - if ( - state.value.editTitle || - state.value.editAuthor || - state.value.editDescription - ) { - CustomIconButton( - icon = Icons.AutoMirrored.Outlined.ArrowBack, - contentDescription = R.string.exit_editing_content_desc, - disableOnClick = true - ) { - if (state.value.editTitle) { - onEvent(BookInfoEvent.OnShowHideEditTitle) - } + animatedTopBars = listOf( + AnimatedTopAppBarData( + contentVisibility = true, + contentNavigationIcon = { + if ( + state.value.editTitle || + state.value.editAuthor || + state.value.editDescription + ) { + CustomIconButton( + icon = Icons.AutoMirrored.Outlined.ArrowBack, + contentDescription = R.string.exit_editing_content_desc, + disableOnClick = true + ) { + if (state.value.editTitle) { + onEvent(BookInfoEvent.OnShowHideEditTitle) + } - if (state.value.editAuthor) { - onEvent(BookInfoEvent.OnShowHideEditAuthor) - } + if (state.value.editAuthor) { + onEvent(BookInfoEvent.OnShowHideEditAuthor) + } - if (state.value.editDescription) { - onEvent(BookInfoEvent.OnShowHideEditDescription) + if (state.value.editDescription) { + onEvent(BookInfoEvent.OnShowHideEditDescription) + } + } + } else { + GoBackButton(onNavigate = onNavigate, enabled = !state.value.updating) { + onEvent(BookInfoEvent.OnCancelUpdate) + } } - } - } else { - GoBackButton(onNavigate = onNavigate, enabled = !state.value.updating) { - onEvent(BookInfoEvent.OnCancelUpdate) - } - } - }, - content1Title = { - DefaultTransition( - firstVisibleItemIndex > 0 && !state.value.editTitle - ) { - Text( - state.value.book.title, - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onSurface, - overflow = TextOverflow.Ellipsis, - maxLines = 1 - ) - } - }, - content1Actions = { - CustomIconButton( - icon = Icons.Outlined.Refresh, - contentDescription = R.string.refresh_book_content_desc, - disableOnClick = false, - enabled = !state.value.updating && !state.value.checkingForUpdate - ) { - onEvent( - BookInfoEvent.OnCheckForUpdate( - snackbarState, - context - ) - ) - } - - Box { - DefaultTransition( - visible = !state.value.editTitle && - !state.value.editAuthor && - !state.value.editDescription - ) { - BookInfoMoreDropDown(snackbarState = snackbarState) - } - CustomAnimatedVisibility( - visible = state.value.editTitle || - state.value.editAuthor || - state.value.editDescription, - enter = Transitions.DefaultTransitionIn, - exit = fadeOut(tween(200)) - ) { + }, + contentTitle = { + DefaultTransition( + firstVisibleItemIndex > 0 && !state.value.editTitle + ) { + Text( + state.value.book.title, + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onSurface, + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + } + }, + contentActions = { CustomIconButton( - icon = Icons.Outlined.Done, - contentDescription = R.string.apply_changes_content_desc, - disableOnClick = true, - enabled = !state.value.updating && - (state.value.titleValue.isNotBlank() && - state.value.titleValue.trim() != - state.value.book.title.trim()) || - - (state.value.authorValue.isNotBlank() && - state.value.authorValue.trim() != - state.value.book.author.getAsString()?.trim()) || - - (state.value.descriptionValue.isNotBlank() && - state.value.descriptionValue.trim() != - state.value.book.description?.trim()), - - color = if ((state.value.titleValue.isNotBlank() && - state.value.titleValue.trim() != - state.value.book.title.trim()) || - - (state.value.authorValue.isNotBlank() && - state.value.authorValue.trim() != - state.value.book.author.getAsString()?.trim()) || - - (state.value.descriptionValue.isNotBlank() && - state.value.descriptionValue.trim() != - state.value.book.description?.trim()) - ) MaterialTheme.colorScheme.onSurface - else MaterialTheme.colorScheme.onSurfaceVariant + icon = Icons.Outlined.Refresh, + contentDescription = R.string.refresh_book_content_desc, + disableOnClick = false, + enabled = !state.value.updating && !state.value.checkingForUpdate ) { onEvent( - BookInfoEvent.OnUpdateData( - refreshList = { - onLibraryEvent(LibraryEvent.OnUpdateBook(it)) - onHistoryEvent(HistoryEvent.OnUpdateBook(it)) - } + BookInfoEvent.OnCheckForUpdate( + snackbarState, + context ) ) } + + Box { + DefaultTransition( + visible = !state.value.editTitle && + !state.value.editAuthor && + !state.value.editDescription + ) { + BookInfoMoreDropDown(snackbarState = snackbarState) + } + CustomAnimatedVisibility( + visible = state.value.editTitle || + state.value.editAuthor || + state.value.editDescription, + enter = Transitions.DefaultTransitionIn, + exit = fadeOut(tween(200)) + ) { + CustomIconButton( + icon = Icons.Outlined.Done, + contentDescription = R.string.apply_changes_content_desc, + disableOnClick = true, + enabled = !state.value.updating && + (state.value.titleValue.isNotBlank() && + state.value.titleValue.trim() != + state.value.book.title.trim()) || + + (state.value.authorValue.isNotBlank() && + state.value.authorValue.trim() != + state.value.book.author.getAsString()?.trim()) || + + (state.value.descriptionValue.isNotBlank() && + state.value.descriptionValue.trim() != + state.value.book.description?.trim()), + + color = if ((state.value.titleValue.isNotBlank() && + state.value.titleValue.trim() != + state.value.book.title.trim()) || + + (state.value.authorValue.isNotBlank() && + state.value.authorValue.trim() != + state.value.book.author.getAsString()?.trim()) || + + (state.value.descriptionValue.isNotBlank() && + state.value.descriptionValue.trim() != + state.value.book.description?.trim()) + ) MaterialTheme.colorScheme.onSurface + else MaterialTheme.colorScheme.onSurfaceVariant + ) { + onEvent( + BookInfoEvent.OnUpdateData( + refreshList = { + onLibraryEvent(LibraryEvent.OnUpdateBook(it)) + onHistoryEvent(HistoryEvent.OnUpdateBook(it)) + } + ) + ) + } + } + } } - } - } + ) + ) ) } \ No newline at end of file diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt index b6041e98..33047ad6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/browse/components/top_bar/BrowseTopBar.kt @@ -1,14 +1,6 @@ package ua.acclorite.book_story.presentation.screens.browse.components.top_bar import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween -import androidx.compose.animation.expandHorizontally -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.shrinkHorizontally -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.foundation.layout.Box import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Check @@ -25,7 +17,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -35,7 +26,7 @@ import androidx.compose.ui.text.style.TextOverflow import ua.acclorite.book_story.R 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.CustomAnimatedVisibility +import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.LocalBrowseViewModel @@ -44,7 +35,6 @@ import ua.acclorite.book_story.presentation.core.components.MoreDropDown import ua.acclorite.book_story.presentation.screens.browse.data.BrowseEvent import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseFilesStructure import ua.acclorite.book_story.presentation.screens.settings.nested.browse.data.BrowseLayout -import ua.acclorite.book_story.presentation.ui.FadeTransitionPreservingSpace /** * Browse Top Bar. @@ -88,157 +78,173 @@ fun BrowseTopBar(filteredFiles: List) { AnimatedTopAppBar( scrollBehavior = null, - isTopBarScrolled = state.value.hasSelectedItems || - isScrolled.value || - inNestedDirectory.value, + isTopBarScrolled = isScrolled.value || inNestedDirectory.value, - content1Visibility = !state.value.hasSelectedItems && !state.value.showSearch, - content1NavigationIcon = { - CustomAnimatedVisibility( - visible = inNestedDirectory.value, - enter = expandHorizontally(tween(200)) - + slideInHorizontally(tween(200)) - + fadeIn(tween(250)), - exit = shrinkHorizontally(tween(150)) - + slideOutHorizontally(tween(150)) - + fadeOut(tween(200)) - ) { - CustomIconButton( - icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = R.string.go_back_content_desc, - disableOnClick = false, - enabled = inNestedDirectory.value - ) { - onEvent(BrowseEvent.OnGoBackDirectory) - } - } - }, - content1Title = { - Box(contentAlignment = Alignment.CenterStart) { - FadeTransitionPreservingSpace( - visible = inNestedDirectory.value, - animationSpec = tween(200) - ) { - Text( - selectedDirectoryName.value, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - FadeTransitionPreservingSpace( - visible = !inNestedDirectory.value, - animationSpec = tween(200) - ) { + animatedTopBars = listOf( + AnimatedTopAppBarData( + contentVisibility = !state.value.hasSelectedItems && + !state.value.showSearch && + !inNestedDirectory.value, + contentNavigationIcon = {}, + contentTitle = { Text( stringResource(id = R.string.browse_screen), maxLines = 1, overflow = TextOverflow.Ellipsis ) + }, + contentActions = { + CustomIconButton( + icon = Icons.Default.Search, + contentDescription = R.string.search_content_desc, + disableOnClick = true + ) { + onEvent(BrowseEvent.OnSearchShowHide) + } + CustomIconButton( + icon = Icons.Default.FilterList, + contentDescription = R.string.filter_content_desc, + disableOnClick = false, + color = animateColorAsState( + if (mainState.value.browseIncludedFilterItems.isNotEmpty()) { + MaterialTheme.colorScheme.primary + } else LocalContentColor.current, + label = "" + ).value, + enabled = !state.value.showFilterBottomSheet + ) { + onEvent(BrowseEvent.OnShowHideFilterBottomSheet) + } + MoreDropDown() } - } - }, - content1Actions = { - CustomIconButton( - icon = Icons.Default.Search, - contentDescription = R.string.search_content_desc, - disableOnClick = true - ) { - onEvent(BrowseEvent.OnSearchShowHide) - } - CustomIconButton( - icon = Icons.Default.FilterList, - contentDescription = R.string.filter_content_desc, - disableOnClick = false, - color = animateColorAsState( - if (mainState.value.browseIncludedFilterItems.isNotEmpty()) { - MaterialTheme.colorScheme.primary - } else LocalContentColor.current, - label = "" - ).value, - enabled = !state.value.showFilterBottomSheet - ) { - onEvent(BrowseEvent.OnShowHideFilterBottomSheet) - } - MoreDropDown() - }, + ), - content2Visibility = state.value.hasSelectedItems, - content2NavigationIcon = { - CustomIconButton( - icon = Icons.Default.Clear, - contentDescription = R.string.clear_selected_items_content_desc, - disableOnClick = true - ) { - onEvent(BrowseEvent.OnClearSelectedFiles) - } - }, - content2Title = { - Text( - stringResource( - id = R.string.selected_items_count_query, - state.value.selectedItemsCount.coerceAtLeast(1) - ), - overflow = TextOverflow.Ellipsis, - maxLines = 1 - ) - }, - content2Actions = { - CustomIconButton( - icon = Icons.Default.SelectAll, - contentDescription = R.string.select_all_files_content_desc, - disableOnClick = false, - ) { - onEvent( - BrowseEvent.OnSelectFiles( - includedFileFormats = mainState.value.browseIncludedFilterItems, - files = filteredFiles + AnimatedTopAppBarData( + contentVisibility = inNestedDirectory.value, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = R.string.go_back_content_desc, + disableOnClick = false, + enabled = inNestedDirectory.value + ) { + onEvent(BrowseEvent.OnGoBackDirectory) + } + }, + contentTitle = { + Text( + selectedDirectoryName.value, + maxLines = 1, + overflow = TextOverflow.Ellipsis ) - ) - } - CustomIconButton( - icon = Icons.Default.Check, - contentDescription = R.string.add_files_content_desc, - disableOnClick = false, - enabled = !state.value.showAddingDialog - ) { - onEvent(BrowseEvent.OnAddingDialogRequest) - } - }, + }, + contentActions = { + CustomIconButton( + icon = Icons.Default.Search, + contentDescription = R.string.search_content_desc, + disableOnClick = true + ) { + onEvent(BrowseEvent.OnSearchShowHide) + } + CustomIconButton( + icon = Icons.Default.FilterList, + contentDescription = R.string.filter_content_desc, + disableOnClick = false, + color = animateColorAsState( + if (mainState.value.browseIncludedFilterItems.isNotEmpty()) { + MaterialTheme.colorScheme.primary + } else LocalContentColor.current, + label = "" + ).value, + enabled = !state.value.showFilterBottomSheet + ) { + onEvent(BrowseEvent.OnShowHideFilterBottomSheet) + } + MoreDropDown() + } + ), - content3Visibility = state.value.showSearch && !state.value.hasSelectedItems, - content3NavigationIcon = { - CustomIconButton( - icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = R.string.exit_search_content_desc, - disableOnClick = true - ) { - onEvent(BrowseEvent.OnSearchShowHide) - } - }, - content3Title = { - CustomSearchTextField( - modifier = Modifier - .focusRequester(focusRequester) - .onGloballyPositioned { - onEvent(BrowseEvent.OnRequestFocus(focusRequester)) - }, - query = state.value.searchQuery, - onQueryChange = { - onEvent(BrowseEvent.OnSearchQueryChange(it)) + AnimatedTopAppBarData( + contentVisibility = state.value.hasSelectedItems, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.Default.Clear, + contentDescription = R.string.clear_selected_items_content_desc, + disableOnClick = true + ) { + onEvent(BrowseEvent.OnClearSelectedFiles) + } }, - onSearch = { - onEvent(BrowseEvent.OnSearch) + contentTitle = { + Text( + stringResource( + id = R.string.selected_items_count_query, + state.value.selectedItemsCount.coerceAtLeast(1) + ), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) }, - placeholder = stringResource( - id = R.string.search_query, - stringResource(id = R.string.files) - ) + contentActions = { + CustomIconButton( + icon = Icons.Default.SelectAll, + contentDescription = R.string.select_all_files_content_desc, + disableOnClick = false, + ) { + onEvent( + BrowseEvent.OnSelectFiles( + includedFileFormats = mainState.value.browseIncludedFilterItems, + files = filteredFiles + ) + ) + } + CustomIconButton( + icon = Icons.Default.Check, + contentDescription = R.string.add_files_content_desc, + disableOnClick = false, + enabled = !state.value.showAddingDialog + ) { + onEvent(BrowseEvent.OnAddingDialogRequest) + } + } + ), + + AnimatedTopAppBarData( + contentVisibility = state.value.showSearch && !state.value.hasSelectedItems, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = R.string.exit_search_content_desc, + disableOnClick = true + ) { + onEvent(BrowseEvent.OnSearchShowHide) + } + }, + contentTitle = { + CustomSearchTextField( + modifier = Modifier + .focusRequester(focusRequester) + .onGloballyPositioned { + onEvent(BrowseEvent.OnRequestFocus(focusRequester)) + }, + query = state.value.searchQuery, + onQueryChange = { + onEvent(BrowseEvent.OnSearchQueryChange(it)) + }, + onSearch = { + onEvent(BrowseEvent.OnSearch) + }, + placeholder = stringResource( + id = R.string.search_query, + stringResource(id = R.string.files) + ) + ) + }, + contentActions = { + MoreDropDown() + } ) - }, - content3Actions = { - MoreDropDown() - }, - + ), customContent = { BrowseTopBarDirectoryPath() } diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt index 23ec058e..9f7c2680 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/history/HistoryScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar +import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.CategoryTitle import ua.acclorite.book_story.presentation.core.components.CustomAnimatedVisibility import ua.acclorite.book_story.presentation.core.components.CustomIconButton @@ -101,69 +102,72 @@ private fun HistoryScreen() { scrollBehavior = null, isTopBarScrolled = state.value.listState.canScrollBackward, - content1Visibility = !state.value.showSearch, - content1NavigationIcon = {}, - content1Title = { - Text( - stringResource(id = R.string.history_screen) - ) - }, - content1Actions = { - CustomIconButton( - icon = Icons.Default.Search, - contentDescription = R.string.search_content_desc, - disableOnClick = true, - ) { - onEvent(HistoryEvent.OnSearchShowHide) - } - CustomIconButton( - icon = Icons.Outlined.DeleteSweep, - contentDescription = R.string.delete_whole_history_content_desc, - disableOnClick = false, - enabled = !state.value.isLoading - && !state.value.isRefreshing - && state.value.history.isNotEmpty() - && !state.value.showDeleteWholeHistoryDialog - ) { - onEvent(HistoryEvent.OnShowHideDeleteWholeHistoryDialog) - } - MoreDropDown() - }, + animatedTopBars = listOf( + AnimatedTopAppBarData( + contentVisibility = !state.value.showSearch, + contentNavigationIcon = {}, + contentTitle = { + Text(stringResource(id = R.string.history_screen)) + }, + contentActions = { + CustomIconButton( + icon = Icons.Default.Search, + contentDescription = R.string.search_content_desc, + disableOnClick = true, + ) { + onEvent(HistoryEvent.OnSearchShowHide) + } + CustomIconButton( + icon = Icons.Outlined.DeleteSweep, + contentDescription = R.string.delete_whole_history_content_desc, + disableOnClick = false, + enabled = !state.value.isLoading + && !state.value.isRefreshing + && state.value.history.isNotEmpty() + && !state.value.showDeleteWholeHistoryDialog + ) { + onEvent(HistoryEvent.OnShowHideDeleteWholeHistoryDialog) + } + MoreDropDown() + } + ), - content2Visibility = state.value.showSearch, - content2NavigationIcon = { - CustomIconButton( - icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = R.string.exit_search_content_desc, - disableOnClick = true - ) { - onEvent(HistoryEvent.OnSearchShowHide) - } - }, - content2Title = { - CustomSearchTextField( - modifier = Modifier - .focusRequester(focusRequester) - .onGloballyPositioned { - onEvent(HistoryEvent.OnRequestFocus(focusRequester)) - }, - query = state.value.searchQuery, - onQueryChange = { - onEvent(HistoryEvent.OnSearchQueryChange(it)) + AnimatedTopAppBarData( + contentVisibility = state.value.showSearch, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = R.string.exit_search_content_desc, + disableOnClick = true + ) { + onEvent(HistoryEvent.OnSearchShowHide) + } }, - onSearch = { - onEvent(HistoryEvent.OnSearch) + contentTitle = { + CustomSearchTextField( + modifier = Modifier + .focusRequester(focusRequester) + .onGloballyPositioned { + onEvent(HistoryEvent.OnRequestFocus(focusRequester)) + }, + query = state.value.searchQuery, + onQueryChange = { + onEvent(HistoryEvent.OnSearchQueryChange(it)) + }, + onSearch = { + onEvent(HistoryEvent.OnSearch) + }, + placeholder = stringResource( + id = R.string.search_query, + stringResource(id = R.string.history) + ) + ) + }, + contentActions = { + MoreDropDown() }, - placeholder = stringResource( - id = R.string.search_query, - stringResource(id = R.string.history) - ) ) - }, - content2Actions = { - MoreDropDown() - }, - content3Visibility = false + ) ) }, bottomBar = { diff --git a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt index d0838038..0a6563f6 100644 --- a/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt +++ b/app/src/main/java/ua/acclorite/book_story/presentation/screens/library/components/LibraryTopBar.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import ua.acclorite.book_story.R import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBar +import ua.acclorite.book_story.presentation.core.components.AnimatedTopAppBarData import ua.acclorite.book_story.presentation.core.components.CustomIconButton import ua.acclorite.book_story.presentation.core.components.CustomSearchTextField import ua.acclorite.book_story.presentation.core.components.LocalLibraryViewModel @@ -55,115 +56,123 @@ fun LibraryTopBar(pagerState: PagerState) { scrollBehavior = null, isTopBarScrolled = state.value.hasSelectedItems, - content1Visibility = !state.value.hasSelectedItems && !state.value.showSearch, - content1NavigationIcon = {}, - content1Title = { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(stringResource(id = R.string.library_screen)) - Spacer(modifier = Modifier.width(6.dp)) - Text( - text = state.value.books.size.toString(), - modifier = Modifier - .background( - MaterialTheme.colorScheme.surfaceContainer, - RoundedCornerShape(14.dp) + animatedTopBars = listOf( + AnimatedTopAppBarData( + contentVisibility = !state.value.hasSelectedItems && !state.value.showSearch, + contentNavigationIcon = {}, + contentTitle = { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(stringResource(id = R.string.library_screen)) + Spacer(modifier = Modifier.width(6.dp)) + Text( + text = state.value.books.size.toString(), + modifier = Modifier + .background( + MaterialTheme.colorScheme.surfaceContainer, + RoundedCornerShape(14.dp) + ) + .padding(horizontal = 8.dp, vertical = 3.dp), + color = MaterialTheme.colorScheme.onSurfaceVariant, + fontSize = 16.sp ) - .padding(horizontal = 8.dp, vertical = 3.dp), - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontSize = 16.sp - ) - } - }, - content1Actions = { - CustomIconButton( - icon = Icons.Default.Search, - contentDescription = R.string.search_content_desc, - disableOnClick = true, - ) { - onEvent(LibraryEvent.OnSearchShowHide) - } - MoreDropDown() - }, - - content2Visibility = state.value.hasSelectedItems, - content2NavigationIcon = { - CustomIconButton( - icon = Icons.Default.Clear, - contentDescription = R.string.clear_selected_items_content_desc, - disableOnClick = true - ) { - onEvent(LibraryEvent.OnClearSelectedBooks) - } - }, - content2Title = { - Text( - stringResource( - id = R.string.selected_items_count_query, - state.value.selectedItemsCount.coerceAtLeast(1) - ), - overflow = TextOverflow.Ellipsis, - maxLines = 1 - ) - }, - content2Actions = { - CustomIconButton( - icon = Icons.AutoMirrored.Outlined.DriveFileMove, - contentDescription = R.string.move_books_content_desc, - enabled = !state.value.isLoading - && !state.value.isRefreshing - && !state.value.showMoveDialog, - disableOnClick = false, - - ) { - onEvent(LibraryEvent.OnShowHideMoveDialog) - } - CustomIconButton( - icon = Icons.Outlined.Delete, - contentDescription = R.string.delete_books_content_desc, - enabled = !state.value.isLoading - && !state.value.isRefreshing - && !state.value.showDeleteDialog, - disableOnClick = false - ) { - onEvent(LibraryEvent.OnShowHideDeleteDialog) - } - }, - - content3Visibility = state.value.showSearch && !state.value.hasSelectedItems, - content3NavigationIcon = { - CustomIconButton( - icon = Icons.AutoMirrored.Default.ArrowBack, - contentDescription = R.string.exit_search_content_desc, - disableOnClick = true - ) { - onEvent( - LibraryEvent.OnSearchShowHide - ) - } - }, - content3Title = { - CustomSearchTextField( - modifier = Modifier - .focusRequester(focusRequester) - .onGloballyPositioned { - onEvent(LibraryEvent.OnRequestFocus(focusRequester)) - }, - query = state.value.searchQuery, - onQueryChange = { - onEvent(LibraryEvent.OnSearchQueryChange(it)) + } }, - onSearch = { - onEvent(LibraryEvent.OnSearch) + contentActions = { + CustomIconButton( + icon = Icons.Default.Search, + contentDescription = R.string.search_content_desc, + disableOnClick = true, + ) { + onEvent(LibraryEvent.OnSearchShowHide) + } + MoreDropDown() + } + ), + + AnimatedTopAppBarData( + contentVisibility = state.value.hasSelectedItems, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.Default.Clear, + contentDescription = R.string.clear_selected_items_content_desc, + disableOnClick = true + ) { + onEvent(LibraryEvent.OnClearSelectedBooks) + } + }, + contentTitle = { + Text( + stringResource( + id = R.string.selected_items_count_query, + state.value.selectedItemsCount.coerceAtLeast(1) + ), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + }, + contentActions = { + CustomIconButton( + icon = Icons.AutoMirrored.Outlined.DriveFileMove, + contentDescription = R.string.move_books_content_desc, + enabled = !state.value.isLoading + && !state.value.isRefreshing + && !state.value.showMoveDialog, + disableOnClick = false, + + ) { + onEvent(LibraryEvent.OnShowHideMoveDialog) + } + CustomIconButton( + icon = Icons.Outlined.Delete, + contentDescription = R.string.delete_books_content_desc, + enabled = !state.value.isLoading + && !state.value.isRefreshing + && !state.value.showDeleteDialog, + disableOnClick = false + ) { + onEvent(LibraryEvent.OnShowHideDeleteDialog) + } + } + ), + + AnimatedTopAppBarData( + contentVisibility = state.value.showSearch && !state.value.hasSelectedItems, + contentNavigationIcon = { + CustomIconButton( + icon = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = R.string.exit_search_content_desc, + disableOnClick = true + ) { + onEvent( + LibraryEvent.OnSearchShowHide + ) + } + }, + contentTitle = { + CustomSearchTextField( + modifier = Modifier + .focusRequester(focusRequester) + .onGloballyPositioned { + onEvent(LibraryEvent.OnRequestFocus(focusRequester)) + }, + query = state.value.searchQuery, + onQueryChange = { + onEvent(LibraryEvent.OnSearchQueryChange(it)) + }, + onSearch = { + onEvent(LibraryEvent.OnSearch) + }, + placeholder = stringResource( + id = R.string.search_query, + stringResource(id = R.string.books) + ) + ) + }, + contentActions = { + MoreDropDown() }, - placeholder = stringResource( - id = R.string.search_query, - stringResource(id = R.string.books) - ) ) - }, - content3Actions = { - MoreDropDown() - }, + ), customContent = { LibraryTabRow( onEvent = onEvent,