From 300a09f26fd9a1ec2eff27c37131d3f6b2bcbdef Mon Sep 17 00:00:00 2001 From: Umair Khalid Date: Tue, 31 Jan 2023 22:34:35 +0500 Subject: [PATCH 1/8] Focusable textfield and button colors added --- .idea/deploymentTargetDropDown.xml | 2 +- .../login/withEmailPassword/LoginButton.kt | 62 +++++++++++ .../withEmailPassword/LoginScreenContent.kt | 101 +++--------------- .../login/withEmailPassword/ScreenHeading.kt | 19 ++++ .../login/withEmailPassword/TvTextField.kt | 60 +++++++++++ .../com/techlads/composetv/theme/Color.kt | 1 + build.gradle.kts | 2 - 7 files changed, 157 insertions(+), 90 deletions(-) create mode 100644 app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginButton.kt create mode 100644 app/src/main/java/com/techlads/composetv/login/withEmailPassword/ScreenHeading.kt create mode 100644 app/src/main/java/com/techlads/composetv/login/withEmailPassword/TvTextField.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 5119a61..45dd427 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -12,6 +12,6 @@ - + \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginButton.kt b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginButton.kt new file mode 100644 index 0000000..8b45513 --- /dev/null +++ b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginButton.kt @@ -0,0 +1,62 @@ +package com.techlads.composetv.login.withEmailPassword + +import androidx.compose.foundation.focusable +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.techlads.composetv.theme.AppTheme +import com.techlads.composetv.theme.LightBlue + +@Composable +fun LoginButton(onClick: () -> Unit) { + + val defaultColor = remember { + Color.White.copy(0.6F) + } + val selectedColor = remember { + LightBlue + } + val selectionColor = remember { mutableStateOf(defaultColor) } + + Box( + modifier = Modifier + .width(300.dp) + .padding(40.dp, 0.dp, 40.dp, 0.dp) + ) { + Button( + onClick = onClick, + shape = AppTheme.midShape, + colors = ButtonDefaults.buttonColors(selectionColor.value), + modifier = Modifier + .fillMaxWidth() + .height(50.dp) + .onFocusChanged { state -> + selectionColor.value = if (state.isFocused) { + selectedColor + } else { + defaultColor + } + } + .focusable(true) + ) { + Text( + text = "LOGIN", style = TextStyle( + color = Color.Black, + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Light + ) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginScreenContent.kt b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginScreenContent.kt index d80a1ee..cbaaa27 100644 --- a/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginScreenContent.kt +++ b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/LoginScreenContent.kt @@ -1,31 +1,16 @@ -@file:OptIn(ExperimentalMaterial3Api::class) package com.techlads.composetv.login.withEmailPassword -import androidx.compose.foundation.focusable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.techlads.composetv.theme.AppTheme - @Composable fun LoginPage( - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, onLoginClick: (user: String, psw: String) -> Unit ) { Column( @@ -34,83 +19,25 @@ fun LoginPage( horizontalAlignment = Alignment.CenterHorizontally, ) { - val username = remember { mutableStateOf(TextFieldValue("")) } - val password = remember { mutableStateOf(TextFieldValue("")) } - - Text( - text = "LOGIN", - style = TextStyle( - fontSize = 55.sp, fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Thin - ) - ) + val username = remember { mutableStateOf("") } + val password = remember { mutableStateOf("") } + ScreenHeading() Spacer(modifier = Modifier.height(20.dp)) - OutlinedTextField( - textStyle = TextStyle( - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Thin - ), - label = { Text(text = "Username") }, - value = username.value, - onValueChange = { username.value = it }, - modifier = Modifier - .onFocusChanged { state -> - if (state.isFocused) { - println("Username") - } - } - .focusable(true, interactionSource) - ) - + TvTextField(value = username.value, label = "Username") { + username.value = it + } Spacer(modifier = Modifier.height(20.dp)) - OutlinedTextField( - textStyle = TextStyle( - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Thin - ), - label = { Text(text = "Password") }, + TvTextField( value = password.value, + label = "Password", visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - onValueChange = { password.value = it }, - modifier = Modifier - .onFocusChanged { state -> - if (state.isFocused) { - println("password") - } - } - .focusable(true, interactionSource) - ) - + keyboardType = KeyboardType.Password + ) { password.value = it } Spacer(modifier = Modifier.height(40.dp)) - Box( - modifier = Modifier - .width(300.dp) - .padding(40.dp, 0.dp, 40.dp, 0.dp) - ) { - Button( - onClick = { onLoginClick(username.value.text, password.value.text) }, - shape = AppTheme.midShape, - colors = ButtonDefaults.buttonColors(Color.White), - modifier = Modifier - .fillMaxWidth() - .height(50.dp) - .onFocusChanged { state -> - if (state.isFocused) { - println("login") - } - } - .focusable(true, interactionSource) - ) { - Text( - text = "LOGIN", style = TextStyle( - color = Color.Black, - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Light - ) - ) - } + + LoginButton { + onLoginClick(username.value, password.value) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/techlads/composetv/login/withEmailPassword/ScreenHeading.kt b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/ScreenHeading.kt new file mode 100644 index 0000000..f926426 --- /dev/null +++ b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/ScreenHeading.kt @@ -0,0 +1,19 @@ +package com.techlads.composetv.login.withEmailPassword + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +@Composable +fun ScreenHeading() { + Text( + text = "LOGIN", style = TextStyle( + fontSize = 55.sp, + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Thin + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/login/withEmailPassword/TvTextField.kt b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/TvTextField.kt new file mode 100644 index 0000000..f2ee62a --- /dev/null +++ b/app/src/main/java/com/techlads/composetv/login/withEmailPassword/TvTextField.kt @@ -0,0 +1,60 @@ +package com.techlads.composetv.login.withEmailPassword + +import androidx.compose.foundation.focusable +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.VisualTransformation +import com.techlads.composetv.theme.LightBlue + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TvTextField( + value: String, + label: String, + visualTransformation: VisualTransformation = VisualTransformation.None, + keyboardType: KeyboardType = KeyboardType.Text, + onValueChange: (String) -> Unit +) { + val defaultColor = remember { + Color.White.copy(0.6F) + } + val selectedColor = remember { + LightBlue + } + val selectionColor = remember { mutableStateOf(defaultColor) } + + OutlinedTextField( + textStyle = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Thin + ), + colors = TextFieldDefaults.outlinedTextFieldColors( + unfocusedBorderColor = selectionColor.value, + unfocusedLabelColor = selectionColor.value + ), + label = { Text(text = label) }, + value = value, + visualTransformation = visualTransformation, + keyboardOptions = KeyboardOptions(keyboardType = keyboardType), + onValueChange = onValueChange, + modifier = Modifier + .onFocusChanged { state -> + selectionColor.value = if (state.isFocused) { + selectedColor + } else { + defaultColor + } + } + .focusable(true) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/theme/Color.kt b/app/src/main/java/com/techlads/composetv/theme/Color.kt index 9fb4636..050fcda 100644 --- a/app/src/main/java/com/techlads/composetv/theme/Color.kt +++ b/app/src/main/java/com/techlads/composetv/theme/Color.kt @@ -21,5 +21,6 @@ val Purple80 = Color(0xFFD0BCFF) val PurpleGrey80 = Color(0xFFCCC2DC) val Pink80 = Color(0xFFEFB8C8) val Neutral10 = Color(0xFF000000) +val LightBlue = Color(0xFF8FD3FE) val Gray20 = Color(0xFF222222) val Gray700 = Color(0xFF616161) diff --git a/build.gradle.kts b/build.gradle.kts index 24e80cc..8648e70 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,4 @@ buildscript { - val compose_version by extra("1.2.0-alpha05") - val wear_compose_version by extra("1.0.0-alpha18") repositories { gradlePluginPortal() google() From cf069fa8b80d2860d70679dbd210537a2bbba1bc Mon Sep 17 00:00:00 2001 From: Umair Khalid Date: Tue, 31 Jan 2023 22:35:40 +0500 Subject: [PATCH 2/8] jcenter repository added --- build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8648e70..05c9103 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,6 @@ buildscript { gradlePluginPortal() google() mavenCentral() - jcenter() maven { url = uri("https://jitpack.io") } } dependencies { @@ -16,7 +15,6 @@ allprojects { repositories { google() mavenCentral() - jcenter() maven { url = uri("https://jitpack.io") } } } From e9862ec2872265e3e5d3f50d8399e6162657faaa Mon Sep 17 00:00:00 2001 From: Umair Khalid Date: Wed, 1 Feb 2023 01:08:28 +0500 Subject: [PATCH 3/8] Exit confirmation dialog added --- app/build.gradle.kts | 2 + .../com/techlads/composetv/CustomDialogUI.kt | 128 ++++++++++++++++++ .../com/techlads/composetv/ExitAppDelegate.kt | 22 +++ .../com/techlads/composetv/LoginActivity.kt | 20 ++- app/src/main/res/drawable/ic_info.xml | 5 + 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/techlads/composetv/CustomDialogUI.kt create mode 100644 app/src/main/java/com/techlads/composetv/ExitAppDelegate.kt create mode 100644 app/src/main/res/drawable/ic_info.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 499f70d..431388b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -55,4 +55,6 @@ dependencies { implementation(libs.androidx.lifecycle.runtime) implementation(libs.androidx.navigation.compose) implementation(libs.qrcode) + implementation("androidx.compose.ui:ui-tooling-preview:1.3.3") + debugImplementation("androidx.compose.ui:ui-tooling:1.3.3") } \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/CustomDialogUI.kt b/app/src/main/java/com/techlads/composetv/CustomDialogUI.kt new file mode 100644 index 0000000..61034df --- /dev/null +++ b/app/src/main/java/com/techlads/composetv/CustomDialogUI.kt @@ -0,0 +1,128 @@ +package com.techlads.composetv + +import android.annotation.SuppressLint +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import com.techlads.composetv.theme.Gray20 +import com.techlads.composetv.theme.Gray700 +import com.techlads.composetv.theme.LightBlue + +@Composable +fun CustomDialog(openDialogCustom: MutableState, onExitClick: () -> Unit) { + Dialog(onDismissRequest = { openDialogCustom.value = false }) { + CustomDialogUI(openDialogCustom = openDialogCustom) { + onExitClick() + } + } +} + +//Layout +@Composable +fun CustomDialogUI( + modifier: Modifier = Modifier, + openDialogCustom: MutableState, + onExitClick: () -> Unit +) { + Card( + shape = RoundedCornerShape(10.dp), + modifier = Modifier.padding(10.dp, 5.dp, 10.dp, 10.dp), + ) { + Column(modifier.background(Color.White)) { + + //....................................................................... + Image( + painter = painterResource(id = R.drawable.ic_info), + contentDescription = null, // decorative + contentScale = ContentScale.Fit, + colorFilter = ColorFilter.tint( + color = LightBlue + ), + modifier = Modifier + .padding(top = 35.dp) + .height(70.dp) + .fillMaxWidth(), + + ) + + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "Confirmation", + textAlign = TextAlign.Center, + modifier = Modifier + .padding(top = 5.dp) + .fillMaxWidth(), + style = MaterialTheme.typography.labelLarge, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "Do you really want to exit app ?", + textAlign = TextAlign.Center, + modifier = Modifier + .padding(top = 10.dp, start = 25.dp, end = 25.dp) + .fillMaxWidth(), + style = MaterialTheme.typography.bodyMedium + ) + } + //....................................................................... + Row( + Modifier + .fillMaxWidth() + .padding(top = 10.dp) + .background(Gray20.copy(0.2F)), + ) { + TextButton(onClick = { + openDialogCustom.value = false + }, modifier = Modifier.weight(1F)) { + Text( + "No", + fontWeight = FontWeight.Bold, + color = Gray700, + modifier = Modifier.padding(top = 5.dp, bottom = 5.dp) + ) + } + + Divider( + Modifier + .height(50.dp) + .width(1.dp) + ) + + TextButton(onClick = { + openDialogCustom.value = false + onExitClick() + }, modifier = Modifier.weight(1F)) { + Text( + "Yes", + fontWeight = FontWeight.ExtraBold, + color = Color.Black, + modifier = Modifier.padding(top = 5.dp, bottom = 5.dp) + ) + } + } + } + } +} + + +@SuppressLint("UnrememberedMutableState") +@Preview(name = "Custom Dialog") +@Composable +fun MyDialogUIPreview() { + CustomDialogUI(openDialogCustom = mutableStateOf(false)) {} +} \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/ExitAppDelegate.kt b/app/src/main/java/com/techlads/composetv/ExitAppDelegate.kt new file mode 100644 index 0000000..65a679d --- /dev/null +++ b/app/src/main/java/com/techlads/composetv/ExitAppDelegate.kt @@ -0,0 +1,22 @@ +package com.techlads.composetv + +import android.window.OnBackInvokedDispatcher +import androidx.activity.ComponentActivity +import androidx.activity.addCallback +import androidx.core.os.BuildCompat + +fun ComponentActivity.registerOnBackPress(onBackPress: () -> Unit) { + if (BuildCompat.isAtLeastT()) { + onBackInvokedDispatcher.registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT + ) { + // Back is pressed... Finishing the activity + onBackPress() + } + } else { + onBackPressedDispatcher.addCallback(this /* lifecycle owner */) { + // Back is pressed... Finishing the activity + onBackPress() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/techlads/composetv/LoginActivity.kt b/app/src/main/java/com/techlads/composetv/LoginActivity.kt index 4b22c87..d546d66 100644 --- a/app/src/main/java/com/techlads/composetv/LoginActivity.kt +++ b/app/src/main/java/com/techlads/composetv/LoginActivity.kt @@ -8,19 +8,33 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import com.google.accompanist.navigation.animation.rememberAnimatedNavController import com.techlads.composetv.navigation.AppNavigation import com.techlads.composetv.theme.Material3Theme -class LoginActivity : ComponentActivity() { +class LoginActivity : ComponentActivity() { @OptIn(ExperimentalAnimationApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - val navController = rememberAnimatedNavController() - App(navController = navController) + val displayDialog = remember { + mutableStateOf(false) + } + + App(navController = rememberAnimatedNavController()) + + registerOnBackPress { + displayDialog.value = true + } + + if (displayDialog.value) + CustomDialog(openDialogCustom = displayDialog){ + finish() + } } } diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..ef9b77f --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,5 @@ + + + From 77fe7946f47bf25647b0eb2fd063ce71f3dbf6c7 Mon Sep 17 00:00:00 2001 From: Umair Khalid Date: Sun, 26 Mar 2023 01:23:20 +0100 Subject: [PATCH 4/8] Feature/home (#6) * Basic home screen added * Left menu basic structure added --- .idea/gradle.xml | 1 + .idea/misc.xml | 2 +- app/build.gradle.kts | 2 + .../com/techlads/composetv/LoginActivity.kt | 2 +- .../com/techlads/composetv/home/HomeScreen.kt | 8 + .../composetv/home/HomeScreenContent.kt | 18 +++ .../techlads/composetv/home/HomeViewModel.kt | 16 ++ .../com/techlads/composetv/home/MenuData.kt | 14 ++ .../techlads/composetv/leftmenu/LeftMenu.kt | 147 ++++++++++++++++++ .../composetv/leftmenu/model/MenuItem.kt | 9 ++ .../composetv/navigation/AppNavigation.kt | 13 +- .../techlads/composetv/navigation/Screens.kt | 1 + app/src/main/res/drawable/ic_menu.xml | 5 + gradle/libs.versions.toml | 5 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 15 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/techlads/composetv/home/HomeScreen.kt create mode 100644 app/src/main/java/com/techlads/composetv/home/HomeScreenContent.kt create mode 100644 app/src/main/java/com/techlads/composetv/home/HomeViewModel.kt create mode 100644 app/src/main/java/com/techlads/composetv/home/MenuData.kt create mode 100644 app/src/main/java/com/techlads/composetv/leftmenu/LeftMenu.kt create mode 100644 app/src/main/java/com/techlads/composetv/leftmenu/model/MenuItem.kt create mode 100644 app/src/main/res/drawable/ic_menu.xml diff --git a/.idea/gradle.xml b/.idea/gradle.xml index a2d7c21..a0de2a1 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,6 +7,7 @@