diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 363286cd..61d185e8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,7 +20,7 @@ android { defaultConfig { applicationId = "com.joeloewi.croissant" - versionCode = 56 + versionCode = 57 versionName = "1.2.7" targetSdk = 34 diff --git a/app/src/main/kotlin/com/joeloewi/croissant/ui/navigation/main/attendances/screen/AttendancesScreen.kt b/app/src/main/kotlin/com/joeloewi/croissant/ui/navigation/main/attendances/screen/AttendancesScreen.kt index d92ed8f0..6d23ea89 100644 --- a/app/src/main/kotlin/com/joeloewi/croissant/ui/navigation/main/attendances/screen/AttendancesScreen.kt +++ b/app/src/main/kotlin/com/joeloewi/croissant/ui/navigation/main/attendances/screen/AttendancesScreen.kt @@ -62,7 +62,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.os.bundleOf import androidx.hilt.navigation.compose.hiltViewModel @@ -247,9 +246,7 @@ fun AttendanceWithGamesItem( } ) { DismissContent( - elevation = animateDpAsState( - HalfDp, label = "" - ).value, + dismissDirection = { swipeToDismissState.dismissDirection }, attendanceWithGames = item, onClickOneTimeAttend = remember { { attendance -> @@ -319,20 +316,24 @@ private fun SwipeToDismissBackground( } } -@OptIn(ExperimentalFoundationApi::class) +@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable private fun DismissContent( - elevation: Dp, + dismissDirection: () -> SwipeToDismissBoxValue, attendanceWithGames: () -> StableWrapper, onClickAttendance: (Attendance) -> Unit, onClickOneTimeAttend: (Attendance) -> Unit ) { ListItem( modifier = Modifier - .shadow(elevation = elevation) .composed { - remember { - clickable { onClickAttendance(attendanceWithGames().value.attendance) } + val elevation by animateDpAsState( + if (dismissDirection() != SwipeToDismissBoxValue.Settled) HalfDp else 0.dp, + label = "" + ) + + remember(elevation, attendanceWithGames().value.attendance.id) { + shadow(elevation).clickable { onClickAttendance(attendanceWithGames().value.attendance) } } }, supportingContent = { diff --git a/data/src/main/kotlin/com/joeloewi/croissant/data/util/ApiResponseExtensions.kt b/data/src/main/kotlin/com/joeloewi/croissant/data/util/ApiResponseExtensions.kt index e214135c..c0818121 100644 --- a/data/src/main/kotlin/com/joeloewi/croissant/data/util/ApiResponseExtensions.kt +++ b/data/src/main/kotlin/com/joeloewi/croissant/data/util/ApiResponseExtensions.kt @@ -10,45 +10,62 @@ suspend fun runAndRetryWithExponentialBackOff( initialDelay: Int = 500, retryFactor: Float = 2f, maxAttempts: Int = 5, - maxDelayMillis: Long = 5000, + maxDelayMillis: Long = 3000, task: suspend () -> ApiResponse, +): ApiResponse = retryTask( + attempt = 1, + initialDelay = initialDelay, + retryFactor = retryFactor, + maxAttempts = maxAttempts, + maxDelayMillis = maxDelayMillis, + task = task +) + +private tailrec suspend fun retryTask( + attempt: Int = 1, + initialDelay: Int, + retryFactor: Float, + maxAttempts: Int, + maxDelayMillis: Long, + task: suspend () -> ApiResponse ): ApiResponse { - var unsuccessfulAttempts = 0 - var apiResponse: ApiResponse + val isRetrying = attempt > 1 - while (true) { - if (unsuccessfulAttempts > 1) { - val fullJitterExponentialBackOffDelay = Random.nextLong( - 0, - min( - maxDelayMillis, - (initialDelay * retryFactor.pow(unsuccessfulAttempts)).toLong() - ) + if (isRetrying) { + val fullJitterExponentialBackOffDelay = Random.nextLong( + 0, + min( + maxDelayMillis, + (initialDelay * retryFactor.pow(attempt - 1)).toLong() ) + ) - delay(fullJitterExponentialBackOffDelay) - } + delay(fullJitterExponentialBackOffDelay) + } - apiResponse = task() - when (apiResponse) { - is ApiResponse.Success -> break - is ApiResponse.Failure -> { - when (apiResponse) { - is ApiResponse.Failure.Error -> { - break - } + return when (val apiResponse = task()) { + is ApiResponse.Success -> apiResponse + is ApiResponse.Failure -> { + when (apiResponse) { + is ApiResponse.Failure.Error -> { + apiResponse + } - is ApiResponse.Failure.Exception -> { - if (unsuccessfulAttempts <= maxAttempts) { - unsuccessfulAttempts += 1 - } else { - break - } + is ApiResponse.Failure.Exception -> { + if (attempt < maxAttempts) { + retryTask( + attempt = attempt + 1, + initialDelay = initialDelay, + retryFactor = retryFactor, + maxAttempts = maxAttempts, + maxDelayMillis = maxDelayMillis, + task = task + ) + } else { + apiResponse } } } } } - - return apiResponse } \ No newline at end of file