From 20188c0b6648191f72ea3aff7811d1d9a2521c38 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Mon, 3 Jan 2022 16:46:44 +0100 Subject: [PATCH] Added complete navigation system, added settings page and splitted the code to be easier to understand --- .idea/misc.xml | 7 + app/build.gradle | 1 + .../jarvis/android/MainActivity.kt | 192 ++---------------- .../jarvis/android/nav/Navigation.kt | 33 +++ .../jarvis/android/nav/Screen.kt | 6 + .../jarvis/android/pages/MainPage.kt | 138 +++++++++++++ .../jarvis/android/pages/SettingsPage.kt | 57 ++++++ .../jarvis/android/utils/Messages.kt | 70 +++++++ .../jarvis/android/utils/Utils.kt | 23 +++ .../drawable/ic_baseline_arrow_back_24.xml | 11 + 10 files changed, 363 insertions(+), 175 deletions(-) create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Navigation.kt create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Screen.kt create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/pages/MainPage.kt create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/pages/SettingsPage.kt create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Messages.kt create mode 100644 app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Utils.kt create mode 100644 app/src/main/res/drawable/ic_baseline_arrow_back_24.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 5c7a865..ba93dbf 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -18,6 +18,13 @@ + + + + + + + diff --git a/app/build.gradle b/app/build.gradle index 3d4fb63..c7c56f8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,7 @@ dependencies { implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation "androidx.navigation:navigation-compose:2.4.0-rc01" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' implementation 'androidx.activity:activity-compose:1.4.0' testImplementation 'junit:junit:4.13.2' diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/MainActivity.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/MainActivity.kt index 384f4df..cd68a76 100644 --- a/app/src/main/java/ch/mathieubroillet/jarvis/android/MainActivity.kt +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/MainActivity.kt @@ -4,30 +4,29 @@ import android.os.Bundle import android.view.WindowManager import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.DpOffset -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat +import androidx.navigation.compose.rememberNavController +import ch.mathieubroillet.jarvis.android.nav.Navigation +import ch.mathieubroillet.jarvis.android.pages.DisplayMainPage import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme -import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont -import ch.mathieubroillet.jarvis.android.utils.IconAlertDialogTextField + class MainActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + WindowCompat.setDecorFitsSystemWindows(window, false) window.setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, @@ -35,6 +34,7 @@ class MainActivity : ComponentActivity() { ) setContent { + // Fix the status & navigation bars staying white when white theme is on with activity in fullscreen val wic = WindowInsetsControllerCompat(window, window.decorView) wic.isAppearanceLightStatusBars = !isSystemInDarkTheme() @@ -47,176 +47,18 @@ class MainActivity : ComponentActivity() { .fillMaxWidth() .fillMaxHeight() ) { - //TODO: check if this is okay??? - DefaultPreview() + Navigation() } } } } } -var messageScroll: ScrollState? = null - -//Draws the base of the main activity, that includes the 3-dots menu and the "hi text". -@Composable -fun Base() { - var expanded by remember { mutableStateOf(false) } - - Column(Modifier.padding(bottom = 25.dp)) { - Row(Modifier.align(Alignment.End)) { - - IconAlertDialogTextField( - R.drawable.ic_baseline_keyboard_24, - "Demandez-moi quelque chose", - "Entrez une phrase" - ) - - IconButton(onClick = { expanded = true }) { - Icon( - painter = painterResource(id = R.drawable.ic_baseline_more_vert_24), - contentDescription = "3 dots button" - ) - } - - - DropdownMenu( - expanded = expanded, - onDismissRequest = { expanded = false }, - offset = DpOffset((-500).dp, 0.dp) - ) { - DropdownMenuItem(onClick = { /* Handle refresh! */ }) { - Text("Effacer la conversation") - } - DropdownMenuItem(onClick = { /* Handle settings! */ }) { - Text("Paramètres") - } - Divider() - DropdownMenuItem(onClick = { /* Handle send feedback! */ }) { - Text("Signaler un problème") - } - } - } - - Text( - text = "Bonjour, comment puis-je vous aider ?", - fontFamily = productSansFont, - fontSize = 30.sp, - modifier = Modifier.padding(top = 30.dp) - ) - } -} - -@Composable -fun RecordFloatingButton() { - //We create a row that we align to the bottom center of the parent box - Row( - Modifier - .fillMaxWidth(), - verticalAlignment = Alignment.Bottom, - horizontalArrangement = Arrangement.Center - ) { - //Microphone floating button to manually start/stop listening - FloatingActionButton(onClick = { /*TODO*/ }, modifier = Modifier.size(70.dp)) { - Icon( - painter = painterResource(id = R.drawable.ic_baseline_mic_24), - contentDescription = "microphone" - ) - } - } -} - -@Composable -fun MessageFromJarvis(text: String) { - //We create a row to contain the message and the robot image (to look like an sms) - Row(Modifier.padding(bottom = 25.dp)) { - - // Adding the robot image as the sender - Image( - painter = painterResource(id = R.drawable.robot256), - contentDescription = "robot", - Modifier - .size(50.dp) - .padding(end = 10.dp) - ) - - // Adding the message box with the text given in the params - Box( - modifier = Modifier - .fillMaxWidth(fraction = 0.9F) - .clip(RoundedCornerShape(15.dp)) - .background(color = MaterialTheme.colors.secondaryVariant) - .padding(horizontal = 10.dp, vertical = 5.dp) - ) { - Text(text = text, fontFamily = productSansFont) - } - } -} - -@Composable -fun MessageFromUser(text: String) { - //We create a row to contain the user message and we align the row to the right side (to look like a conversation between two people) - Row( - Modifier - .padding(bottom = 25.dp) - .fillMaxWidth(), horizontalArrangement = Arrangement.End - ) { - // The message box with the text - Box( - modifier = Modifier - .fillMaxWidth(fraction = 0.8F) - .clip(RoundedCornerShape(15.dp)) - .background(color = MaterialTheme.colors.secondary) - .padding(horizontal = 10.dp, vertical = 5.dp) - ) { - Text( - text = text, - fontFamily = productSansFont, - color = if (!isSystemInDarkTheme()) Color.White else Color(15, 15, 15, 255) - ) - } - } -} - @Preview(showBackground = true) @Composable fun DefaultPreview() { JarvisComposeTheme { - //We create a main box with basic padding to avoid having stuff too close to every side. - Box( - Modifier - .fillMaxHeight() - .fillMaxWidth() - .padding(horizontal = 15.dp) - .padding(top = 45.dp, bottom = 10.dp) - ) { - - // This column regroup the base and all the conversations (everything except the footer) - Column(Modifier.padding(bottom = 80.dp)) { - Base() - - messageScroll = rememberScrollState() - // This column regroup only the conversations and make them scrollable - - LazyColumn(content = { - item { - // Basic interaction stuff for demo - MessageFromJarvis(text = "Salut, je suis Jarvis! \nPose moi une question et je ferais de mon mieux pour te renseigner.") - MessageFromUser(text = "Quel temps fait-il à Paris en ce moment ?") - MessageFromJarvis(text = "A Paris, il fait actuellement 10 degrés et le ciel est nuageux.") - } - }) - } - - - // Finally we add the footer to the bottom center of the main box - Column( - Modifier - .align(Alignment.BottomCenter) - .padding(bottom = 40.dp) - ) { - RecordFloatingButton() - } - } + DisplayMainPage(rememberNavController()) } } \ No newline at end of file diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Navigation.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Navigation.kt new file mode 100644 index 0000000..6bc6c12 --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Navigation.kt @@ -0,0 +1,33 @@ +package ch.mathieubroillet.jarvis.android.nav + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import ch.mathieubroillet.jarvis.android.pages.DisplayMainPage +import ch.mathieubroillet.jarvis.android.pages.DisplaySettingsPage + +@Composable +fun Navigation() { + val navController = rememberNavController() + NavHost(navController = navController, startDestination = Screen.MainScreen.route) { + composable(route = Screen.MainScreen.route) { + MainScreen(navController = navController) + } + composable(route = Screen.SettingsScreen.route) { + SettingsScreen(navController = navController) + } + } + +} + +@Composable +fun MainScreen(navController: NavController) { + DisplayMainPage(navController) +} + +@Composable +fun SettingsScreen(navController: NavController) { + DisplaySettingsPage(navController) +} \ No newline at end of file diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Screen.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Screen.kt new file mode 100644 index 0000000..7c710a8 --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/nav/Screen.kt @@ -0,0 +1,6 @@ +package ch.mathieubroillet.jarvis.android.nav + +sealed class Screen(val route: String){ + object MainScreen : Screen("main_screen") + object SettingsScreen : Screen("settings_screen") +} \ No newline at end of file diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/MainPage.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/MainPage.kt new file mode 100644 index 0000000..93564c1 --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/MainPage.kt @@ -0,0 +1,138 @@ +package ch.mathieubroillet.jarvis.android.pages + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController +import ch.mathieubroillet.jarvis.android.R +import ch.mathieubroillet.jarvis.android.nav.Screen +import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme +import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont +import ch.mathieubroillet.jarvis.android.utils.DefaultBox +import ch.mathieubroillet.jarvis.android.utils.IconAlertDialogTextField +import ch.mathieubroillet.jarvis.android.utils.MessageFromJarvis +import ch.mathieubroillet.jarvis.android.utils.MessageFromUser + + +//Draws the base of the main activity, that includes the 3-dots menu and the "hi text". +@Composable +fun Base(navController: NavController) { + + Column(Modifier.padding(bottom = 25.dp)) { + Row(Modifier.align(Alignment.End)) { + + IconAlertDialogTextField( + R.drawable.ic_baseline_keyboard_24, + "Demandez-moi quelque chose", + "Entrez une phrase" + ) + + DropDownSettingsMenu(navController) + } + + Text( + text = "Bonjour, comment puis-je vous aider ?", + fontFamily = productSansFont, + fontSize = 30.sp, + modifier = Modifier.padding(top = 30.dp) + ) + } +} + +@Composable +fun DropDownSettingsMenu(navController: NavController) { + var expanded by remember { mutableStateOf(false) } + + IconButton(onClick = { expanded = true }) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_more_vert_24), + contentDescription = "3 dots button" + ) + } + + + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + offset = DpOffset((-500).dp, 0.dp) + ) { + DropdownMenuItem(onClick = { /* Handle refresh! */ }) { + Text("Effacer la conversation") + } + DropdownMenuItem(onClick = { navController.navigate(Screen.SettingsScreen.route) }) { + Text("Paramètres") + } + Divider() + DropdownMenuItem(onClick = { /* Handle send feedback! */ }) { + Text("Signaler un problème") + } + } +} + +@Composable +fun StartRecordingFAB() { + //We create a row that we align to the bottom center of the parent box + Row( + Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.Center + ) { + //Microphone floating button to manually start/stop listening + FloatingActionButton(onClick = { /*TODO*/ }, modifier = Modifier.size(70.dp)) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_mic_24), + contentDescription = "microphone" + ) + } + } +} + +@Composable +fun DisplayMainPage(navController: NavController) { + //We create a main box with basic padding to avoid having stuff too close to every side. + DefaultBox { + + // This column regroup the base and all the conversations (everything except the footer) + Column(Modifier.padding(bottom = 80.dp)) { + Base(navController) + + // This column regroup only the conversations and make them scrollable + LazyColumn(content = { + item { + // Basic interaction stuff for demo + MessageFromJarvis(text = "Salut, je suis Jarvis! \nPose moi une question et je ferais de mon mieux pour te renseigner.") + MessageFromUser(text = "Quel temps fait-il à Paris en ce moment ?") + MessageFromJarvis(text = "A Paris, il fait actuellement 10 degrés et le ciel est nuageux.") + } + }) + } + + // Finally we add the footer to the bottom center of the main box + Column( + Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 40.dp) + ) { + StartRecordingFAB() + } + } +} + + +@Preview(showBackground = true) +@Composable +fun MainPagePreview() { + JarvisComposeTheme { + DisplayMainPage(rememberNavController()) + } +} \ No newline at end of file diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/SettingsPage.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/SettingsPage.kt new file mode 100644 index 0000000..a2b76b9 --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/pages/SettingsPage.kt @@ -0,0 +1,57 @@ +package ch.mathieubroillet.jarvis.android.pages + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import androidx.navigation.compose.rememberNavController +import ch.mathieubroillet.jarvis.android.R +import ch.mathieubroillet.jarvis.android.nav.Screen +import ch.mathieubroillet.jarvis.android.ui.theme.JarvisComposeTheme +import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont +import ch.mathieubroillet.jarvis.android.utils.DefaultBox + + +@Composable +fun DisplaySettingsPage(navController: NavController) { + DefaultBox { + SettingsBase(navController) + } +} + +@Composable +fun SettingsBase(navController: NavController) { + Column(Modifier.padding(bottom = 25.dp)) { + Row { + IconButton(onClick = { navController.navigate(Screen.MainScreen.route) }) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = "back button" + ) + } + } + Text( + text = "Paramètres", + fontFamily = productSansFont, + fontSize = 30.sp, + modifier = Modifier.padding(top = 30.dp) + ) + } +} + +@Preview(showBackground = true) +@Composable +fun SettingsPagePreview() { + JarvisComposeTheme { + DisplaySettingsPage(rememberNavController()) + } +} \ No newline at end of file diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Messages.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Messages.kt new file mode 100644 index 0000000..036bddf --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Messages.kt @@ -0,0 +1,70 @@ +package ch.mathieubroillet.jarvis.android.utils + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import ch.mathieubroillet.jarvis.android.R +import ch.mathieubroillet.jarvis.android.ui.theme.productSansFont + + +@Composable +fun MessageFromJarvis(text: String) { + //We create a row to contain the message and the robot image (to look like an sms) + Row(Modifier.padding(bottom = 25.dp)) { + + // Adding the robot image as the sender + Image( + painter = painterResource(id = R.drawable.robot256), + contentDescription = "robot", + Modifier + .size(50.dp) + .padding(end = 10.dp) + ) + + // Adding the message box with the text given in the params + Box( + modifier = Modifier + .fillMaxWidth(fraction = 0.9F) + .clip(RoundedCornerShape(15.dp)) + .background(color = MaterialTheme.colors.secondaryVariant) + .padding(horizontal = 10.dp, vertical = 5.dp) + ) { + Text(text = text, fontFamily = productSansFont) + } + } +} + +@Composable +fun MessageFromUser(text: String) { + //We create a row to contain the user message and we align the row to the right side (to look like a conversation between two people) + Row( + Modifier + .padding(bottom = 25.dp) + .fillMaxWidth(), horizontalArrangement = Arrangement.End + ) { + // The message box with the text + Box( + modifier = Modifier + .fillMaxWidth(fraction = 0.8F) + .clip(RoundedCornerShape(15.dp)) + .background(color = MaterialTheme.colors.secondary) + .padding(horizontal = 10.dp, vertical = 5.dp) + ) { + Text( + text = text, + fontFamily = productSansFont, + color = if (!isSystemInDarkTheme()) Color.White else Color(15, 15, 15, 255) + ) + } + } +} diff --git a/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Utils.kt b/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Utils.kt new file mode 100644 index 0000000..f7326d1 --- /dev/null +++ b/app/src/main/java/ch/mathieubroillet/jarvis/android/utils/Utils.kt @@ -0,0 +1,23 @@ +package ch.mathieubroillet.jarvis.android.utils + +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + + +@Composable +fun DefaultBox( + content: @Composable() (BoxScope.() -> Unit) +) { + Box( + Modifier + .fillMaxHeight() + .fillMaxWidth() + .padding(horizontal = 15.dp) + .padding(top = 45.dp, bottom = 10.dp) + ) { + content() + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml new file mode 100644 index 0000000..2a31b2e --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml @@ -0,0 +1,11 @@ + + +