diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5042467e..60cbdb2e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,12 +28,12 @@ plugins { android { namespace = "com.sadellie.unitto" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "com.sadellie.unitto" minSdk = 21 - targetSdk = 33 + targetSdk = 34 versionCode = 22 versionName = "Lilac Luster" } diff --git a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt index 59ce7f13..131b7a64 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt +++ b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt @@ -19,10 +19,8 @@ package com.sadellie.unitto import androidx.compose.animation.core.tween -import androidx.compose.material3.DrawerValue +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalNavigationDrawer -import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf @@ -40,6 +38,10 @@ import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.sadellie.unitto.core.base.TopLevelDestinations import com.sadellie.unitto.core.ui.common.UnittoDrawerSheet +import com.sadellie.unitto.core.ui.common.UnittoModalNavigationDrawer +import com.sadellie.unitto.core.ui.common.close +import com.sadellie.unitto.core.ui.common.open +import com.sadellie.unitto.core.ui.common.rememberUnittoDrawerState import com.sadellie.unitto.core.ui.model.DrawerItems import com.sadellie.unitto.core.ui.theme.AppTypography import com.sadellie.unitto.core.ui.theme.DarkThemeColors @@ -49,13 +51,13 @@ import io.github.sadellie.themmo.Themmo import io.github.sadellie.themmo.rememberThemmoController import kotlinx.coroutines.launch +@OptIn(ExperimentalFoundationApi::class) @Composable internal fun UnittoApp(uiPrefs: UIPreferences) { val themmoController = rememberThemmoController( lightColorScheme = LightThemeColors, darkColorScheme = DarkThemeColors, - // Anything below will not be called if theming mode is still loading from DataStore themingMode = uiPrefs.themingMode, dynamicThemeEnabled = uiPrefs.enableDynamicTheme, amoledThemeEnabled = uiPrefs.enableAmoledTheme, @@ -66,7 +68,7 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { val sysUiController = rememberSystemUiController() // Navigation drawer stuff - val drawerState = rememberDrawerState(DrawerValue.Closed) + val drawerState = rememberUnittoDrawerState() val drawerScope = rememberCoroutineScope() val mainTabs = listOf( DrawerItems.Calculator, @@ -88,14 +90,6 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { } } } - val gesturesEnabled: Boolean by remember(navBackStackEntry?.destination) { - derivedStateOf { - // Will be true for routes like - // [null, calculator_route, settings_graph, settings_route, themes_route] - // We disable drawer drag gesture when we are too deep - navController.backQueue.size <= 4 - } - } Themmo( themmoController = themmoController, @@ -107,10 +101,8 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { mutableStateOf(backgroundColor.luminance() > 0.5f) } - ModalNavigationDrawer( - drawerState = drawerState, - gesturesEnabled = gesturesEnabled, - drawerContent = { + UnittoModalNavigationDrawer( + drawer = { UnittoDrawerSheet( modifier = Modifier, mainTabs = mainTabs, @@ -126,15 +118,20 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { restoreState = true } } + }, + modifier = Modifier, + state = drawerState, + gesturesEnabled = true, + scope = drawerScope, + content = { + UnittoNavigation( + navController = navController, + themmoController = it, + startDestination = uiPrefs.startingScreen, + openDrawer = { drawerScope.launch { drawerState.open() } } + ) } - ) { - UnittoNavigation( - navController = navController, - themmoController = it, - startDestination = uiPrefs.startingScreen, - openDrawer = { drawerScope.launch { drawerState.open() } } - ) - } + ) LaunchedEffect(useDarkIcons) { sysUiController.setNavigationBarColor(Color.Transparent, useDarkIcons) diff --git a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt b/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt index 8e5fcf8d..7e19b4ae 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt +++ b/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt @@ -23,7 +23,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import com.sadellie.unitto.feature.calculator.navigation.calculatorScreen @@ -55,20 +54,10 @@ internal fun UnittoNavigation( startDestination = startDestination, modifier = Modifier.background(MaterialTheme.colorScheme.background) ) { - fun navigateToSettings() { - navController.navigateToSettings { - popUpTo(navController.graph.findStartDestination().id) { - saveState = true - } - launchSingleTop = true - restoreState = true - } - } - converterScreen( navigateToLeftScreen = navController::navigateToLeftSide, navigateToRightScreen = navController::navigateToRightSide, - navigateToSettings = ::navigateToSettings, + navigateToSettings = navController::navigateToSettings, navigateToMenu = openDrawer, viewModel = converterViewModel ) @@ -95,12 +84,12 @@ internal fun UnittoNavigation( calculatorScreen( navigateToMenu = openDrawer, - navigateToSettings = ::navigateToSettings + navigateToSettings = navController::navigateToSettings ) dateDifferenceScreen( navigateToMenu = openDrawer, - navigateToSettings = ::navigateToSettings + navigateToSettings = navController::navigateToSettings ) } } diff --git a/build-logic/convention/src/main/java/UnittoHiltPlugin.kt b/build-logic/convention/src/main/java/UnittoHiltPlugin.kt index f883aa1d..be0545f1 100644 --- a/build-logic/convention/src/main/java/UnittoHiltPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoHiltPlugin.kt @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.getByType +@Suppress("UNUSED") class UnittoHiltPlugin : Plugin { override fun apply(target: Project) { with(target) { diff --git a/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt b/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt index 37a429f2..d7670ac2 100644 --- a/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt +++ b/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt @@ -25,6 +25,7 @@ import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.getByType +@Suppress("UNUSED") class UnittoLibraryComposePlugin : Plugin { override fun apply(target: Project) { with(target) { diff --git a/build-logic/convention/src/main/java/UnittoLibraryFeaturePlugin.kt b/build-logic/convention/src/main/java/UnittoLibraryFeaturePlugin.kt index 49b4e58d..26c031fb 100644 --- a/build-logic/convention/src/main/java/UnittoLibraryFeaturePlugin.kt +++ b/build-logic/convention/src/main/java/UnittoLibraryFeaturePlugin.kt @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.getByType +@Suppress("UNUSED") class UnittoLibraryFeaturePlugin : Plugin { override fun apply(target: Project) { with(target) { diff --git a/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt b/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt index 4e1bc798..b0189e6c 100644 --- a/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt @@ -25,6 +25,7 @@ import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies import org.gradle.kotlin.dsl.getByType +@Suppress("UNUSED") class UnittoLibraryPlugin : Plugin { override fun apply(target: Project) { with(target) { diff --git a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt b/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt index 0a63a567..99c0f09b 100644 --- a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt +++ b/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt @@ -34,7 +34,7 @@ internal fun Project.configureKotlinAndroid( commonExtension: CommonExtension<*, *, *, *>, ) { commonExtension.apply { - compileSdk = 33 + compileSdk = 34 defaultConfig { minSdk = 21 diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index 681bdca9..51d74dca 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -37,7 +37,6 @@ android { dependencies { testImplementation(libs.junit) - testImplementation(libs.org.robolectric) testImplementation(libs.androidx.compose.ui.test.junit4) debugImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoNavigationDrawer.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoNavigationDrawer.kt new file mode 100644 index 00000000..08fd55ac --- /dev/null +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoNavigationDrawer.kt @@ -0,0 +1,195 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.core.ui.common + +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.anchoredDraggable +import androidx.compose.foundation.gestures.animateTo +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.DrawerDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import com.sadellie.unitto.core.ui.model.DrawerItems +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import kotlin.math.roundToInt + +// Why do I have to do it myself? +@Composable +fun UnittoModalNavigationDrawer( + drawer: @Composable () -> Unit, + modifier: Modifier, + state: AnchoredDraggableState, + gesturesEnabled: Boolean, + scope: CoroutineScope, + content: @Composable () -> Unit, +) { + Box(modifier.fillMaxSize()) { + content() + + Scrim( + open = state.isOpen, + onClose = { if (gesturesEnabled) scope.launch { state.close() } }, + fraction = { + fraction(state.anchors.minAnchor(), state.anchors.maxAnchor(), state.offset) + }, + color = DrawerDefaults.scrimColor + ) + + // Drawer + Box(Modifier + .offset { + IntOffset( + x = state + .requireOffset() + .roundToInt(), y = 0 + ) + } + .anchoredDraggable( + state = state, + orientation = Orientation.Horizontal, + enabled = gesturesEnabled or state.isOpen, + ) + .padding(end = 18.dp) // Draggable when closed + ) { + drawer() + } + + } +} + +@Composable +private fun Scrim( + open: Boolean, + onClose: () -> Unit, + fraction: () -> Float, + color: Color, +) { + val dismissDrawer = if (open) { + Modifier.pointerInput(onClose) { detectTapGestures { onClose() } } + } else { + Modifier + } + + Canvas( + Modifier + .fillMaxSize() + .then(dismissDrawer) + ) { + drawRect(color, alpha = fraction()) + } +} + +enum class UnittoDrawerState { OPEN, CLOSED } + +@Composable +fun rememberUnittoDrawerState( + initialValue: UnittoDrawerState = UnittoDrawerState.CLOSED, +): AnchoredDraggableState { + val minValue = -with(LocalDensity.current) { 360.dp.toPx() } + val positionalThreshold = -minValue * 0.5f + val velocityThreshold = with(LocalDensity.current) { 400.dp.toPx() } + + return remember { + AnchoredDraggableState( + initialValue = initialValue, + anchors = DraggableAnchors { + UnittoDrawerState.OPEN at 0F + UnittoDrawerState.CLOSED at minValue + }, + positionalThreshold = { positionalThreshold }, + velocityThreshold = { velocityThreshold }, + animationSpec = tween() + ) + } +} + +private val AnchoredDraggableState.isOpen + get() = this.currentValue == UnittoDrawerState.OPEN + +suspend fun AnchoredDraggableState.close() { + this.animateTo(UnittoDrawerState.CLOSED) +} + +suspend fun AnchoredDraggableState.open() { + this.animateTo(UnittoDrawerState.OPEN) +} + +private fun fraction(a: Float, b: Float, pos: Float) = + ((pos - a) / (b - a)).coerceIn(0f, 1f) + +@Preview(backgroundColor = 0xFFC8F7D4, showBackground = true, showSystemUi = true) +@Composable +private fun PreviewUnittoModalNavigationDrawer() { + val drawerState = rememberUnittoDrawerState(initialValue = UnittoDrawerState.OPEN) + val corScope = rememberCoroutineScope() + + UnittoModalNavigationDrawer( + drawer = { + UnittoDrawerSheet( + modifier = Modifier, + mainTabs = listOf( + DrawerItems.Calculator, + DrawerItems.Calculator, + DrawerItems.Calculator, + ), + additionalTabs = listOf( + DrawerItems.Calculator, + DrawerItems.Calculator, + DrawerItems.Calculator, + ), + currentDestination = DrawerItems.Calculator.destination, + onItemClick = {} + ) + }, + modifier = Modifier, + state = drawerState, + gesturesEnabled = true, + scope = corScope, + content = { + Column { + Text(text = "Content") + Button( + onClick = { corScope.launch { drawerState.open() } } + ) { + Text(text = "BUTTON") + } + } + } + ) +} diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoSlider.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoSlider.kt index 73fc9141..d4e18137 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoSlider.kt +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoSlider.kt @@ -26,11 +26,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider -import androidx.compose.material3.SliderPositions +import androidx.compose.material3.SliderState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue @@ -72,18 +72,18 @@ fun UnittoSlider( @Composable private fun SquigglyTrack( - sliderPosition: SliderPositions, + sliderState: SliderState, eachWaveWidth: Float = 80f, strokeWidth: Float = 15f, filledColor: Color = MaterialTheme.colorScheme.primary, unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant ) { val coroutineScope = rememberCoroutineScope() - var direct by remember { mutableStateOf(0.72f) } + var direct by remember { mutableFloatStateOf(0.72f) } val animatedDirect = animateFloatAsState(direct, spring(stiffness = Spring.StiffnessLow)) - val slider = sliderPosition.activeRange.endInclusive + val slider = sliderState.valueRange.endInclusive - LaunchedEffect(sliderPosition.activeRange.endInclusive) { + LaunchedEffect(sliderState.valueRange.endInclusive) { coroutineScope.launch { delay(200L) direct *= -1 @@ -148,7 +148,7 @@ private fun SquigglyTrack( @Preview(device = "spec:width=1920dp,height=1080dp,dpi=480") @Composable private fun PreviewNewSlider() { - var currentValue by remember { mutableStateOf(0.9f) } + var currentValue by remember { mutableFloatStateOf(0.9f) } UnittoSlider( value = currentValue, diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt b/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt index 430a76c3..2e67a81e 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt +++ b/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt @@ -20,8 +20,8 @@ package com.sadellie.unitto.core.ui import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test class ExpressionTransformerTest { diff --git a/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt b/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt index 2f581428..28a5ec48 100644 --- a/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt +++ b/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt @@ -18,8 +18,8 @@ package com.sadellie.unitto.data.common -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test class IsExpressionText { diff --git a/data/epoch/src/test/java/com/sadellie/unitto/data/epoch/DateToEpochTest.kt b/data/epoch/src/test/java/com/sadellie/unitto/data/epoch/DateToEpochTest.kt index 5a4ee4f7..30b963a2 100644 --- a/data/epoch/src/test/java/com/sadellie/unitto/data/epoch/DateToEpochTest.kt +++ b/data/epoch/src/test/java/com/sadellie/unitto/data/epoch/DateToEpochTest.kt @@ -18,8 +18,8 @@ package com.sadellie.unitto.data.epoch -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test class DateToEpochTest { diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionComplexTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionComplexTest.kt index d530ebd6..f7ab5edb 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionComplexTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionComplexTest.kt @@ -18,7 +18,7 @@ package io.github.sadellie.evaluatto -import org.junit.Test +import org.junit.jupiter.api.Test class ExpressionComplexTest { diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionExceptionsTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionExceptionsTest.kt index 262c5841..78ffeb83 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionExceptionsTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionExceptionsTest.kt @@ -18,7 +18,7 @@ package io.github.sadellie.evaluatto -import org.junit.Test +import org.junit.jupiter.api.Test class ExpressionExceptionsTest { diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt index 24d0b75e..0e1f68f8 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt @@ -18,7 +18,7 @@ package io.github.sadellie.evaluatto -import org.junit.Test +import org.junit.jupiter.api.Test class ExpressionSimpleTest { diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt index fd8f8331..b6b9d8e6 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt @@ -18,9 +18,10 @@ package io.github.sadellie.evaluatto -import org.junit.Test +import org.junit.jupiter.api.Test class FixLexiconTest { + @Test fun `missing multiply`() { assertLex( diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt index 1651ff2e..806c42e7 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt @@ -18,12 +18,13 @@ package io.github.sadellie.evaluatto -import org.junit.Assert +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertThrows import java.math.BigDecimal import java.math.RoundingMode fun assertExpr(expr: String, result: String, radianMode: Boolean = true) = - Assert.assertEquals( + assertEquals( BigDecimal(result).setScale(10, RoundingMode.HALF_EVEN), Expression(expr, radianMode).calculate().setScale(10, RoundingMode.HALF_EVEN) ) @@ -33,13 +34,13 @@ fun assertExprFail( expr: String, radianMode: Boolean = true ) { - Assert.assertThrows(expectedThrowable) { + assertThrows(expectedThrowable) { Expression(expr, radianMode = radianMode).calculate() } } fun assertLex(expected: List, actual: String) = - Assert.assertEquals(expected, Tokenizer(actual).tokenize()) + assertEquals(expected, Tokenizer(actual).tokenize()) fun assertLex(expected: String, actual: String) = - Assert.assertEquals(expected, Tokenizer(actual).tokenize().joinToString("")) + assertEquals(expected, Tokenizer(actual).tokenize().joinToString("")) diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/TokenizerTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/TokenizerTest.kt index 12a23cc4..7f35b7ef 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/TokenizerTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/TokenizerTest.kt @@ -18,9 +18,10 @@ package io.github.sadellie.evaluatto -import org.junit.Test +import org.junit.jupiter.api.Test class TokenizerTest { + @Test fun tokens1() = assertLex(listOf("789"), "789") diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsRepositoryTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsRepositoryTest.kt index ab6b2a74..a1bfc406 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsRepositoryTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsRepositoryTest.kt @@ -21,8 +21,8 @@ package com.sadellie.unitto.data.units import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS import com.sadellie.unitto.data.model.AbstractUnit import com.sadellie.unitto.data.model.UnitGroup -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test import java.math.BigDecimal class AllUnitsRepositoryTest { diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt index 314db4d2..e5872ddb 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt @@ -20,14 +20,11 @@ package com.sadellie.unitto.data.units import com.sadellie.unitto.data.model.NumberBaseUnit import com.sadellie.unitto.data.model.UnitGroup -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test import java.math.BigDecimal -@RunWith(JUnit4::class) class AllUnitsTest { // Group and it's tested unit ids @@ -527,7 +524,7 @@ class AllUnitsTest { history[unitFrom.group] = content.plus(this) } - @After + @AfterEach fun after() { val unitGroup = history.keys.first() // GROUP : testedCount / totalCount diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinFilterAndSortTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinFilterAndSortTest.kt index 95d56a27..63cd6de9 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinFilterAndSortTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinFilterAndSortTest.kt @@ -22,8 +22,8 @@ import com.sadellie.unitto.data.model.AbstractUnit import com.sadellie.unitto.data.model.DefaultUnit import com.sadellie.unitto.data.model.UnitGroup import com.sadellie.unitto.data.model.sortByLev -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test import java.math.BigDecimal val baseList: List = listOf( diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinTest.kt index e9d4df7f..1cdb72bf 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/LevenshteinTest.kt @@ -19,8 +19,8 @@ package com.sadellie.unitto.data.units import com.sadellie.unitto.data.common.lev -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test class LevenshteinTest { diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt index 1deaf6d3..28657026 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt @@ -19,8 +19,8 @@ package com.sadellie.unitto.data.units import com.sadellie.unitto.data.common.setMinimumRequiredScale -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test import java.math.BigDecimal class MinimumRequiredScaleTest { diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt index 51758964..f99fbd4b 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt @@ -47,6 +47,7 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -120,8 +121,8 @@ private fun CalculatorScreen( val dragCoroutineScope = rememberCoroutineScope() val dragAnimSpec = rememberSplineBasedDecay() - var textThingyHeight by remember { mutableStateOf(0) } - var historyItemHeight by remember { mutableStateOf(0) } + var textThingyHeight by remember { mutableIntStateOf(0) } + var historyItemHeight by remember { mutableIntStateOf(0) } var showClearHistoryDialog by rememberSaveable { mutableStateOf(false) } val showClearHistoryButton by remember(dragAmount.value, historyItemHeight) { diff --git a/feature/converter/build.gradle.kts b/feature/converter/build.gradle.kts index 91b5c875..296ff6c4 100644 --- a/feature/converter/build.gradle.kts +++ b/feature/converter/build.gradle.kts @@ -30,7 +30,6 @@ android { dependencies { testImplementation(libs.junit) testImplementation(libs.org.jetbrains.kotlinx.coroutines.test) - testImplementation(libs.org.robolectric) testImplementation(libs.androidx.room.runtime) testImplementation(libs.androidx.room.ktx) kapt(libs.androidx.room.compiler) diff --git a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/CoroutinesTestUtils.kt b/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/CoroutinesTestUtils.kt deleted file mode 100644 index 68734339..00000000 --- a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/CoroutinesTestUtils.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Unitto is a unit converter for Android - * Copyright (c) 2022-2023 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestDispatcher -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain -import org.junit.rules.TestWatcher -import org.junit.runner.Description - -@ExperimentalCoroutinesApi -class CoroutineTestRule(private val dispatcher: TestDispatcher = UnconfinedTestDispatcher()) : - TestWatcher() { - - override fun starting(description: Description) { - super.starting(description) - Dispatchers.setMain(dispatcher) - } - - override fun finished(description: Description) { - super.finished(description) - Dispatchers.resetMain() - } - -} diff --git a/feature/datedifference/src/test/java/com/sadellie/unitto/feature/datedifference/DateDifferenceKtTest.kt b/feature/datedifference/src/test/java/com/sadellie/unitto/feature/datedifference/DateDifferenceKtTest.kt index b7e8162b..7591a9ae 100644 --- a/feature/datedifference/src/test/java/com/sadellie/unitto/feature/datedifference/DateDifferenceKtTest.kt +++ b/feature/datedifference/src/test/java/com/sadellie/unitto/feature/datedifference/DateDifferenceKtTest.kt @@ -18,8 +18,8 @@ package com.sadellie.unitto.feature.datedifference -import org.junit.Assert.assertEquals -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test import java.time.LocalDateTime import java.time.format.DateTimeFormatter diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt index 08d4b585..0bae6585 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/AboutScreen.kt @@ -37,6 +37,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue @@ -59,7 +60,7 @@ internal fun AboutScreen( ) { val mContext = LocalContext.current val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle() - var aboutItemClick: Int by rememberSaveable { mutableStateOf(0) } + var aboutItemClick: Int by rememberSaveable { mutableIntStateOf(0) } var showDialog: Boolean by rememberSaveable { mutableStateOf(false) } UnittoScreenWithLargeTopBar( diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt index 1d4e624f..a9929b51 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt @@ -40,7 +40,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier @@ -56,10 +56,10 @@ import com.sadellie.unitto.core.base.OutputFormat import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.base.Separator import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.UnittoSlider import com.sadellie.unitto.core.ui.common.SegmentedButton import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar +import com.sadellie.unitto.core.ui.common.UnittoSlider import com.sadellie.unitto.core.ui.common.squashable import com.sadellie.unitto.core.ui.common.textfield.formatExpression import com.sadellie.unitto.core.ui.theme.NumbersTextStyleDisplayMedium @@ -255,9 +255,9 @@ fun FormattingScreen( @Preview @Composable private fun PreviewFormattingScreen() { - var currentPrecision by remember { mutableStateOf(6) } - var currentSeparator by remember { mutableStateOf(Separator.COMMA) } - var currentOutputFormat by remember { mutableStateOf(OutputFormat.PLAIN) } + var currentPrecision by remember { mutableIntStateOf(6) } + var currentSeparator by remember { mutableIntStateOf(Separator.COMMA) } + var currentOutputFormat by remember { mutableIntStateOf(OutputFormat.PLAIN) } FormattingScreen( uiState = FormattingUIState( diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt index 1d14d759..96ca4201 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt @@ -21,7 +21,6 @@ package com.sadellie.unitto.feature.settings.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController -import androidx.navigation.NavOptionsBuilder import androidx.navigation.compose.composable import androidx.navigation.compose.navigation import com.sadellie.unitto.core.base.TopLevelDestinations @@ -41,8 +40,8 @@ internal const val thirdPartyRoute = "third_party_route" internal const val aboutRoute = "about_route" internal const val formattingRoute = "formatting_route" -fun NavController.navigateToSettings(builder: NavOptionsBuilder.() -> Unit) { - navigate(settingsRoute, builder) +fun NavController.navigateToSettings() { + navigate(settingsRoute) } fun NavController.navigateToUnitGroups() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67e1e916..66a7bbe4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,39 +1,39 @@ [versions] appCode = "22" appName = "Lilac Luster" -kotlin = "1.8.21" -androidxCore = "1.10.0" -androidGradlePlugin = "8.0.1" -orgJetbrainsKotlinxCoroutinesTest = "1.6.4" +kotlin = "1.9.0" +androidxCore = "1.10.1" +androidGradlePlugin = "8.0.2" +orgJetbrainsKotlinxCoroutinesTest = "1.7.2" androidxCompose = "1.5.0-alpha02" -androidxComposeCompiler = "1.4.7" -androidxComposeUi = "1.5.0-alpha04" -androidxComposeMaterial3 = "1.2.0-alpha01" -androidxNavigation = "2.5.3" +androidxComposeCompiler = "1.5.0" +androidxComposeUi = "1.6.0-alpha01" +androidxComposeMaterial3 = "1.2.0-alpha03" +androidxNavigation = "2.6.0" androidxLifecycleRuntimeCompose = "2.6.1" androidxHilt = "1.0.0" -comGoogleDagger = "2.45" -androidxComposeMaterialIconsExtended = "1.5.0-alpha04" +comGoogleDagger = "2.47" +androidxComposeMaterialIconsExtended = "1.6.0-alpha01" androidxDatastore = "1.0.0" comGoogleAccompanist = "0.30.1" -androidxRoom = "2.5.1" -comSquareupMoshi = "1.14.0" +androidxRoom = "2.6.0-alpha02" +comSquareupMoshi = "1.15.0" comSquareupRetrofit2 = "2.9.0" -comGithubSadellieThemmo = "ed4063f70f" +comGithubSadellieThemmo = "1.0.0" orgBurnoutcrewComposereorderable = "0.9.6" -junit = "4.13.2" +junit = "5.9.3" androidxTest = "1.5.0" -androidxTestExt = "1.1.4" +androidxTestExt = "1.1.5" androidDesugarJdkLibs = "2.0.3" -androidxTestRunner = "1.5.1" +androidxTestRunner = "1.5.2" androidxTestRules = "1.5.0" -orgRobolectric = "4.9" +orgRobolectric = "4.10.3" [libraries] androidx-core = { group = "androidx.core", name = "core-ktx", version.ref = "androidxCore" } androidx-test = { group = "androidx.test", name = "core", version.ref = "androidxTest" } androidx-test-ext = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxTestExt" } -junit = { group = "junit", name = "junit", version.ref = "junit" } +junit = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" } androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxTestRules" } org-robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "orgRobolectric" }