diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 22b7d229a..05ce6c08a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -176,6 +176,10 @@ dependencies { implementation(libs.activity.compose) implementation(libs.appcompat) + // Adaptive Navigation Suite + implementation(libs.androidx.compose.material3.adaptive.navigation.suite) + implementation(libs.androidx.compose.material3.adaptive.navigation) + // Testing testImplementation(libs.junit) androidTestImplementation(libs.junit.ext) diff --git a/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt b/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt index 11fb7bbb4..ede8e865a 100644 --- a/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt +++ b/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt @@ -3,21 +3,17 @@ package me.ash.reader.ui.component import android.os.Build import android.view.SoundEffectConstants import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.material3.* +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp @@ -46,35 +42,24 @@ fun FilterBar( MaterialTheme.colorScheme.primaryContainer } onDark MaterialTheme.colorScheme.secondaryContainer + val layoutType = NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo( + currentWindowAdaptiveInfo() + ) + val containerHeight = when (filterBarStyle) { FlowFilterBarStylePreference.Icon.value -> 64.dp else -> 80.dp } - Surface( - color = MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation), - modifier = modifier - ) { - Row( - modifier = - Modifier - .fillMaxWidth() - .windowInsetsPadding(NavigationBarDefaults.windowInsets) - .defaultMinSize(minHeight = containerHeight) - .selectableGroup(), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - - Spacer(modifier = Modifier.width(filterBarPadding)) + NavigationSuiteScaffold( + modifier = modifier.background(MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation)), + navigationSuiteItems = { Filter.values.forEach { item -> - NavigationBarItem( - modifier = Modifier.height(containerHeight), - alwaysShowLabel = when (filterBarStyle) { - FlowFilterBarStylePreference.Icon.value -> false - FlowFilterBarStylePreference.IconLabel.value -> true - FlowFilterBarStylePreference.IconLabelOnlySelected.value -> false - else -> false + item( + selected = filter == item, + onClick = { + view.playSoundEffect(SoundEffectConstants.CLICK) + filterOnClick(item) }, icon = { Icon( @@ -92,28 +77,17 @@ fun FilterBar( { Text( text = item.toName(), -// style = MaterialTheme.typography.labelLarge, maxLines = 1, overflow = TextOverflow.Ellipsis, ) } - }, - selected = filter == item, - onClick = { -// view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - view.playSoundEffect(SoundEffectConstants.CLICK) - filterOnClick(item) - }, - colors = NavigationBarItemDefaults.colors( - indicatorColor = indicatorColor, - unselectedIconColor = MaterialTheme.colorScheme.onSurfaceVariant, - selectedIconColor = MaterialTheme.colorScheme.contentColorFor(indicatorColor), - unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant, - selectedTextColor = MaterialTheme.colorScheme.onSurface - ) + } ) } - Spacer(modifier = Modifier.width(filterBarPadding)) - } + }, + layoutType = layoutType, + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation), + ) { + Spacer(modifier = Modifier.defaultMinSize(minHeight = containerHeight).navigationBarsPadding()) } } diff --git a/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt b/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt index b75862ca7..a0c70e86d 100644 --- a/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt +++ b/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt @@ -1,12 +1,14 @@ package me.ash.reader.ui.component.base import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.* import androidx.compose.material3.* +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScope import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp @@ -24,43 +26,98 @@ fun RYScaffold( navigationIcon: (@Composable () -> Unit)? = null, actions: (@Composable RowScope.() -> Unit)? = null, topBar: (@Composable () -> Unit)? = null, - bottomBar: (@Composable () -> Unit)? = null, floatingActionButton: (@Composable () -> Unit)? = null, + navigationSuiteItems: (NavigationSuiteScope.() -> Unit)? = null, content: @Composable () -> Unit = {}, ) { - Scaffold( - modifier = modifier - .background( - MaterialTheme.colorScheme.surfaceColorAtElevation( - topBarTonalElevation, - color = containerColor - ) - ), - containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( - containerTonalElevation, - color = containerColor - ) onDark MaterialTheme.colorScheme.surface, - topBar = { - if (topBar != null) topBar() else if (navigationIcon != null || actions != null) { - TopAppBar( - title = {}, - navigationIcon = { navigationIcon?.invoke() }, - actions = { actions?.invoke(this) }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( - topBarTonalElevation - ), + val layoutType = NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo( + currentWindowAdaptiveInfo() + ) + + if (navigationSuiteItems != null) { + NavigationSuiteScaffold( + modifier = modifier + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation, + color = containerColor ) - ) + ), + layoutType = layoutType, + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + containerTonalElevation, + color = containerColor + ) onDark MaterialTheme.colorScheme.surface, + navigationSuiteItems = navigationSuiteItems, + content = { + Column { + if (topBar != null) { + topBar() + } else if (navigationIcon != null || actions != null) { + TopAppBar( + title = {}, + navigationIcon = { navigationIcon?.invoke() }, + actions = { actions?.invoke(this) }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation + ), + ) + ) + } + content() + if (floatingActionButton != null) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomEnd + ) { + floatingActionButton() + } + } + } } - }, - content = { - Column { - Spacer(modifier = Modifier.height(it.calculateTopPadding())) - content() - } - }, - bottomBar = { bottomBar?.invoke() }, - floatingActionButton = { floatingActionButton?.invoke() }, - ) + ) + } else { + Scaffold( + modifier = modifier + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation, + color = containerColor + ) + ), + topBar = { + if (topBar != null) { + topBar() + } else if (navigationIcon != null || actions != null) { + TopAppBar( + title = {}, + navigationIcon = { navigationIcon?.invoke() }, + actions = { actions?.invoke(this) }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation + ), + ) + ) + } + }, + floatingActionButton = { + if (floatingActionButton != null) { + floatingActionButton() + } + }, + content = { + Column { + Spacer(modifier = Modifier.height(it.calculateTopPadding())) + content() + } + }, + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + containerTonalElevation, + color = containerColor + ) onDark MaterialTheme.colorScheme.surface + ) + } } + diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt index fae4b5223..f97b54252 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt @@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.KeyboardArrowRight @@ -27,13 +26,13 @@ import androidx.compose.material.icons.rounded.UnfoldLess import androidx.compose.material.icons.rounded.UnfoldMore import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable @@ -49,26 +48,19 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshots.SnapshotStateMap import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController +import androidx.window.core.layout.WindowWidthSizeClass import androidx.work.WorkInfo import kotlinx.coroutines.launch import me.ash.reader.R -import me.ash.reader.infrastructure.preference.LocalFeedsFilterBarFilled -import me.ash.reader.infrastructure.preference.LocalFeedsFilterBarPadding -import me.ash.reader.infrastructure.preference.LocalFeedsFilterBarStyle -import me.ash.reader.infrastructure.preference.LocalFeedsFilterBarTonalElevation -import me.ash.reader.infrastructure.preference.LocalFeedsGroupListExpand -import me.ash.reader.infrastructure.preference.LocalFeedsGroupListTonalElevation -import me.ash.reader.infrastructure.preference.LocalFeedsTopBarTonalElevation -import me.ash.reader.infrastructure.preference.LocalNewVersionNumber -import me.ash.reader.infrastructure.preference.LocalSkipVersionNumber -import me.ash.reader.ui.component.FilterBar +import me.ash.reader.domain.model.general.Filter +import me.ash.reader.infrastructure.preference.* import me.ash.reader.ui.component.base.Banner import me.ash.reader.ui.component.base.DisplayText import me.ash.reader.ui.component.base.FeedbackIconButton @@ -103,6 +95,7 @@ fun FeedsPage( subscribeViewModel: SubscribeViewModel = hiltViewModel(), homeViewModel: HomeViewModel, ) { + var accountTabVisible by remember { mutableStateOf(false) } val scope = rememberCoroutineScope() @@ -412,22 +405,42 @@ fun FeedsPage( } } }, - bottomBar = { - FilterBar( - filter = filterUiState.filter, - filterBarStyle = filterBarStyle.value, - filterBarFilled = filterBarFilled.value, - filterBarPadding = filterBarPadding.dp, - filterBarTonalElevation = filterBarTonalElevation.value.dp, - ) { - filterChange( - navController = navController, - homeViewModel = homeViewModel, - filterState = filterUiState.copy(filter = it), - isNavigate = false, + navigationSuiteItems = { + Filter.values.forEach { item -> + item( + selected = filterUiState.filter == item, + onClick = { + filterChange( + navController = navController, + homeViewModel = homeViewModel, + filterState = filterUiState.copy(filter = item), + isNavigate = false, + ) + }, + icon = { + Icon( + imageVector = if (filterUiState.filter == item && filterBarFilled.value) { + item.iconFilled + } else { + item.iconOutline + }, + contentDescription = item.toName() + ) + }, + label = if (filterBarStyle.value == FlowFilterBarStylePreference.Icon.value) { + null + } else { + { + Text( + text = item.toName(), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } ) } - } + }, ) SubscribeDialog(subscribeViewModel = subscribeViewModel) diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt index 6c21b22e4..ce1cf900f 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt @@ -16,11 +16,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.rounded.DoneAll import androidx.compose.material.icons.rounded.Search -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.LargeTopAppBar -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.* import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable @@ -37,8 +33,8 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController @@ -50,17 +46,7 @@ import me.ash.reader.R import me.ash.reader.domain.model.article.ArticleFlowItem import me.ash.reader.domain.model.article.ArticleWithFeed import me.ash.reader.domain.model.general.Filter -import me.ash.reader.infrastructure.preference.LocalFlowArticleListDateStickyHeader -import me.ash.reader.infrastructure.preference.LocalFlowArticleListFeedIcon -import me.ash.reader.infrastructure.preference.LocalFlowArticleListTonalElevation -import me.ash.reader.infrastructure.preference.LocalFlowFilterBarFilled -import me.ash.reader.infrastructure.preference.LocalFlowFilterBarPadding -import me.ash.reader.infrastructure.preference.LocalFlowFilterBarStyle -import me.ash.reader.infrastructure.preference.LocalFlowFilterBarTonalElevation -import me.ash.reader.infrastructure.preference.LocalFlowTopBarTonalElevation -import me.ash.reader.infrastructure.preference.LocalMarkAsReadOnScroll -import me.ash.reader.infrastructure.preference.LocalSharedContent -import me.ash.reader.ui.component.FilterBar +import me.ash.reader.infrastructure.preference.* import me.ash.reader.ui.component.base.DisplayText import me.ash.reader.ui.component.base.FeedbackIconButton import me.ash.reader.ui.component.base.RYExtensibleVisibility @@ -405,23 +391,43 @@ fun FlowPage( } } }, - bottomBar = { - FilterBar( - filter = filterUiState.filter, - filterBarStyle = filterBarStyle.value, - filterBarFilled = filterBarFilled.value, - filterBarPadding = filterBarPadding.dp, - filterBarTonalElevation = filterBarTonalElevation.value.dp, - ) { - scope.launch { - if (flowUiState.listState.firstVisibleItemIndex != 0) { - flowUiState.listState.animateScrollToItem(0) + navigationSuiteItems = { + Filter.values.forEach { item -> + item( + selected = filterUiState.filter == item, + onClick = { + scope.launch { + if (flowUiState.listState.firstVisibleItemIndex != 0) { + flowUiState.listState.animateScrollToItem(0) + } + } + if (filterUiState.filter != item) { + homeViewModel.changeFilter(filterUiState.copy(filter = item)) + } + }, + icon = { + Icon( + imageVector = if (filterUiState.filter == item && filterBarFilled.value) { + item.iconFilled + } else { + item.iconOutline + }, + contentDescription = item.toName() + ) + }, + label = if (filterBarStyle.value == FlowFilterBarStylePreference.Icon.value) { + null + } else { + { + Text( + text = item.toName(), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } } - } - if (filterUiState.filter != it) { - homeViewModel.changeFilter(filterUiState.copy(filter = it)) - } + ) } - } - ) + }, + ) } diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AccountsPage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AccountsPage.kt index 0258972be..a74da8bd4 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AccountsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AccountsPage.kt @@ -1,6 +1,5 @@ package me.ash.reader.ui.page.settings.accounts -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt index 840f491ee..233448c39 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt @@ -1,6 +1,5 @@ package me.ash.reader.ui.page.settings.accounts -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt index 98dc8dce0..8cac3c826 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/reading/ReadingStylePage.kt @@ -49,7 +49,6 @@ import me.ash.reader.infrastructure.preference.LocalReadingPageTonalElevation import me.ash.reader.infrastructure.preference.LocalReadingRenderer import me.ash.reader.infrastructure.preference.LocalReadingTheme import me.ash.reader.infrastructure.preference.ReadingFontsPreference -import me.ash.reader.infrastructure.preference.ReadingPageTonalElevationPreference import me.ash.reader.infrastructure.preference.ReadingRendererPreference import me.ash.reader.infrastructure.preference.ReadingThemePreference import me.ash.reader.infrastructure.preference.not diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/languages/LanguagesPage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/languages/LanguagesPage.kt index a85d46b9c..8011e65e2 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/languages/LanguagesPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/languages/LanguagesPage.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.KeyboardArrowRight -import androidx.compose.material.icons.outlined.KeyboardArrowRight import androidx.compose.material.icons.outlined.Lightbulb import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material3.ExperimentalMaterial3Api diff --git a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt index 8a0cfd5f1..68f245964 100644 --- a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt @@ -89,7 +89,6 @@ fun StartupPage( } } }, - bottomBar = null, floatingActionButton = { ExtendedFloatingActionButton( modifier = Modifier.navigationBarsPadding(), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ca38138c8..f3851557b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,6 +26,10 @@ profileinstaller = "1.3.1" room = "2.6.1" work = "2.9.0" +#Adaptive Navigation Suite +adaptiveNavigationSuite = "1.3.1" +material3-adaptive = "1.0.0" + # Compose composeBom = "2024.09.02" composeCompiler = "1.5.8" @@ -118,6 +122,10 @@ core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +#Adaptive Navigation Suite +androidx-compose-material3-adaptive-navigation-suite = { module = "androidx.compose.material3:material3-adaptive-navigation-suite", version.ref = "adaptiveNavigationSuite" } +androidx-compose-material3-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "material3-adaptive" } + # Testing junit = { group = "junit", name = "junit", version.ref = "junit" } junit-ext = { group = "androidx.test.ext", name = "junit", version.ref = "junitExt" }