From bb4109e3135186f9a3a290c19dc6093519bde250 Mon Sep 17 00:00:00 2001 From: pabloscloud Date: Sat, 25 Nov 2023 10:50:05 +0000 Subject: [PATCH] v.0.12.2 - animates start/stop buttons - improves calendar for tablets --- app/build.gradle.kts | 4 +- app/release/output-metadata.json | 4 +- .../cloud/pablos/overload/ui/OverloadApp.kt | 33 ++++- .../OverloadNavigationComponents.kt | 5 +- .../overload/ui/tabs/calendar/CalendarTab.kt | 129 ++++++++++++++---- .../pablos/overload/ui/tabs/home/HomeTab.kt | 30 ++-- .../overload/ui/tabs/home/HomeTabFab.kt | 9 +- .../overload/ui/utils/WindowStateUtils.kt | 7 + .../pablos/overload/ui/views/YearView.kt | 5 +- .../metadata/android/en-US/changelogs/122.txt | 2 + gradle/libs.versions.toml | 12 +- 11 files changed, 179 insertions(+), 61 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/122.txt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 64c62eb..83aa1a6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "cloud.pablos.overload" minSdk = 26 targetSdk = 34 - versionCode = 121 - versionName = "0.12.1" + versionCode = 122 + versionName = "0.12.2" vectorDrawables.useSupportLibrary = true testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index f9725ef..3b4f371 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 121, - "versionName": "0.12.1", + "versionCode": 122, + "versionName": "0.12.2", "outputFile": "app-release.apk" } ], diff --git a/app/src/main/java/cloud/pablos/overload/ui/OverloadApp.kt b/app/src/main/java/cloud/pablos/overload/ui/OverloadApp.kt index 0931717..cac4d89 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/OverloadApp.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/OverloadApp.kt @@ -1,6 +1,7 @@ package cloud.pablos.overload.ui import android.os.Build +import android.util.Log import androidx.annotation.RequiresApi import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background @@ -48,6 +49,7 @@ import cloud.pablos.overload.ui.tabs.calendar.CalendarTab import cloud.pablos.overload.ui.tabs.configurations.ConfigurationsTab import cloud.pablos.overload.ui.tabs.home.HomeTab import cloud.pablos.overload.ui.utils.DevicePosture +import cloud.pablos.overload.ui.utils.OverloadContentType import cloud.pablos.overload.ui.utils.OverloadNavigationContentPosition import cloud.pablos.overload.ui.utils.OverloadNavigationType import cloud.pablos.overload.ui.utils.isBookPosture @@ -66,6 +68,7 @@ fun OverloadApp( onEvent: (ItemEvent) -> Unit, ) { val navigationType: OverloadNavigationType + val contentType: OverloadContentType val foldingFeature = displayFeatures.filterIsInstance().firstOrNull() @@ -82,9 +85,17 @@ fun OverloadApp( when (windowSize.widthSizeClass) { WindowWidthSizeClass.Compact -> { navigationType = OverloadNavigationType.BOTTOM_NAVIGATION + contentType = OverloadContentType.SINGLE_PANE } WindowWidthSizeClass.Medium -> { navigationType = OverloadNavigationType.NAVIGATION_RAIL + contentType = if (foldingDevicePosture != DevicePosture.NormalPosture) { + OverloadContentType.DUAL_PANE + } else { + OverloadContentType.SINGLE_PANE + } + + Log.d("ol_df", displayFeatures.toString()) } WindowWidthSizeClass.Expanded -> { navigationType = if (foldingDevicePosture is DevicePosture.BookPosture) { @@ -92,9 +103,11 @@ fun OverloadApp( } else { OverloadNavigationType.PERMANENT_NAVIGATION_DRAWER } + contentType = OverloadContentType.DUAL_PANE } else -> { navigationType = OverloadNavigationType.BOTTOM_NAVIGATION + contentType = OverloadContentType.SINGLE_PANE } } @@ -114,6 +127,7 @@ fun OverloadApp( OverloadNavigationWrapper( navigationType = navigationType, + contentType = contentType, navigationContentPosition = navigationContentPosition, state = state, onEvent = onEvent, @@ -124,6 +138,7 @@ fun OverloadApp( @Composable private fun OverloadNavigationWrapper( navigationType: OverloadNavigationType, + contentType: OverloadContentType, navigationContentPosition: OverloadNavigationContentPosition, state: ItemState, onEvent: (ItemEvent) -> Unit, @@ -152,6 +167,7 @@ private fun OverloadNavigationWrapper( }) { OverloadAppContent( navigationType = navigationType, + contentType = contentType, navigationContentPosition = navigationContentPosition, navController = navController, selectedDestination = selectedDestination, @@ -165,6 +181,7 @@ private fun OverloadNavigationWrapper( OverloadNavigationType.BOTTOM_NAVIGATION -> { OverloadAppContent( navigationType = navigationType, + contentType = contentType, navigationContentPosition = navigationContentPosition, navController = navController, selectedDestination = selectedDestination, @@ -198,6 +215,7 @@ private fun OverloadNavigationWrapper( ) { OverloadAppContent( navigationType = navigationType, + contentType = contentType, navigationContentPosition = navigationContentPosition, navController = navController, selectedDestination = selectedDestination, @@ -220,6 +238,7 @@ private fun OverloadNavigationWrapper( fun OverloadAppContent( modifier: Modifier = Modifier, navigationType: OverloadNavigationType, + contentType: OverloadContentType, navigationContentPosition: OverloadNavigationContentPosition, navController: NavHostController, selectedDestination: String, @@ -261,6 +280,7 @@ fun OverloadAppContent( ) { OverloadNavHost( navigationType = navigationType, + contentType = contentType, navController = navController, state = state, onEvent = onEvent, @@ -315,6 +335,7 @@ fun OverloadAppContent( @Composable private fun OverloadNavHost( navigationType: OverloadNavigationType, + contentType: OverloadContentType, navController: NavHostController, modifier: Modifier = Modifier, state: ItemState, @@ -326,10 +347,18 @@ private fun OverloadNavHost( startDestination = OverloadRoute.HOME, ) { composable(OverloadRoute.HOME) { - HomeTab(navigationType = navigationType, state = state, onEvent = onEvent) + HomeTab( + navigationType = navigationType, + state = state, + onEvent = onEvent, + ) } composable(OverloadRoute.CALENDAR) { - CalendarTab(state = state, onEvent = onEvent) + CalendarTab( + contentType = contentType, + state = state, + onEvent = onEvent, + ) } composable(OverloadRoute.CONFIGURATIONS) { ConfigurationsTab(state = state) diff --git a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationComponents.kt b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationComponents.kt index 0aefd7f..4aa5dda 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationComponents.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/navigation/OverloadNavigationComponents.kt @@ -2,6 +2,7 @@ package cloud.pablos.overload.ui.navigation import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -189,7 +190,7 @@ fun PermanentNavigationDrawerContent( modifier = Modifier.padding(16.dp), ) - if (state.selectedDayCalendar == LocalDate.now().toString()) { + AnimatedVisibility(visible = state.selectedDayCalendar == LocalDate.now().toString()) { OverloadNavigationFab(state = state, onEvent = onEvent) } } @@ -276,7 +277,7 @@ fun ModalNavigationDrawerContent( } } - if (state.selectedDayCalendar == LocalDate.now().toString()) { + AnimatedVisibility(visible = state.selectedDayCalendar == LocalDate.now().toString()) { OverloadNavigationFab(state = state, onEvent = onEvent) } } diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/calendar/CalendarTab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/calendar/CalendarTab.kt index 8f9566f..7863e88 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/calendar/CalendarTab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/calendar/CalendarTab.kt @@ -2,6 +2,7 @@ package cloud.pablos.overload.ui.tabs.calendar import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.detectVerticalDragGestures import androidx.compose.foundation.layout.Arrangement @@ -38,9 +39,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState +import cloud.pablos.overload.ui.utils.OverloadContentType import cloud.pablos.overload.ui.views.DayView import cloud.pablos.overload.ui.views.TextView import cloud.pablos.overload.ui.views.YearView +import cloud.pablos.overload.ui.views.getFormattedDate import cloud.pablos.overload.ui.views.getLocalDate import cloud.pablos.overload.ui.views.parseToLocalDateTime import kotlinx.coroutines.launch @@ -52,6 +55,7 @@ import java.time.temporal.ChronoUnit @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun CalendarTab( + contentType: OverloadContentType, state: ItemState, onEvent: (ItemEvent) -> Unit, ) { @@ -118,39 +122,91 @@ fun CalendarTab( ) { paddingValues -> Box(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.padding(paddingValues)) { - Surface( - tonalElevation = NavigationBarDefaults.Elevation, - color = MaterialTheme.colorScheme.background, - ) { - WeekDaysHeader() + AnimatedVisibility(visible = contentType == OverloadContentType.DUAL_PANE) { + Row(modifier = Modifier.fillMaxSize()) { + Box( + modifier = Modifier.weight(1f), + ) { + Column { + Surface( + tonalElevation = NavigationBarDefaults.Elevation, + color = MaterialTheme.colorScheme.background, + ) { + WeekDaysHeader() + } + + YearView( + state = state, + onEvent = onEvent, + year = state.selectedYearCalendar, + bottomPadding = 0.dp, + ) + } + } + + Box( + modifier = Modifier.weight(1f), + ) { + HorizontalPager( + state = pagerState, + ) { + Column { + Surface( + tonalElevation = NavigationBarDefaults.Elevation, + color = MaterialTheme.colorScheme.background, + ) { + DateHeader(selectedDay) + } + + DayView( + state = state, + onEvent = onEvent, + date = selectedDay, + isEditable = false, + ) + } + } + } + } } - BottomSheetScaffold( - scaffoldState = sheetState, - sheetContent = { - HorizontalPager( - state = pagerState, + AnimatedVisibility(visible = contentType == OverloadContentType.SINGLE_PANE) { + Column { + Surface( + tonalElevation = NavigationBarDefaults.Elevation, + color = MaterialTheme.colorScheme.background, ) { - DayView( + WeekDaysHeader() + } + + BottomSheetScaffold( + scaffoldState = sheetState, + sheetContent = { + HorizontalPager( + state = pagerState, + ) { + DayView( + state = state, + onEvent = onEvent, + date = selectedDay, + isEditable = false, + ) + } + }, + ) { innerPadding -> + YearView( state = state, onEvent = onEvent, - date = selectedDay, - isEditable = false, + year = state.selectedYearCalendar, + bottomPadding = innerPadding.calculateBottomPadding(), ) - } - }, - ) { innerPadding -> - YearView( - state = state, - onEvent = onEvent, - year = state.selectedYearCalendar, - bottomPadding = innerPadding.calculateBottomPadding(), - ) - - Modifier.pointerInput(Unit) { - detectVerticalDragGestures { _, dragAmount -> - val maxOffset = 64.dp.toPx() - - sheetOffset = (sheetOffset + dragAmount).coerceIn(0f, maxOffset) + + Modifier.pointerInput(Unit) { + detectVerticalDragGestures { _, dragAmount -> + val maxOffset = 64.dp.toPx() + + sheetOffset = (sheetOffset + dragAmount).coerceIn(0f, maxOffset) + } + } } } } @@ -192,3 +248,20 @@ fun DayOfWeekHeaderCell(text: String) { ) } } + +@Composable +fun DateHeader(date: LocalDate) { + val text = getFormattedDate(date, true) + Box( + modifier = Modifier + .padding(4.dp) + .height(36.dp) + .fillMaxWidth(), + ) { + TextView( + text = text, + fontSize = 14.sp, + modifier = Modifier.padding(6.dp), + ) + } +} diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt index c4d2449..ffbb1bd 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTab.kt @@ -1,8 +1,11 @@ package cloud.pablos.overload.ui.tabs.home +import android.annotation.SuppressLint import android.os.Build import androidx.annotation.RequiresApi -import androidx.compose.animation.animateContentSize +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,19 +21,21 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Tab import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import cloud.pablos.overload.data.item.ItemEvent import cloud.pablos.overload.data.item.ItemState +import cloud.pablos.overload.ui.utils.OverloadContentType import cloud.pablos.overload.ui.utils.OverloadNavigationType import cloud.pablos.overload.ui.views.TextView import kotlinx.coroutines.launch import java.time.LocalDate import java.time.format.DateTimeFormatter +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @OptIn(ExperimentalFoundationApi::class) @RequiresApi(Build.VERSION_CODES.S) @Composable @@ -64,6 +69,16 @@ fun HomeTab( bottomBar = { HomeTabDeleteBottomAppBar(state = state, onEvent = onEvent) }, + floatingActionButton = { + AnimatedVisibility( + visible = navigationType == OverloadNavigationType.BOTTOM_NAVIGATION && + state.selectedDayCalendar == LocalDate.now().toString(), + enter = scaleIn(), + exit = scaleOut(), + ) { + HomeTabFab(state = state, onEvent = onEvent) + } + }, ) { paddingValues -> Box(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.padding(paddingValues)) { @@ -100,17 +115,6 @@ fun HomeTab( item.screen(state, onEvent) } } - if ( - navigationType == OverloadNavigationType.BOTTOM_NAVIGATION && - state.selectedDayCalendar == LocalDate.now().toString() - ) { - Box( - modifier = Modifier.align(Alignment.BottomEnd) - .animateContentSize(), - ) { - HomeTabFab(state = state, onEvent = onEvent) - } - } } } } diff --git a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt index f30eda8..894b451 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/tabs/home/HomeTabFab.kt @@ -2,6 +2,7 @@ package cloud.pablos.overload.ui.tabs.home import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.animation.animateContentSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons @@ -45,9 +46,9 @@ fun HomeTabFab( onClick = { startOrStopPause(state, onEvent) }, - modifier = Modifier.padding(10.dp), containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.onSecondaryContainer, + modifier = Modifier.animateContentSize(), ) { Row( verticalAlignment = Alignment.CenterVertically, @@ -55,12 +56,12 @@ fun HomeTabFab( ) { Icon( imageVector = icon, - contentDescription = stringResource(id = R.string.edit), - modifier = Modifier.padding(start = 8.dp), + contentDescription = buttonText, + modifier = Modifier.padding(8.dp), ) TextView( text = buttonText, - modifier = Modifier.padding(start = 8.dp), + modifier = Modifier.padding(end = 8.dp), ) } } diff --git a/app/src/main/java/cloud/pablos/overload/ui/utils/WindowStateUtils.kt b/app/src/main/java/cloud/pablos/overload/ui/utils/WindowStateUtils.kt index d72feeb..f33ac02 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/utils/WindowStateUtils.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/utils/WindowStateUtils.kt @@ -47,3 +47,10 @@ enum class OverloadNavigationType { enum class OverloadNavigationContentPosition { TOP, CENTER } + +/** + * App Content shown depending on device size and state. + */ +enum class OverloadContentType { + SINGLE_PANE, DUAL_PANE +} diff --git a/app/src/main/java/cloud/pablos/overload/ui/views/YearView.kt b/app/src/main/java/cloud/pablos/overload/ui/views/YearView.kt index 10b257d..14570d8 100644 --- a/app/src/main/java/cloud/pablos/overload/ui/views/YearView.kt +++ b/app/src/main/java/cloud/pablos/overload/ui/views/YearView.kt @@ -36,6 +36,7 @@ import java.time.format.DateTimeFormatter import java.time.format.TextStyle import java.util.Locale +@OptIn(ExperimentalStdlibApi::class) @RequiresApi(Build.VERSION_CODES.S) @Composable fun YearView(year: Int, state: ItemState, onEvent: (ItemEvent) -> Unit, bottomPadding: Dp) { @@ -179,8 +180,8 @@ fun EmptyDayCell() { ) } -fun getFormattedDate(date: LocalDate): String { - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") +fun getFormattedDate(date: LocalDate, human: Boolean = false): String { + val formatter = DateTimeFormatter.ofPattern(if (human) "dd.MM.yyyy" else "yyyy-MM-dd") return date.format(formatter) } diff --git a/fastlane/metadata/android/en-US/changelogs/122.txt b/fastlane/metadata/android/en-US/changelogs/122.txt new file mode 100644 index 0000000..9dd2be6 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/122.txt @@ -0,0 +1,2 @@ +- animates start/stop buttons +- improves calendar for tablets \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f06ed29..d1d90be 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,8 +3,8 @@ # Do not add a dependency to an individual sample, edit the global version instead. ##### [versions] -accompanist = "0.30.1" -androidGradlePlugin = "8.1.3" +accompanist = "0.32.0" +androidGradlePlugin = "8.1.4" androidx-activity-compose = "1.8.0" androidx-appcompat = "1.6.1" androidx-benchmark = "1.2.0" @@ -25,12 +25,12 @@ androidxHiltNavigationCompose = "1.1.0" androix-test-uiautomator = "2.2.0" coil = "2.4.0" gson = "2.10.1" -acra = "5.11.1" +acra = "5.11.3" # @keep compileSdk = "33" -compose-compiler = "1.5.3" -coroutines = "1.7.2" +compose-compiler = "1.5.4" +coroutines = "1.7.3" google-maps = "18.2.0" gradle-versions = "0.46.0" hilt = "2.43.2" @@ -39,7 +39,7 @@ hiltExt = "1.1.0" jdkDesugar = "2.0.4" junit = "4.13.2" # @pin Update in conjuction with Compose Compiler -kotlin = "1.9.10" +kotlin = "1.9.20" kotlinx_immutable = "0.3.5" ksp = "1.9.10-1.0.13" maps-compose = "2.5.3"