Migration to Kotlin 1.9.0 and Compose 1.5.0

This commit is contained in:
Thomas Andres Gomez 2023-08-30 15:46:15 +02:00
parent 08346d1dba
commit 42b26e2b9b
15 changed files with 89 additions and 136 deletions

View file

@ -10,7 +10,7 @@ plugins {
android {
namespace = "com.pixelized.rplexicon"
compileSdk = 33
compileSdk = 34
signingConfigs {
getByName("debug") {
@ -30,7 +30,7 @@ android {
defaultConfig {
applicationId = "com.pixelized.rplexicon"
minSdk = 26
targetSdk = 33
targetSdk = 34
versionName = "0.3.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@ -80,7 +80,7 @@ android {
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.8"
kotlinCompilerExtensionVersion = "1.5.2"
}
packaging {
@ -99,16 +99,18 @@ dependencies {
implementation("androidx.activity:activity-compose:1.7.2")
// Compose
implementation("androidx.compose.ui:ui:1.4.3")
implementation("androidx.compose.ui:ui-util:1.4.3")
implementation("androidx.compose.ui:ui-graphics:1.4.3")
implementation("androidx.compose.ui:ui-tooling-preview:1.4.3")
implementation("androidx.compose.material:material:1.4.3")
implementation("androidx.compose.ui:ui:1.5.0")
implementation("androidx.compose.ui:ui-util:1.5.0")
implementation("androidx.compose.ui:ui-graphics:1.5.0")
implementation("androidx.compose.ui:ui-tooling-preview:1.5.0")
implementation("androidx.compose.material:material:1.5.0")
implementation("androidx.compose.material3:material3:1.1.1")
debugImplementation("androidx.compose.ui:ui-tooling:1.4.3")
debugImplementation("androidx.compose.ui:ui-tooling:1.5.0")
// Navigation
implementation("androidx.navigation:navigation-compose:2.7.1")
// Accompanist
implementation("com.google.accompanist:accompanist-navigation-animation:0.30.1")
implementation("com.google.accompanist:accompanist-placeholder:0.30.1")
// Splash Screen support prior to Android 12
@ -132,8 +134,8 @@ dependencies {
// Hilt: Dependency injection
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
implementation("com.google.dagger:hilt-android:2.45")
kapt("com.google.dagger:hilt-compiler:2.45")
implementation("com.google.dagger:hilt-android:2.46.1")
kapt("com.google.dagger:hilt-compiler:2.46.1")
// Image
implementation("com.github.skydoves:landscapist-glide:2.1.11")

View file

@ -1,6 +1,5 @@
package com.pixelized.rplexicon.ui.navigation
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.BottomAppBar
@ -17,7 +16,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.staticCompositionLocalOf
@ -26,8 +25,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.pixelized.rplexicon.LocalSnack
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.navigation.pages.LEXICON_LIST_ROUTE
@ -44,10 +43,10 @@ val LocalPageNavHost = staticCompositionLocalOf<NavHostController> {
error("LocalScreenNavHost not ready")
}
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeNavHost(
navHostController: NavHostController = rememberAnimatedNavController(),
navHostController: NavHostController = rememberNavController(),
bottomBarItems: List<BottomBarItem> = rememberBottomBarItems(navHostController),
lexiconListState: LazyListState,
questListState: LazyListState,
@ -72,7 +71,7 @@ fun HomeNavHost(
},
bottomBar = {
val selectedIndex = rememberSaveable {
mutableStateOf(bottomBarItems.indexOfFirst { it.route == startDestination })
mutableIntStateOf(bottomBarItems.indexOfFirst { it.route == startDestination })
}
BottomAppBar(
containerColor = MaterialTheme.colorScheme.surface,
@ -105,7 +104,7 @@ fun HomeNavHost(
CompositionLocalProvider(
LocalPageNavHost provides navHostController,
) {
AnimatedNavHost(
NavHost(
modifier = Modifier.padding(padding),
navController = navHostController,
startDestination = startDestination,

View file

@ -1,6 +1,5 @@
package com.pixelized.rplexicon.ui.navigation
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@ -8,8 +7,8 @@ import androidx.compose.runtime.staticCompositionLocalOf
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.pixelized.rplexicon.ui.navigation.screens.AUTHENTICATION_ROUTE
import com.pixelized.rplexicon.ui.navigation.screens.composableAuthentication
import com.pixelized.rplexicon.ui.navigation.screens.composableHome
@ -22,10 +21,9 @@ val LocalScreenNavHost = staticCompositionLocalOf<NavHostController> {
error("LocalScreenNavHost not ready")
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun ScreenNavHost(
navHostController: NavHostController = rememberAnimatedNavController(),
navHostController: NavHostController = rememberNavController(),
startDestination: String = AUTHENTICATION_ROUTE,
) {
val lexiconListState = rememberLazyListState()
@ -35,7 +33,7 @@ fun ScreenNavHost(
CompositionLocalProvider(
LocalScreenNavHost provides navHostController,
) {
AnimatedNavHost(
NavHost(
navController = navHostController,
startDestination = startDestination,
) {

View file

@ -1,19 +1,27 @@
package com.pixelized.rplexicon.ui.navigation
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.runtime.Composable
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavGraphBuilder
import com.google.accompanist.navigation.animation.composable
import androidx.navigation.compose.composable
typealias EnterAnimation = AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?
typealias ExitAnimation = AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.animatedComposable(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
animation: NavigationAnimation = NavigationAnimation.NONE,
content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
) {
composable(
route = route,
@ -26,82 +34,30 @@ fun NavGraphBuilder.animatedComposable(
)
}
@OptIn(ExperimentalAnimationApi::class)
sealed class NavigationAnimation constructor(
val enterTransition: (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)?,
val exitTransition: (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)?,
val popEnterTransition: (AnimatedContentScope<NavBackStackEntry>.() -> EnterTransition?)?,
val popExitTransition: (AnimatedContentScope<NavBackStackEntry>.() -> ExitTransition?)?,
val enterTransition: EnterAnimation?,
val exitTransition: ExitAnimation?,
val popEnterTransition: EnterAnimation?,
val popExitTransition: ExitAnimation?,
) {
object Push : NavigationAnimation(
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Left,
animationSpec = tween(DURATION),
)
},
exitTransition = {
null
},
popEnterTransition = {
null
},
popExitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Right,
animationSpec = tween(DURATION),
)
},
data object Push : NavigationAnimation(
enterTransition = { slideInHorizontally { it } },
exitTransition = { slideOutHorizontally { -it / 5 } },
popEnterTransition = { slideInHorizontally { -it / 5 } },
popExitTransition = { slideOutHorizontally { it } },
)
object Modal : NavigationAnimation(
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Up,
animationSpec = tween(DURATION),
)
},
exitTransition = {
null
},
popEnterTransition = {
null
},
popExitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Down,
animationSpec = tween(DURATION),
)
},
data object Fade : NavigationAnimation(
enterTransition = { fadeIn() },
exitTransition = { fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { fadeOut() },
)
object Fade : NavigationAnimation(
enterTransition = {
fadeIn(
animationSpec = tween(DURATION),
)
},
exitTransition = {
null
},
popEnterTransition = {
null
},
popExitTransition = {
fadeOut(
animationSpec = tween(DURATION),
)
},
data object NONE : NavigationAnimation(
enterTransition = { EnterTransition.None },
exitTransition = { ExitTransition.None },
popEnterTransition = { EnterTransition.None },
popExitTransition = { ExitTransition.None },
)
object NONE : NavigationAnimation(
enterTransition = null,
exitTransition = null,
popEnterTransition = null,
popExitTransition = null,
)
companion object {
const val DURATION = 300
}
}

View file

@ -17,7 +17,7 @@ fun NavGraphBuilder.composableLexicon(
) {
animatedComposable(
route = LEXICON_LIST_ROUTE,
animation = NavigationAnimation.NONE,
animation = NavigationAnimation.Fade,
) {
LexiconScreen(
lazyListState = lazyListState

View file

@ -17,7 +17,7 @@ fun NavGraphBuilder.composableLocations(
) {
animatedComposable(
route = LOCATION_LIST_ROUTE,
animation = NavigationAnimation.NONE,
animation = NavigationAnimation.Fade,
) {
LocationScreen(
lazyListState = lazyListState,

View file

@ -17,9 +17,11 @@ fun NavGraphBuilder.composableQuests(
) {
animatedComposable(
route = QUEST_LIST_ROUTE,
animation = NavigationAnimation.NONE,
animation = NavigationAnimation.Fade,
) {
QuestListScreen(lazyListState = lazyListState)
QuestListScreen(
lazyListState = lazyListState,
)
}
}

View file

@ -14,7 +14,7 @@ const val AUTHENTICATION_ROUTE = ROUTE
fun NavGraphBuilder.composableAuthentication() {
animatedComposable(
route = AUTHENTICATION_ROUTE,
animation = NavigationAnimation.Fade,
animation = NavigationAnimation.Push,
) {
AuthenticationScreen()
}

View file

@ -19,7 +19,7 @@ fun NavGraphBuilder.composableHome(
) {
animatedComposable(
route = HOME_ROUTE,
animation = NavigationAnimation.Fade,
animation = NavigationAnimation.Push,
) {
HomeNavHost(
lexiconListState = lexiconListState,

View file

@ -5,7 +5,6 @@ import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.net.Uri
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
@ -14,7 +13,6 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.lazy.LazyRow
@ -35,13 +33,11 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@ -113,10 +109,7 @@ fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio {
) ?: emptyList()
),
diminutive = diminutive?.let {
highlightRegex?.annotatedString(
input = it,
spanStyle = highlight
)
highlightRegex.annotatedString(input = it, spanStyle = highlight)
},
gender = AnnotatedString(
text = gender,
@ -133,13 +126,13 @@ fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio {
}
),
description = description?.let { description ->
highlightRegex?.annotatedString(description, spanStyle = highlight)
highlightRegex.annotatedString(input = description, spanStyle = highlight)
},
history = history?.let { history ->
highlightRegex?.annotatedString(history, spanStyle = highlight)
highlightRegex.annotatedString(input = history, spanStyle = highlight)
},
tags = tags?.let { tags ->
highlightRegex?.annotatedString(tags, spanStyle = highlight)
highlightRegex.annotatedString(input = tags, spanStyle = highlight)
},
)
}
@ -356,7 +349,7 @@ private fun LexiconDetailPreview() {
description = "Brulkhai, ou plus simplement Bru, est solidement bâti. Elle mesure 192 cm pour 110 kg de muscles lorsquelle est en bonne santé. Elle a les cheveux châtains, les yeux noisettes et la peau couleur gris-vert typique de son espèce. Dun tempérament taciturne, elle parle peu et de façon concise. Elle est parfois brutale, aussi bien physiquement que verbalement, Elle ne prend cependant aucun plaisir à malmener ceux quelle considère plus faibles quelle. Dune nature simple et honnête, elle ne mâche pas ses mots et ne dissimule généralement pas ses pensées. Son intelligence modeste est plus le reflet dun manque déducation et dune capacité limitée à gérer ses émotions quà une débilité congénitale. Elle voue à la force un culte car cest par son expression quelle se sent vraiment vivante et éprouve de grandes difficultés vis à vis de ceux quelle nomme foshnu (bébé, chouineur en commun).",
history = null,
tags = "protagoniste, brute",
search = "Bru",
search = null,
highlightGender = true,
highlightRace = true,
)

View file

@ -39,6 +39,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
@ -104,7 +105,9 @@ fun LocationDetail(
val scope = rememberCoroutineScope()
val scroll = rememberScrollState()
val pager = rememberPagerState()
val pager = rememberPagerState(
pageCount = { viewModel.location.value.marquees.size },
)
val fantasy = rememberFantasyMapState()
val snapBehavior = rememberSnapConnection(scrollState = scroll)
val scrollBehavior = rememberScrollConnection(scrollState = scroll)
@ -114,7 +117,7 @@ fun LocationDetail(
val location = rememberAnnotation(item = viewModel.location)
val snackJob = remember { mutableStateOf<Job?>(null) }
val mapHighlight = remember { mutableStateOf(Offset.Unspecified) }
val selectedIndex = remember { mutableStateOf(0) }
val selectedIndex = remember { mutableIntStateOf(0) }
Surface {
LocationContent(
@ -383,7 +386,6 @@ private fun LocationContent(
.nestedScroll(connection),
state = pagerState,
verticalAlignment = Alignment.Top,
pageCount = item.value.marquees.size,
contentPadding = PaddingValues(all = 16.dp),
pageSpacing = 16.dp,
) {
@ -511,7 +513,7 @@ private fun LocationPreview() {
modifier = Modifier.fillMaxSize(),
connection = remember { object : NestedScrollConnection {} },
scrollState = rememberScrollState(),
pagerState = rememberPagerState(),
pagerState = rememberPagerState(pageCount = { 2 }),
fantasyMapState = rememberFantasyMapState(),
item = rememberAnnotation(item = remember {
mutableStateOf(

View file

@ -3,6 +3,9 @@ package com.pixelized.rplexicon.ui.screens.quest.list
import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize

View file

@ -1,20 +1,18 @@
package com.pixelized.rplexicon.ui.theme.animation
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Stable
@Stable
@OptIn(ExperimentalAnimationApi::class)
data class LexiconAnimation constructor(
val itemList: AnimatedContentScope<Boolean>.() -> ContentTransform,
val itemList: AnimatedContentTransitionScope<*>.() -> ContentTransform,
)
@OptIn(ExperimentalAnimationApi::class)
@Stable
fun lexiconAnimation(): LexiconAnimation = LexiconAnimation(
itemList = { fadeIn() with fadeOut() },
itemList = { fadeIn() togetherWith fadeOut() },
)

View file

@ -34,7 +34,7 @@ fun Regex?.annotatedSpan(
}?.toList() ?: emptyList()
}
fun Regex.annotatedString(
fun Regex?.annotatedString(
input: String,
startIndex: Int = 0,
spanStyle: SpanStyle