Enable predictive back gestures, improve navigation animations
This commit is contained in:
@@ -40,6 +40,9 @@ android {
|
|||||||
jvmTarget.set(JvmTarget.JVM_17) // Use the enum for target JVM version
|
jvmTarget.set(JvmTarget.JVM_17) // Use the enum for target JVM version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ksp {
|
||||||
|
arg("room.schemaLocation", "$projectDir/schemas")
|
||||||
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,14 @@
|
|||||||
android:name=".TomatoApplication"
|
android:name=".TomatoApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Tomato">
|
android:theme="@style/Theme.Tomato"
|
||||||
|
tools:targetApi="36">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
package org.nsh07.pomodoro.ui
|
package org.nsh07.pomodoro.ui
|
||||||
|
|
||||||
|
import androidx.compose.animation.ContentTransform
|
||||||
import androidx.compose.animation.Crossfade
|
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.calculateEndPadding
|
||||||
import androidx.compose.foundation.layout.calculateStartPadding
|
import androidx.compose.foundation.layout.calculateStartPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme.motionScheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.ShortNavigationBar
|
import androidx.compose.material3.ShortNavigationBar
|
||||||
import androidx.compose.material3.ShortNavigationBarItem
|
import androidx.compose.material3.ShortNavigationBarItem
|
||||||
@@ -19,6 +24,8 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.rememberUpdatedState
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
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.platform.LocalLayoutDirection
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -48,6 +55,10 @@ fun AppScreen(
|
|||||||
val progress by rememberUpdatedState((uiState.totalTime.toFloat() - remainingTime) / uiState.totalTime)
|
val progress by rememberUpdatedState((uiState.totalTime.toFloat() - remainingTime) / uiState.totalTime)
|
||||||
var showBrandTitle by remember { mutableStateOf(true) }
|
var showBrandTitle by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
val layoutDirection = LocalLayoutDirection.current
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
val motionScheme = motionScheme
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
delay(1500)
|
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)
|
val backStack = rememberNavBackStack<Screen>(Screen.Timer)
|
||||||
|
|
||||||
@@ -75,7 +88,7 @@ fun AppScreen(
|
|||||||
{ if (backStack.size > 1) backStack.removeAt(1) }
|
{ if (backStack.size > 1) backStack.removeAt(1) }
|
||||||
},
|
},
|
||||||
icon = {
|
icon = {
|
||||||
Crossfade (selected) { selected ->
|
Crossfade(selected) { selected ->
|
||||||
if (selected) Icon(painterResource(it.selectedIcon), null)
|
if (selected) Icon(painterResource(it.selectedIcon), null)
|
||||||
else Icon(painterResource(it.unselectedIcon), null)
|
else Icon(painterResource(it.unselectedIcon), null)
|
||||||
}
|
}
|
||||||
@@ -89,6 +102,25 @@ fun AppScreen(
|
|||||||
NavDisplay(
|
NavDisplay(
|
||||||
backStack = backStack,
|
backStack = backStack,
|
||||||
onBack = { backStack.removeLastOrNull() },
|
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 {
|
entryProvider = entryProvider {
|
||||||
entry<Screen.Timer> {
|
entry<Screen.Timer> {
|
||||||
TimerScreen(
|
TimerScreen(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.nsh07.pomodoro.ui.settingsScreen
|
package org.nsh07.pomodoro.ui.settingsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@@ -7,6 +8,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.LoadingIndicator
|
import androidx.compose.material3.LoadingIndicator
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
@@ -34,7 +36,7 @@ fun SettingsScreen(modifier: Modifier = Modifier) {
|
|||||||
subtitle = {},
|
subtitle = {},
|
||||||
titleHorizontalAlignment = Alignment.CenterHorizontally
|
titleHorizontalAlignment = Alignment.CenterHorizontally
|
||||||
)
|
)
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
LoadingIndicator()
|
LoadingIndicator()
|
||||||
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
|
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.nsh07.pomodoro.ui.statsScreen
|
package org.nsh07.pomodoro.ui.statsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@@ -7,6 +8,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.LoadingIndicator
|
import androidx.compose.material3.LoadingIndicator
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
import androidx.compose.material3.MaterialTheme.typography
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
@@ -34,7 +36,7 @@ fun StatsScreen(modifier: Modifier = Modifier) {
|
|||||||
subtitle = {},
|
subtitle = {},
|
||||||
titleHorizontalAlignment = Alignment.CenterHorizontally
|
titleHorizontalAlignment = Alignment.CenterHorizontally
|
||||||
)
|
)
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize().background(colorScheme.surface)) {
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
LoadingIndicator()
|
LoadingIndicator()
|
||||||
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
|
Text("Coming Soon", style = typography.headlineSmall, fontFamily = robotoFlexTitle)
|
||||||
|
|||||||
@@ -34,16 +34,13 @@ import androidx.compose.material3.MaterialTheme.typography
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.StrokeCap
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -71,7 +68,6 @@ fun TimerScreen(
|
|||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val motionScheme = motionScheme
|
val motionScheme = motionScheme
|
||||||
val haptic = LocalHapticFeedback.current
|
|
||||||
|
|
||||||
val color by animateColorAsState(
|
val color by animateColorAsState(
|
||||||
if (uiState.timerMode == TimerMode.FOCUS) colorScheme.primary
|
if (uiState.timerMode == TimerMode.FOCUS) colorScheme.primary
|
||||||
@@ -89,10 +85,6 @@ fun TimerScreen(
|
|||||||
animationSpec = motionScheme.slowEffectsSpec()
|
animationSpec = motionScheme.slowEffectsSpec()
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(uiState.timerMode) {
|
|
||||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {
|
title = {
|
||||||
|
|||||||
Reference in New Issue
Block a user