Disable search fab and add a skeleton of search screen.

This commit is contained in:
Andres Gomez, Thomas (ITDV CC) - AF (ext) 2023-07-16 17:52:19 +02:00
parent 54e09e5f1d
commit 70aa2a7972
15 changed files with 296 additions and 49 deletions

View file

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.pixelized.rplexicon",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "0.1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

View file

@ -23,12 +23,7 @@ class AuthenticationRepository @Inject constructor(
val credential: GoogleAccountCredential
get() {
val credential = GoogleAccountCredential
.usingOAuth2(
context, listOf(
SheetsScopes.SPREADSHEETS,
SheetsScopes.SPREADSHEETS_READONLY,
)
)
.usingOAuth2(context, capabilities)
.setBackOff(ExponentialBackOff())
credential.selectedAccount = signInCredential.value?.let {
@ -43,4 +38,11 @@ class AuthenticationRepository @Inject constructor(
) {
signInCredential.value = credential
}
companion object {
private val capabilities = listOf(
// SheetsScopes.SPREADSHEETS,
SheetsScopes.SPREADSHEETS_READONLY,
)
}
}

View file

@ -95,16 +95,16 @@ class LexiconRepository @Inject constructor(
Lexicon(
id = index,
name = name,
diminutive = diminutive,
diminutive = diminutive?.takeIf { it.isNotBlank() },
gender = when (gender) {
"Male" -> Lexicon.Gender.MALE
"Femelle" -> Lexicon.Gender.FEMALE
else -> Lexicon.Gender.UNDETERMINED
},
race = race,
race = race?.takeIf { it.isNotBlank() },
portrait = portrait?.split("\n")?.mapNotNull { it.toUriOrNull() } ?: emptyList(),
description = description,
history = history,
description = description?.takeIf { it.isNotBlank() },
history = history?.takeIf { it.isNotBlank() },
)
} else {
null
@ -119,7 +119,7 @@ class LexiconRepository @Inject constructor(
}
private fun String?.toUriOrNull(): Uri? = try {
this?.toUri()
this?.takeIf { it.isNotBlank() }?.toUri()
} catch (_: Exception) {
null
}

View file

@ -9,6 +9,11 @@ import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import com.pixelized.rplexicon.ui.navigation.screens.AUTHENTICATION_ROUTE
import com.pixelized.rplexicon.ui.navigation.screens.composableAuthentication
import com.pixelized.rplexicon.ui.navigation.screens.composableCharacterDetail
import com.pixelized.rplexicon.ui.navigation.screens.composableLexicon
import com.pixelized.rplexicon.ui.navigation.screens.composableSearch
val LocalScreenNavHost = staticCompositionLocalOf<NavHostController> {
error("LocalScreenNavHost not ready")
@ -32,12 +37,11 @@ fun ScreenNavHost(
composableAuthentication()
composableLexicon(lazyListState = lexiconListState)
composableCharacterDetail()
composableSearch()
}
}
}
fun defaultOption(): NavOptionsBuilder.() -> Unit = { }
fun rootOption(): NavOptionsBuilder.() -> Unit = {
launchSingleTop = true
restoreState = true

View file

@ -1,8 +1,10 @@
package com.pixelized.rplexicon.ui.navigation
package com.pixelized.rplexicon.ui.navigation.screens
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
import com.pixelized.rplexicon.ui.navigation.animatedComposable
import com.pixelized.rplexicon.ui.screens.authentication.AuthenticationScreen
private const val ROUTE = "authentication"

View file

@ -1,4 +1,4 @@
package com.pixelized.rplexicon.ui.navigation
package com.pixelized.rplexicon.ui.navigation.screens
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
@ -8,6 +8,8 @@ import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
import com.pixelized.rplexicon.ui.navigation.animatedComposable
import com.pixelized.rplexicon.ui.screens.detail.CharacterDetailScreen
import com.pixelized.rplexicon.utilitary.extentions.ARG

View file

@ -1,10 +1,11 @@
package com.pixelized.rplexicon.ui.navigation
package com.pixelized.rplexicon.ui.navigation.screens
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
import com.pixelized.rplexicon.ui.navigation.animatedComposable
import com.pixelized.rplexicon.ui.screens.lexicon.LexiconScreen
private const val ROUTE = "lexicon"

View file

@ -0,0 +1,27 @@
package com.pixelized.rplexicon.ui.navigation.screens
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptionsBuilder
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
import com.pixelized.rplexicon.ui.navigation.animatedComposable
import com.pixelized.rplexicon.ui.screens.search.SearchScreen
private const val ROUTE = "search"
const val SEARCH_ROUTE = ROUTE
fun NavGraphBuilder.composableSearch() {
animatedComposable(
route = SEARCH_ROUTE,
animation = NavigationAnimation.Push,
) {
SearchScreen()
}
}
fun NavHostController.navigateToSearch(
option: NavOptionsBuilder.() -> Unit = {},
) {
navigate(route = ROUTE, builder = option)
}

View file

@ -30,7 +30,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.rplexicon.LocalActivity
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.navigateToLexicon
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLexicon
import com.pixelized.rplexicon.ui.navigation.rootOption
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.ui.theme.colors.GoogleColorPalette

View file

@ -175,13 +175,13 @@ private fun CharacterDetailScreenContent(
modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
item.value.race?.let {
item.value.gender?.let {
Text(
style = remember { typography.labelMedium.copy(fontStyle = FontStyle.Italic) },
text = it,
)
}
item.value.gender?.let {
item.value.race?.let {
Text(
style = remember { typography.labelMedium.copy(fontStyle = FontStyle.Italic) },
text = it,

View file

@ -6,7 +6,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import com.pixelized.rplexicon.model.Lexicon
import com.pixelized.rplexicon.repository.LexiconRepository
import com.pixelized.rplexicon.ui.navigation.characterDetailArgument
import com.pixelized.rplexicon.ui.navigation.screens.characterDetailArgument
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -21,11 +21,11 @@ class CharacterDetailViewModel @Inject constructor(
val source = repository.data.value[savedStateHandle.characterDetailArgument.id]
return CharacterDetailUio(
name = source.name,
diminutive = source.diminutive?.takeIf { it.isNotBlank() }?.let { "./ $it" },
diminutive = source.diminutive?.let { "./ $it" },
gender = when (source.gender) {
Lexicon.Gender.MALE -> "homme"
Lexicon.Gender.FEMALE -> "femme"
Lexicon.Gender.UNDETERMINED -> "inconnu"
Lexicon.Gender.MALE -> "Male"
Lexicon.Gender.FEMALE -> "Femelle"
Lexicon.Gender.UNDETERMINED -> "Inconnu"
},
race = source.race,
portrait = source.portrait,

View file

@ -48,7 +48,8 @@ import com.pixelized.rplexicon.LocalSnack
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.composable.FloatingActionButton
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.navigateToCharacterDetail
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterDetail
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSearch
import com.pixelized.rplexicon.ui.screens.lexicon.LexiconErrorUio.Default
import com.pixelized.rplexicon.ui.screens.lexicon.LexiconErrorUio.Permission
import com.pixelized.rplexicon.ui.theme.LexiconTheme
@ -96,7 +97,7 @@ fun LexiconScreen(
refreshing = viewModel.isLoading,
isFabExpended = isFabExpended,
onSearch = {
screen.navigateToSearch()
},
onItem = {
screen.navigateToCharacterDetail(id = it.id)
@ -134,26 +135,26 @@ private fun LexiconScreenContent(
)
},
floatingActionButton = {
FloatingActionButton(
modifier = Modifier.padding(start = 32.dp),
expended = isFabExpended.value,
onClick = onSearch,
icon = {
Icon(
tint = MaterialTheme.colorScheme.onPrimary,
painter = painterResource(id = R.drawable.ic_baseline_search_24),
contentDescription = null,
)
},
text = {
val typography = MaterialTheme.typography
Text(
color = MaterialTheme.colorScheme.onPrimary,
style = remember { typography.bodyLarge.copy(fontWeight = FontWeight.Bold) },
text = "Rechercher",
)
},
)
// FloatingActionButton(
// modifier = Modifier.padding(start = 32.dp),
// expended = isFabExpended.value,
// onClick = onSearch,
// icon = {
// Icon(
// tint = MaterialTheme.colorScheme.onPrimary,
// painter = painterResource(id = R.drawable.ic_baseline_search_24),
// contentDescription = null,
// )
// },
// text = {
// val typography = MaterialTheme.typography
// Text(
// color = MaterialTheme.colorScheme.onPrimary,
// style = remember { typography.bodyLarge.copy(fontWeight = FontWeight.Bold) },
// text = "Rechercher",
// )
// },
// )
}
) {
Box(
@ -167,7 +168,7 @@ private fun LexiconScreenContent(
state = lazyColumnState,
contentPadding = PaddingValues(
top = 8.dp,
bottom = 8.dp + 16.dp + 56.dp + 16.dp
bottom = 8.dp + 16.dp // + 56.dp + 16.dp,
),
) {
items(items = items.value) { item ->

View file

@ -37,7 +37,7 @@ class LexiconViewModel @Inject constructor(
name = item.name,
diminutive = item.diminutive?.takeIf { it.isNotBlank() }?.let { "./ $it" },
gender = when (item.gender) {
Lexicon.Gender.MALE -> "h."
Lexicon.Gender.MALE -> "m."
Lexicon.Gender.FEMALE -> "f."
Lexicon.Gender.UNDETERMINED -> "u."
},

View file

@ -0,0 +1,183 @@
package com.pixelized.rplexicon.ui.screens.search
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ExposedDropdownMenuBox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.theme.LexiconTheme
@Composable
fun SearchScreen() {
val screen = LocalScreenNavHost.current
Surface {
SearchScreenContent(
modifier = Modifier.fillMaxSize(),
onBack = {
screen.popBackStack()
}
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SearchScreenContent(
modifier: Modifier = Modifier,
onBack: () -> Unit,
) {
Scaffold(
modifier = modifier,
containerColor = Color.Transparent,
topBar = {
TopAppBar(
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_back_ios_new_24),
contentDescription = null
)
}
},
title = {
Text(text = "Rechercher")
},
)
},
) {
Column(
modifier = Modifier
.padding(paddingValues = it)
.padding(all = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
TextField(
modifier = Modifier.fillMaxWidth(),
value = "",
label = {
Text("Nom")
},
onValueChange = { _ -> },
colors = TextFieldDefaults.colors(
focusedContainerColor = MaterialTheme.colorScheme.surface,
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
),
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
DropDownField(
modifier = Modifier.weight(1f),
subject = remember { mutableStateOf("1") },
subjects = listOf("1", "2"),
onChange = { },
expanded = remember { mutableStateOf(false) },
onExpandedChange = { }
)
DropDownField(
modifier = Modifier.weight(1f),
subject = remember { mutableStateOf("1") },
subjects = listOf("1", "2"),
onChange = { },
expanded = remember { mutableStateOf(false) },
onExpandedChange = { }
)
}
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DropDownField(
modifier: Modifier = Modifier,
subjects: List<String>,
subject: State<String>,
onChange: (String) -> Unit,
expanded: State<Boolean>,
onExpandedChange: (Boolean) -> Unit
) {
ExposedDropdownMenuBox(
modifier = modifier,
expanded = expanded.value,
onExpandedChange = onExpandedChange,
) {
TextField(
modifier = Modifier.clickable { onExpandedChange(true) },
readOnly = true,
singleLine = true,
placeholder = {
Text(
text = "pouet"
)
},
trailingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_baseline_arrow_drop_down_24),
contentDescription = null,
)
},
colors = TextFieldDefaults.colors(
focusedContainerColor = MaterialTheme.colorScheme.surface,
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
),
value = subject.value,
onValueChange = {},
)
ExposedDropdownMenu(
expanded = expanded.value,
onDismissRequest = { onExpandedChange(false) },
) {
subjects.forEach {
DropdownMenuItem(
onClick = { onChange(it) },
content = { Text(text = it) },
)
}
}
}
}
@Composable
@Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES)
private fun SearchScreenContentPreview() {
LexiconTheme {
Surface {
SearchScreenContent(
modifier = Modifier.fillMaxSize(),
onBack = { },
)
}
}
}

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M7,10l5,5 5,-5z"/>
</vector>