From 42bd75a28f24ff3c3c126a65ee821db7c387d3ec Mon Sep 17 00:00:00 2001 From: samAricha Date: Fri, 9 Feb 2024 06:33:19 +0300 Subject: [PATCH 1/5] adding app state for the bottom navs but not working yet --- .../organiks_platform_android/MainActivity.kt | 5 - .../navigation/BottomBarRoutes.kt | 10 +- .../navigation/Screen.kt | 4 + .../navDrawer/NavigationDrawerM3.kt | 166 +++++++++--------- app/src/main/res/values/strings.xml | 4 + 5 files changed, 97 insertions(+), 92 deletions(-) diff --git a/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt b/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt index dfe2172..51d5525 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt @@ -45,11 +45,6 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) -// WindowCompat.setDecorFitsSystemWindows( -// window, -// false -// ) - Log.d("TAG1", "WORKINg") val isLoading = splashViewModel.isLoading.value diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt index a775d93..0ff6aa8 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt @@ -10,12 +10,10 @@ enum class BottomBarRoutes( val routes: String, @DrawableRes val icon: Int ) { - - HOME(1, R.string.homeRoute, "/home", R.drawable.home), - NOTIFICATION( + DASHBOARD(1, R.string.dashboard, Screen.Home.route, R.drawable.home), + PRODUCTION_HOME( 2, - R.string.notificationRoute, "/notification", R.drawable.monitoring + R.string.productionHome, Screen.ProductionHome.route, R.drawable.monitoring ), - Profile(3, R.string.profileRoute, "/profile", R.drawable.add_to_list) - + PRODUCTION_RECORDING(3, R.string.productionRecording, Screen.ProductionRecording.route, R.drawable.add_to_list) } \ No newline at end of file diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/Screen.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/Screen.kt index e6a51d1..1974fe5 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/Screen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/Screen.kt @@ -17,4 +17,8 @@ sealed class Screen(val route: String) { object AiSearchScreen: Screen(route = "ai_search_screen") object GeminiChatScreen: Screen(route = "gemini_chat_screen") object ProfileScreen: Screen(route = "profile_screen") + + object Splash : Screen("splash") + object BottomBar : Screen("bottombar") + object Detail : Screen("detail") } \ No newline at end of file diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt index 0d82bcc..413d21d 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt @@ -73,9 +73,11 @@ import teka.android.organiks_platform_android.R import teka.android.organiks_platform_android.ScaffoldContent import teka.android.organiks_platform_android.modules.auth.AuthViewModel import teka.android.organiks_platform_android.navigation.AppNavigationActions +import teka.android.organiks_platform_android.navigation.AppState import teka.android.organiks_platform_android.navigation.MainNavGraph import teka.android.organiks_platform_android.navigation.Screen import teka.android.organiks_platform_android.navigation.To_MAIN_GRAPH_ROUTE +import teka.android.organiks_platform_android.navigation.rememberAppState import teka.android.organiks_platform_android.ui.theme.LightPrimaryColor import teka.android.organiks_platform_android.ui.theme.NoShapes import teka.android.organiks_platform_android.ui.theme.PrimaryColor @@ -98,6 +100,8 @@ fun NavigationDrawerM3( val authViewModel: AuthViewModel = hiltViewModel() val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val scope = rememberCoroutineScope() + val appState = rememberAppState(navHostController) + val navigationActions = remember(navHostController) { AppNavigationActions(navHostController) @@ -111,13 +115,10 @@ fun NavigationDrawerM3( label = "Home", secondaryLabel = "64", onItemClick = { - // Define the action for the "Home" item here - // For example, navigate to the Home screen navigationActions.navigateToHome() scope.launch { drawerState.close() } - Toast.makeText(context, "This is a Home Toast. Yay!", Toast.LENGTH_SHORT).show() // navHostController.navigate(Screen.Home.route) } @@ -127,8 +128,6 @@ fun NavigationDrawerM3( label = "Notifications", secondaryLabel = "12", onItemClick = { - // Define the action for the "Notifications" item here - // For example, navigate to the Notifications screen Toast.makeText(context, "This is a Notifications Toast. Yay!", Toast.LENGTH_SHORT).show() // navHostController.navigate(Screen.ProductionHome.route) } @@ -245,7 +244,8 @@ fun NavigationDrawerM3( navHostController = navHostController, scaffoldState = scaffoldState, scope = scope, - onDrawerIconClick = { scope.launch { drawerState.open() } } + onDrawerIconClick = { scope.launch { drawerState.open() } }, + appState = appState ) } ) @@ -266,7 +266,8 @@ fun ScaffoldContent2( navHostController: NavHostController, scaffoldState: ScaffoldState, scope: CoroutineScope, - onDrawerIconClick: () -> Unit + onDrawerIconClick: () -> Unit, + appState: AppState ) { Scaffold( scaffoldState = scaffoldState, @@ -274,87 +275,90 @@ fun ScaffoldContent2( AppBar(onNavigationIconClick = onDrawerIconClick) }, bottomBar = { - BottomNavigation( - modifier = Modifier.height(52.dp), - backgroundColor = Color.White - ) { - val navBackStackEntry by navHostController.currentBackStackEntryAsState() - val currentRoute = navBackStackEntry?.destination?.route - - BottomNavigationItem( - selected = currentRoute == Screen.DashboardScreen.route, - onClick = { - navHostController.navigate(Screen.DashboardScreen.route) { - launchSingleTop = true +// if (appState.shouldShowBottomBar){ + BottomNavigation( + modifier = Modifier.height(52.dp), + backgroundColor = Color.White + ) { + val navBackStackEntry by appState.navHostController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route + + BottomNavigationItem( + selected = currentRoute == Screen.DashboardScreen.route, + onClick = { + navHostController.navigate(Screen.DashboardScreen.route) { + launchSingleTop = true + } + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(if (currentRoute == Screen.DashboardScreen.route) R.drawable.home else R.drawable.outline_home_24), + contentDescription = "Home", + modifier = Modifier.size(20.dp), + tint = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Home", + fontSize = 10.sp, + color = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray + ) } - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(if (currentRoute == Screen.DashboardScreen.route) R.drawable.home else R.drawable.outline_home_24), - contentDescription = "Home", - modifier = Modifier.size(20.dp), - tint = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Home", - fontSize = 10.sp, - color = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray - ) - } - ) + ) - BottomNavigationItem( - selected = currentRoute == Screen.ProductionHome.route, - onClick = { - navHostController.navigate(Screen.ProductionHome.route) { - launchSingleTop = true + BottomNavigationItem( + selected = currentRoute == Screen.ProductionHome.route, + onClick = { + navHostController.navigate(Screen.ProductionHome.route) { + launchSingleTop = true + } + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(R.drawable.monitoring), + contentDescription = "Records", + modifier = Modifier.size(20.dp), + tint = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Records", + fontSize = 10.sp, + color = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray + ) } - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(R.drawable.monitoring), - contentDescription = "Records", - modifier = Modifier.size(20.dp), - tint = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Records", - fontSize = 10.sp, - color = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray - ) - } - ) + ) + + BottomNavigationItem( + selected = currentRoute?.startsWith(Screen.ProductionRecording.route) == true, + onClick = { + navHostController.navigate(route = "${Screen.ProductionRecording.route}?id=-1") + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(R.drawable.add_to_list), + contentDescription = "Add Record", + modifier = Modifier.size(20.dp), + tint = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Add", + fontSize = 10.sp, + color = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray + ) + } + ) + } +// } - BottomNavigationItem( - selected = currentRoute?.startsWith(Screen.ProductionRecording.route) == true, - onClick = { - navHostController.navigate(route = "${Screen.ProductionRecording.route}?id=-1") - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(R.drawable.add_to_list), - contentDescription = "Add Record", - modifier = Modifier.size(20.dp), - tint = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Add", - fontSize = 10.sp, - color = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray - ) - } - ) - } } ) { Box(modifier = Modifier.padding(bottom = 60.dp)) { - MainNavGraph(navHostController) + MainNavGraph(appState.navHostController,) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aec4444..7fd28b4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,6 +8,10 @@ Notification Profile + ProductionHome + ProductionRecording + DashboardScreen + The password needs to consist of at least 8 characters The password needs to contain at least one letter and digit From 1f7fbf94f7d34436790e16c5b0ed4494517794ca Mon Sep 17 00:00:00 2001 From: samAricha Date: Sat, 10 Feb 2024 13:06:19 +0300 Subject: [PATCH 2/5] conditional display of bottom bar and the current screen remains selected in NavigationDrawer --- .../organiks_platform_android/MainActivity.kt | 1 + .../MainAppScreen.kt | 4 +- .../navigation/AppState.kt | 58 +++++- .../navigation/BottomBarRoutes.kt | 2 +- .../navigation/MainNavGraph.kt | 2 +- .../navigation/RootNavGraph.kt | 5 +- .../chat_screen/CustomBottomSearchBar.kt | 1 + .../aiadvice/chat_screen/GeminiChatScreen.kt | 16 +- .../presentation/dashborad/DashboardScreen.kt | 12 ++ .../navDrawer/NavigationDrawerM3.kt | 180 +++++++++--------- 10 files changed, 175 insertions(+), 106 deletions(-) diff --git a/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt b/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt index 51d5525..85fbff4 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/MainActivity.kt @@ -62,6 +62,7 @@ class MainActivity : ComponentActivity() { val startDestination by splashViewModel.startDestination startDestination?.let { RootNavGraph( +// appState = appState, navController = rememberNavController(), startDestination = it ) diff --git a/app/src/main/java/teka/android/organiks_platform_android/MainAppScreen.kt b/app/src/main/java/teka/android/organiks_platform_android/MainAppScreen.kt index ecb654e..998ea9b 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/MainAppScreen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/MainAppScreen.kt @@ -28,8 +28,8 @@ import teka.android.organiks_platform_android.ui.theme.PrimaryColor @RequiresApi(Build.VERSION_CODES.O) @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable -fun MainAppScreen() { - NavigationDrawerM3() +fun MainAppScreen(appState: AppState) { + NavigationDrawerM3(appState) } diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/AppState.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/AppState.kt index bb15aef..ed34df8 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/AppState.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/AppState.kt @@ -1,27 +1,71 @@ package teka.android.organiks_platform_android.navigation +import android.content.res.Resources +import androidx.compose.material.ScaffoldState +import androidx.compose.material.rememberScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.lifecycle.Lifecycle +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavDestination +import androidx.navigation.NavGraph import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import kotlinx.coroutines.CoroutineScope @Composable fun rememberAppState( - navHostController: NavHostController = rememberNavController() -) = remember(navHostController) { - AppState(navHostController) + scaffoldState: ScaffoldState = rememberScaffoldState(), + navHostController: NavHostController, + coroutineScope: CoroutineScope = rememberCoroutineScope() +) = remember(scaffoldState, navHostController, coroutineScope) { + AppState(scaffoldState, navHostController, coroutineScope) } @Stable class AppState( - val navHostController: NavHostController + val scaffoldState: ScaffoldState, + val navHostController: NavHostController, + coroutineScope: CoroutineScope ) { - - private val routes = BottomBarRoutes.values().map { it.routes } + private val bottomBarRoutes = BottomBarRoutes.values().map { it.routes } val shouldShowBottomBar: Boolean @Composable get() = - navHostController.currentBackStackEntryAsState().value?.destination?.route in routes + navHostController.currentBackStackEntryAsState().value?.destination?.route in bottomBarRoutes + + + val currentRoute: String? + get() = navHostController.currentDestination?.route + + fun upPress() { + navHostController.navigateUp() + } + + fun navigateToBottomBarRoute(route: String) { + if (route != currentRoute) { + navHostController.navigate(route) { + launchSingleTop = true + restoreState = true + popUpTo(findStartDestination(navHostController.graph).id) { + saveState = true + } + } + } + } +} + + +private fun NavBackStackEntry.lifecycleIsResumed() = + this.lifecycle.currentState == Lifecycle.State.RESUMED + +private val NavGraph.startDestination: NavDestination? + get() = findNode(startDestinationId) + +private tailrec fun findStartDestination(graph: NavDestination): NavDestination { + return if (graph is NavGraph) findStartDestination(graph.startDestination!!) else graph } \ No newline at end of file diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt index 0ff6aa8..d17fd8b 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/BottomBarRoutes.kt @@ -10,7 +10,7 @@ enum class BottomBarRoutes( val routes: String, @DrawableRes val icon: Int ) { - DASHBOARD(1, R.string.dashboard, Screen.Home.route, R.drawable.home), + DASHBOARD(1, R.string.dashboard, Screen.DashboardScreen.route, R.drawable.home), PRODUCTION_HOME( 2, R.string.productionHome, Screen.ProductionHome.route, R.drawable.monitoring diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/MainNavGraph.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/MainNavGraph.kt index 461063a..117f50d 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/MainNavGraph.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/MainNavGraph.kt @@ -21,7 +21,7 @@ import teka.android.organiks_platform_android.ui.animations.scaleOutOfContainer @Composable fun MainNavGraph( - navController: NavHostController = rememberNavController(), + navController: NavHostController, ) { NavHost( diff --git a/app/src/main/java/teka/android/organiks_platform_android/navigation/RootNavGraph.kt b/app/src/main/java/teka/android/organiks_platform_android/navigation/RootNavGraph.kt index 30ec80c..2f4bd4c 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/navigation/RootNavGraph.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/navigation/RootNavGraph.kt @@ -33,6 +33,9 @@ fun RootNavGraph( navController: NavHostController, startDestination: String = To_MAIN_GRAPH_ROUTE ) { + val appState = rememberAppState(navHostController = navController) + + NavHost(navController = navController, startDestination = startDestination, route = ROOT_GRAPH_ROUTE){ @@ -48,7 +51,7 @@ fun RootNavGraph( if (isLoggedInState != null) { if (isLoggedInState as Boolean) { - MainAppScreen() + MainAppScreen(appState) } else { LoginScreen(navController) } diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt index a6177cc..273865d 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt @@ -126,6 +126,7 @@ fun CustomBottomSearchBar( disabledContainerColor = Cream2, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, + cursorColor = SecondaryLightColor ), leadingIcon = { IconButton( diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt index a298374..1a11b37 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt @@ -1,9 +1,12 @@ package teka.android.organiks_platform_android.presentation.aiadvice.chat_screen +import android.annotation.SuppressLint +import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -18,6 +21,7 @@ import androidx.compose.runtime.mutableStateOf 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.LocalFocusManager import androidx.compose.ui.unit.dp @@ -30,6 +34,7 @@ import teka.android.organiks_platform_android.domain.models.ChatStatusModel import teka.android.organiks_platform_android.ui.theme.LightGreen import teka.android.organiks_platform_android.ui.theme.LightRed +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { val chatUiState = viewModel.uiState @@ -49,7 +54,7 @@ fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { modifier = Modifier .fillMaxWidth() .padding(horizontal = 10.dp) - .padding(bottom = 30.dp, top = 5.dp), + .padding(bottom = 15.dp, top = 5.dp), status = chatUiState.value.status, onSendClick = { text, images -> coroutineScope.launch(Dispatchers.IO) { @@ -74,10 +79,9 @@ fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { }, modifier = Modifier.pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) - }, - ) { paddingValues -> + } + ) { ChatList( - modifier = Modifier.padding(paddingValues), messages = chatUiState.value.messages ) @@ -107,7 +111,7 @@ fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { @Composable -fun ChatList(modifier: Modifier, messages: List) { +fun ChatList(messages: List) { val listState = rememberLazyListState() if (messages.isNotEmpty()) { @@ -117,7 +121,7 @@ fun ChatList(modifier: Modifier, messages: List) { } LazyColumn( state = listState, - modifier = modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/dashborad/DashboardScreen.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/dashborad/DashboardScreen.kt index caf183d..73cbb00 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/dashborad/DashboardScreen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/dashborad/DashboardScreen.kt @@ -80,6 +80,18 @@ fun DashboardScreen() { iconResId = teka.android.organiks_platform_android.R.drawable.baseline_sync_problem_24, color = Color(0xFFE57373) ) + DashboardCard( + title = "Not Backed up", + value = "$totalNotBackedUpCount Records", + iconResId = teka.android.organiks_platform_android.R.drawable.baseline_sync_problem_24, + color = Color(0xFFE57373) + ) + DashboardCard( + title = "Not Backed up", + value = "$totalNotBackedUpCount Records", + iconResId = teka.android.organiks_platform_android.R.drawable.baseline_sync_problem_24, + color = Color(0xFFE57373) + ) } } } diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt index 413d21d..a599b62 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/navDrawer/NavigationDrawerM3.kt @@ -93,6 +93,7 @@ import teka.android.organiks_platform_android.ui.widgets.CustomDialog @SuppressLint("CoroutineCreationDuringComposition") @Composable fun NavigationDrawerM3( + appState: AppState ) { val navHostController: NavHostController = rememberNavController() val context = LocalContext.current @@ -100,11 +101,11 @@ fun NavigationDrawerM3( val authViewModel: AuthViewModel = hiltViewModel() val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val scope = rememberCoroutineScope() - val appState = rememberAppState(navHostController) + val appState = rememberAppState(navHostController = navHostController) - val navigationActions = remember(navHostController) { - AppNavigationActions(navHostController) + val navigationActions = remember(appState.navHostController) { + AppNavigationActions(appState.navHostController) } val showDialog = remember { mutableStateOf(false) } @@ -114,6 +115,7 @@ fun NavigationDrawerM3( icon = Icons.Default.Home, label = "Home", secondaryLabel = "64", + route = Screen.DashboardScreen.route, onItemClick = { navigationActions.navigateToHome() scope.launch { @@ -127,6 +129,7 @@ fun NavigationDrawerM3( icon = Icons.Default.Notifications, label = "Notifications", secondaryLabel = "12", + route = null, onItemClick = { Toast.makeText(context, "This is a Notifications Toast. Yay!", Toast.LENGTH_SHORT).show() // navHostController.navigate(Screen.ProductionHome.route) @@ -136,6 +139,7 @@ fun NavigationDrawerM3( icon = Icons.Default.VoiceChat, label = "AiAssistant", secondaryLabel = "Chat", + route = Screen.GeminiChatScreen.route, onItemClick = { navigationActions.navigateToGeminichatScreen() scope.launch { @@ -148,6 +152,7 @@ fun NavigationDrawerM3( icon = Icons.Default.VideoLibrary, label = "Videos", secondaryLabel = "", + route = null, onItemClick = { Toast.makeText(context, "Videos Coming Soon!", Toast.LENGTH_SHORT).show() } @@ -156,6 +161,7 @@ fun NavigationDrawerM3( icon = Icons.Default.ExitToApp, label = "Log Out", secondaryLabel = "", + route = null, onItemClick = { scope.launch { drawerState.close() @@ -184,6 +190,8 @@ fun NavigationDrawerM3( drawerState = drawerState, gesturesEnabled = drawerState.isOpen, drawerContent = { + val navBackStackEntry by appState.navHostController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route ModalDrawerSheet( modifier = Modifier.width(280.dp), drawerContainerColor = Color.White, @@ -226,7 +234,7 @@ fun NavigationDrawerM3( label = { Text(text = item.label, fontFamily = ReemKufi) }, - selected = item == selectedItem, + selected = item.route == currentRoute, onClick = item.onItemClick, icon = { Icon(imageVector = item.icon, contentDescription = item.label)}, // badge = { Text(text = item.secondaryLabel)}, @@ -241,7 +249,7 @@ fun NavigationDrawerM3( }, content = { ScaffoldContent2( - navHostController = navHostController, + navHostController = appState.navHostController, scaffoldState = scaffoldState, scope = scope, onDrawerIconClick = { scope.launch { drawerState.open() } }, @@ -254,13 +262,14 @@ fun NavigationDrawerM3( data class DrawerItem( val icon: ImageVector, val label: String, + val route: String?, val secondaryLabel: String, val onItemClick: () -> Unit ) -@SuppressLint("UnusedMaterialScaffoldPaddingParameter") +@SuppressLint("UnusedMaterialScaffoldPaddingParameter", "UnusedMaterial3ScaffoldPaddingParameter") @Composable fun ScaffoldContent2( navHostController: NavHostController, @@ -275,96 +284,91 @@ fun ScaffoldContent2( AppBar(onNavigationIconClick = onDrawerIconClick) }, bottomBar = { -// if (appState.shouldShowBottomBar){ - BottomNavigation( - modifier = Modifier.height(52.dp), - backgroundColor = Color.White - ) { - val navBackStackEntry by appState.navHostController.currentBackStackEntryAsState() - val currentRoute = navBackStackEntry?.destination?.route - - BottomNavigationItem( - selected = currentRoute == Screen.DashboardScreen.route, - onClick = { - navHostController.navigate(Screen.DashboardScreen.route) { - launchSingleTop = true + if (appState.shouldShowBottomBar){ + BottomNavigation( + modifier = Modifier.height(52.dp), + backgroundColor = Color.White + ) { + val navBackStackEntry by appState.navHostController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route + + BottomNavigationItem( + selected = currentRoute == Screen.DashboardScreen.route, + onClick = { + navHostController.navigate(Screen.DashboardScreen.route) { + launchSingleTop = true + } + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(if (currentRoute == Screen.DashboardScreen.route) R.drawable.home else R.drawable.outline_home_24), + contentDescription = "Home", + modifier = Modifier.size(20.dp), + tint = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Home", + fontSize = 10.sp, + color = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray + ) } - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(if (currentRoute == Screen.DashboardScreen.route) R.drawable.home else R.drawable.outline_home_24), - contentDescription = "Home", - modifier = Modifier.size(20.dp), - tint = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Home", - fontSize = 10.sp, - color = if (currentRoute == Screen.DashboardScreen.route) PrimaryColor else Color.Gray - ) - } - ) + ) - BottomNavigationItem( - selected = currentRoute == Screen.ProductionHome.route, - onClick = { - navHostController.navigate(Screen.ProductionHome.route) { - launchSingleTop = true + BottomNavigationItem( + selected = currentRoute == Screen.ProductionHome.route, + onClick = { + navHostController.navigate(Screen.ProductionHome.route) { + launchSingleTop = true + } + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(R.drawable.monitoring), + contentDescription = "Records", + modifier = Modifier.size(20.dp), + tint = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Records", + fontSize = 10.sp, + color = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray + ) } - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(R.drawable.monitoring), - contentDescription = "Records", - modifier = Modifier.size(20.dp), - tint = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Records", - fontSize = 10.sp, - color = if (currentRoute == Screen.ProductionHome.route) PrimaryColor else Color.Gray - ) - } - ) + ) - BottomNavigationItem( - selected = currentRoute?.startsWith(Screen.ProductionRecording.route) == true, - onClick = { - navHostController.navigate(route = "${Screen.ProductionRecording.route}?id=-1") - }, - icon = { - androidx.compose.material.Icon( - painter = painterResource(R.drawable.add_to_list), - contentDescription = "Add Record", - modifier = Modifier.size(20.dp), - tint = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray - ) - }, - label = { - androidx.compose.material.Text( - text = "Add", - fontSize = 10.sp, - color = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray - ) - } - ) + BottomNavigationItem( + selected = currentRoute?.startsWith(Screen.ProductionRecording.route) == true, + onClick = { + navHostController.navigate(route = "${Screen.ProductionRecording.route}?id=-1") + }, + icon = { + androidx.compose.material.Icon( + painter = painterResource(R.drawable.add_to_list), + contentDescription = "Add Record", + modifier = Modifier.size(20.dp), + tint = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray + ) + }, + label = { + androidx.compose.material.Text( + text = "Add", + fontSize = 10.sp, + color = if (currentRoute?.startsWith(Screen.ProductionRecording.route) == true) PrimaryColor else Color.Gray + ) + } + ) + } } -// } - - } + }, ) { - Box(modifier = Modifier.padding(bottom = 60.dp)) { +// Box(modifier = Modifier.padding(bottom = 60.dp)) { MainNavGraph(appState.navHostController,) - } +// } } - - - - } From 98bd98c8f7027675eaf56c27fffb0c14f632d7ee Mon Sep 17 00:00:00 2001 From: samAricha Date: Sat, 10 Feb 2024 13:10:11 +0300 Subject: [PATCH 3/5] trying to setup the keyboard and search bar space --- .../aiadvice/chat_screen/GeminiChatScreen.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt index 1a11b37..224bae3 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt @@ -54,7 +54,7 @@ fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { modifier = Modifier .fillMaxWidth() .padding(horizontal = 10.dp) - .padding(bottom = 15.dp, top = 5.dp), + .padding(top = 5.dp), status = chatUiState.value.status, onSendClick = { text, images -> coroutineScope.launch(Dispatchers.IO) { @@ -77,13 +77,16 @@ fun GeminiChatScreen(viewModel: ChatViewModel = ChatViewModel()) { ) } }, - modifier = Modifier.pointerInput(Unit) { - detectTapGestures(onTap = { focusManager.clearFocus() }) - } + modifier = Modifier + .pointerInput(Unit) { + detectTapGestures(onTap = { focusManager.clearFocus() }) + } + .padding(bottom = 15.dp) ) { ChatList( messages = chatUiState.value.messages ) + Spacer(modifier = Modifier.height(15.dp)) if (showDialog.value) { CustomChatDialog( From 69ade04c5398524961e62c3e1f809f3c3de37240 Mon Sep 17 00:00:00 2001 From: samAricha Date: Mon, 12 Feb 2024 23:41:09 +0300 Subject: [PATCH 4/5] calling the glide for converting the images to bitmap on a background thread i.e dispatchers.IO --- .../aiadvice/chat_screen/CustomBottomSearchBar.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt index 273865d..42ac7f7 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt @@ -5,6 +5,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -32,6 +33,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -52,6 +54,9 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.bumptech.glide.Glide +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import teka.android.organiks_platform_android.domain.models.ChatStatusModel import teka.android.organiks_platform_android.ui.theme.Cream1 import teka.android.organiks_platform_android.ui.theme.Cream2 @@ -82,10 +87,14 @@ fun CustomBottomSearchBar( rememberLauncherForActivityResult( contract = ActivityResultContracts.PickMultipleVisualMedia(5) ) { uris -> - images.value = uris.mapNotNull { uri -> Glide.with(context).asBitmap().load(uri).submit().get() + scope.launch(Dispatchers.IO) { + images.value = uris.mapNotNull { uri -> + Glide.with(context).asBitmap().load(uri).submit().get() + } } } + Column { LazyRow { items(images.value.size) { index -> @@ -131,7 +140,9 @@ fun CustomBottomSearchBar( leadingIcon = { IconButton( onClick = { -// pickerLauncher.launch() + pickMultipleMedia.launch( + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) + ) }, content = { Icon( From 5cc3c09e4ef578bd39c0dea437cb76d13a314271 Mon Sep 17 00:00:00 2001 From: samAricha Date: Tue, 13 Feb 2024 00:51:11 +0300 Subject: [PATCH 5/5] update views and ui for GeminiChatScreen but still not displaying responses --- .../aiadvice/chat_screen/ChatUiState.kt | 1 - .../chat_screen/CustomBottomSearchBar.kt | 3 --- .../aiadvice/chat_screen/GeminiChatScreen.kt | 3 +++ .../chat_screen/components/MessageBubble.kt | 2 ++ .../components/MessageImagesStack.kt | 22 ++++++++++++------- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/ChatUiState.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/ChatUiState.kt index ebc4660..5ecdd8d 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/ChatUiState.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/ChatUiState.kt @@ -4,7 +4,6 @@ package teka.android.organiks_platform_android.presentation.aiadvice.chat_screen import teka.android.organiks_platform_android.domain.models.ChatMessageModel import teka.android.organiks_platform_android.domain.models.ChatStatusModel - data class ChatUiState( val messages: List = emptyList(), val status: ChatStatusModel = ChatStatusModel.Idle, diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt index 42ac7f7..e1f7307 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/CustomBottomSearchBar.kt @@ -68,9 +68,6 @@ import java.io.IOException import java.io.InputStream -/** - * TODO : allow sending attachments without text - */ @Composable fun CustomBottomSearchBar( modifier: Modifier = Modifier, diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt index 224bae3..c5ac309 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/GeminiChatScreen.kt @@ -128,6 +128,9 @@ fun ChatList(messages: List) { contentPadding = PaddingValues(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { + item{ + Spacer(modifier = Modifier.height(25.dp)) + } items(messages.size) { val message = messages[it] if (message.images.isNotEmpty()) { diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageBubble.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageBubble.kt index 0244030..a5bddd9 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageBubble.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageBubble.kt @@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageImagesStack.kt b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageImagesStack.kt index ed4afef..f7cc72b 100644 --- a/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageImagesStack.kt +++ b/app/src/main/java/teka/android/organiks_platform_android/presentation/aiadvice/chat_screen/components/MessageImagesStack.kt @@ -1,5 +1,6 @@ package teka.android.organiks_platform_android.presentation.aiadvice.chat_screen.components +import android.graphics.BitmapFactory import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationVector1D @@ -13,12 +14,15 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.scaleIn import androidx.compose.animation.slideInHorizontally import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults @@ -36,6 +40,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset @@ -77,14 +83,14 @@ fun MessageImagesStack( cardCount = message.images.size, cardShape = RoundedCornerShape(20.dp), cardContent = { index -> -// Image( -// bitmap = message.images[index].toImageBitmap(), -// contentDescription = "Same Card Type with Different Image", -// contentScale = ContentScale.Crop, -// modifier = Modifier -// .heightIn(100.dp, 300.dp) -// .widthIn(50.dp, 200.dp) -// ) + Image( + bitmap = BitmapFactory.decodeByteArray(message.images[index], 0, message.images[index].size).asImageBitmap(), + contentDescription = "Same Card Type with Different Image", + contentScale = ContentScale.Crop, + modifier = Modifier + .heightIn(100.dp, 300.dp) + .widthIn(50.dp, 200.dp) + ) }, orientation = Orientation.Horizontal( alignment = HorizontalAlignment.EndToStart,