Enable predictive back gestures, improve navigation animations

This commit is contained in:
Nishant Mishra
2025-07-04 18:06:41 +05:30
parent 8f3ee5359e
commit fd8b716ee9
6 changed files with 46 additions and 13 deletions

View File

@@ -40,6 +40,9 @@ android {
jvmTarget.set(JvmTarget.JVM_17) // Use the enum for target JVM version
}
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
buildFeatures {
compose = true
}

View File

@@ -6,12 +6,14 @@
android:name=".TomatoApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Tomato">
android:theme="@style/Theme.Tomato"
tools:targetApi="36">
<activity
android:name=".MainActivity"
android:exported="true"

View File

@@ -1,12 +1,17 @@
package org.nsh07.pomodoro.ui
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.Crossfade
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme.motionScheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ShortNavigationBar
import androidx.compose.material3.ShortNavigationBarItem
@@ -19,6 +24,8 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.painterResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -48,6 +55,10 @@ fun AppScreen(
val progress by rememberUpdatedState((uiState.totalTime.toFloat() - remainingTime) / uiState.totalTime)
var showBrandTitle by remember { mutableStateOf(true) }
val layoutDirection = LocalLayoutDirection.current
val haptic = LocalHapticFeedback.current
val motionScheme = motionScheme
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
delay(1500)
@@ -55,7 +66,9 @@ fun AppScreen(
}
}
val layoutDirection = LocalLayoutDirection.current
LaunchedEffect(uiState.timerMode) {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
val backStack = rememberNavBackStack<Screen>(Screen.Timer)
@@ -75,7 +88,7 @@ fun AppScreen(
{ if (backStack.size > 1) backStack.removeAt(1) }
},
icon = {
Crossfade (selected) { selected ->
Crossfade(selected) { selected ->
if (selected) Icon(painterResource(it.selectedIcon), null)
else Icon(painterResource(it.unselectedIcon), null)
}
@@ -89,6 +102,25 @@ fun AppScreen(
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
transitionSpec = {
ContentTransform(
fadeIn(motionScheme.defaultEffectsSpec()),
fadeOut(motionScheme.defaultEffectsSpec())
)
},
popTransitionSpec = {
ContentTransform(
fadeIn(motionScheme.defaultEffectsSpec()),
fadeOut(motionScheme.defaultEffectsSpec())
)
},
predictivePopTransitionSpec = {
ContentTransform(
fadeIn(motionScheme.defaultEffectsSpec()),
fadeOut(motionScheme.defaultEffectsSpec()) +
scaleOut(targetScale = 0.7f),
)
},
entryProvider = entryProvider {
entry<Screen.Timer> {
TimerScreen(

View File

@@ -1,5 +1,6 @@
package org.nsh07.pomodoro.ui.settingsScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -7,6 +8,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
@@ -34,7 +36,7 @@ fun SettingsScreen(modifier: Modifier = Modifier) {
subtitle = {},
titleHorizontalAlignment = Alignment.CenterHorizontally
)
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
LoadingIndicator()
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)

View File

@@ -1,5 +1,6 @@
package org.nsh07.pomodoro.ui.statsScreen
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -7,6 +8,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
@@ -34,7 +36,7 @@ fun StatsScreen(modifier: Modifier = Modifier) {
subtitle = {},
titleHorizontalAlignment = Alignment.CenterHorizontally
)
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
LoadingIndicator()
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)

View File

@@ -34,16 +34,13 @@ import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@@ -71,7 +68,6 @@ fun TimerScreen(
modifier: Modifier = Modifier
) {
val motionScheme = motionScheme
val haptic = LocalHapticFeedback.current
val color by animateColorAsState(
if (uiState.timerMode == TimerMode.FOCUS) colorScheme.primary
@@ -89,10 +85,6 @@ fun TimerScreen(
animationSpec = motionScheme.slowEffectsSpec()
)
LaunchedEffect(uiState.timerMode) {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
Column(modifier = modifier) {
TopAppBar(
title = {