Skip to content

Commit da4389b

Browse files
authored
Feature: auth to CMP (#2381)
1 parent 978ecc4 commit da4389b

11 files changed

Lines changed: 105 additions & 72 deletions

File tree

core/designsystem/src/commonMain/kotlin/com/mifos/core/designsystem/icon/MifosIcons.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package com.mifos.core.designsystem.icon
1111

1212
import androidx.compose.material.icons.Icons
1313
import androidx.compose.material.icons.automirrored.filled.ArrowBack
14+
import androidx.compose.material.icons.automirrored.filled.ArrowForward
1415
import androidx.compose.material.icons.automirrored.filled.Assignment
1516
import androidx.compose.material.icons.automirrored.filled.CompareArrows
1617
import androidx.compose.material.icons.automirrored.filled.Help
@@ -35,6 +36,7 @@ import androidx.compose.material.icons.filled.FlashOn
3536
import androidx.compose.material.icons.filled.Image
3637
import androidx.compose.material.icons.filled.Info
3738
import androidx.compose.material.icons.filled.LocationOn
39+
import androidx.compose.material.icons.filled.Lock
3840
import androidx.compose.material.icons.filled.Menu
3941
import androidx.compose.material.icons.filled.MoreVert
4042
import androidx.compose.material.icons.filled.Notifications
@@ -100,6 +102,7 @@ object MifosIcons {
100102
val ArrowUp = Icons.Rounded.KeyboardArrowUp
101103
val ArrowDown = Icons.Rounded.KeyboardArrowDown
102104
val MoreVert = Icons.Rounded.MoreVert
105+
val ArrowForward = Icons.AutoMirrored.Filled.ArrowForward
103106
val FileTask = Icons.Default.AssignmentTurnedIn
104107
val AddLocation = Icons.Rounded.AddLocation
105108
val CloudDownload = Icons.Default.CloudDownload
@@ -123,6 +126,7 @@ object MifosIcons {
123126
val Profile = Icons.Outlined.AccountCircle
124127
val ProfileBoarder = Icons.Rounded.AccountCircle
125128
val buildingIcon = Icons.Filled.Apartment
129+
val Lock: ImageVector = Icons.Filled.Lock
126130

127131
val Paid: ImageVector = Icons.Default.Paid
128132
val Logout: ImageVector = Icons.AutoMirrored.Filled.Logout

feature/auth/build.gradle.kts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,24 @@
88
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
99
*/
1010
plugins {
11-
alias(libs.plugins.mifos.android.feature)
12-
alias(libs.plugins.mifos.android.library.compose)
13-
alias(libs.plugins.mifos.android.library.jacoco)
11+
alias(libs.plugins.mifos.cmp.feature)
1412
}
1513

1614
android {
1715
namespace = "com.mifos.feature.auth"
1816
}
1917

20-
dependencies {
21-
implementation(projects.core.data)
22-
implementation(projects.core.domain)
23-
24-
testImplementation(libs.hilt.android.testing)
18+
kotlin {
19+
sourceSets {
20+
commonMain.dependencies {
21+
implementation(compose.material3)
22+
implementation(compose.components.resources)
23+
implementation(compose.ui)
24+
implementation(libs.kermit.simple)
25+
implementation(libs.kermit.logging)
26+
api(projects.core.data)
27+
api(projects.core.domain)
28+
}
29+
}
2530
}
31+
File renamed without changes.

feature/auth/src/main/res/drawable/feature_auth_mifos_logo.jpg renamed to feature/auth/src/commonMain/composeResources/drawable/feature_auth_mifos_logo.jpg

File renamed without changes.

feature/auth/src/main/res/values/strings.xml renamed to feature/auth/src/commonMain/composeResources/values/strings.xml

File renamed without changes.

feature/auth/src/main/java/com/mifos/feature/auth/di/AuthModule.kt renamed to feature/auth/src/commonMain/kotlin/com/mifos/feature/auth/di/AuthModule.kt

File renamed without changes.

feature/auth/src/main/java/com/mifos/feature/auth/login/LoginScreen.kt renamed to feature/auth/src/commonMain/kotlin/com/mifos/feature/auth/login/LoginScreen.kt

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
*/
1010
package com.mifos.feature.auth.login
1111

12+
import androidclient.feature.auth.generated.resources.Res
13+
import androidclient.feature.auth.generated.resources.feature_auth_enter_credentials
14+
import androidclient.feature.auth.generated.resources.feature_auth_mifos_logo
15+
import androidclient.feature.auth.generated.resources.feature_auth_password
16+
import androidclient.feature.auth.generated.resources.feature_auth_username
1217
import androidx.compose.foundation.layout.Box
1318
import androidx.compose.foundation.layout.Column
1419
import androidx.compose.foundation.layout.PaddingValues
@@ -21,13 +26,7 @@ import androidx.compose.foundation.layout.padding
2126
import androidx.compose.foundation.layout.width
2227
import androidx.compose.foundation.rememberScrollState
2328
import androidx.compose.foundation.verticalScroll
24-
import androidx.compose.material.icons.Icons
2529
import androidx.compose.material.icons.automirrored.filled.ArrowForward
26-
import androidx.compose.material.icons.filled.Error
27-
import androidx.compose.material.icons.filled.Lock
28-
import androidx.compose.material.icons.filled.Person
29-
import androidx.compose.material.icons.filled.Visibility
30-
import androidx.compose.material.icons.filled.VisibilityOff
3130
import androidx.compose.material3.Button
3231
import androidx.compose.material3.ButtonDefaults
3332
import androidx.compose.material3.CircularProgressIndicator
@@ -46,32 +45,30 @@ import androidx.compose.runtime.collectAsState
4645
import androidx.compose.runtime.getValue
4746
import androidx.compose.runtime.mutableStateOf
4847
import androidx.compose.runtime.remember
48+
import androidx.compose.runtime.rememberCoroutineScope
4949
import androidx.compose.runtime.saveable.rememberSaveable
5050
import androidx.compose.runtime.setValue
5151
import androidx.compose.ui.Alignment
5252
import androidx.compose.ui.Modifier
53-
import androidx.compose.ui.graphics.Color
54-
import androidx.compose.ui.graphics.Color.Companion.DarkGray
5553
import androidx.compose.ui.graphics.Color.Companion.White
56-
import androidx.compose.ui.platform.LocalContext
57-
import androidx.compose.ui.res.painterResource
58-
import androidx.compose.ui.res.stringResource
59-
import androidx.compose.ui.text.TextStyle
60-
import androidx.compose.ui.text.font.FontStyle
61-
import androidx.compose.ui.text.font.FontWeight
6254
import androidx.compose.ui.text.input.PasswordVisualTransformation
6355
import androidx.compose.ui.text.input.TextFieldValue
6456
import androidx.compose.ui.text.input.VisualTransformation
6557
import androidx.compose.ui.text.style.TextAlign
66-
import androidx.compose.ui.tooling.preview.Preview
6758
import androidx.compose.ui.unit.dp
6859
import androidx.compose.ui.unit.sp
6960
import androidx.compose.ui.window.Dialog
7061
import androidx.compose.ui.window.DialogProperties
7162
import com.mifos.core.designsystem.component.MifosAndroidClientIcon
7263
import com.mifos.core.designsystem.component.MifosOutlinedTextField
73-
import com.mifos.feature.auth.R
74-
import org.koin.androidx.compose.koinViewModel
64+
import com.mifos.core.designsystem.icon.MifosIcons
65+
import com.mifos.core.ui.util.DevicePreview
66+
import kotlinx.coroutines.launch
67+
import org.jetbrains.compose.resources.StringResource
68+
import org.jetbrains.compose.resources.getString
69+
import org.jetbrains.compose.resources.painterResource
70+
import org.jetbrains.compose.resources.stringResource
71+
import org.koin.compose.viewmodel.koinViewModel
7572

7673
/**
7774
* Created by Aditya Gupta on 11/02/24.
@@ -86,7 +83,7 @@ internal fun LoginScreen(
8683
loginViewModel: LoginViewModel = koinViewModel(),
8784
) {
8885
val state = loginViewModel.loginUiState.collectAsState().value
89-
val context = LocalContext.current
86+
val coroutineScope = rememberCoroutineScope()
9087

9188
val snackbarHostState = remember { SnackbarHostState() }
9289

@@ -104,16 +101,16 @@ internal fun LoginScreen(
104101
}
105102
var passwordVisibility: Boolean by remember { mutableStateOf(false) }
106103

107-
val usernameError: MutableState<Int?> = remember { mutableStateOf(null) }
108-
val passwordError: MutableState<Int?> = remember { mutableStateOf(null) }
104+
val usernameError: MutableState<StringResource?> = remember { mutableStateOf(null) }
105+
val passwordError: MutableState<StringResource?> = remember { mutableStateOf(null) }
109106

110107
when (state) {
111108
is LoginUiState.Empty -> {}
112109

113110
is LoginUiState.ShowError -> {
114111
showDialog.value = false
115112
LaunchedEffect(key1 = state.message) {
116-
snackbarHostState.showSnackbar(message = context.getString(state.message))
113+
snackbarHostState.showSnackbar(message = getString(state.message))
117114
}
118115
}
119116

@@ -141,7 +138,7 @@ internal fun LoginScreen(
141138
modifier = modifier
142139
.fillMaxSize()
143140
.padding(16.dp),
144-
containerColor = Color.White,
141+
containerColor = White,
145142
snackbarHost = { SnackbarHost(snackbarHostState) },
146143
bottomBar = {
147144
Box(
@@ -162,7 +159,7 @@ internal fun LoginScreen(
162159
Spacer(modifier = Modifier.width(4.dp))
163160

164161
Icon(
165-
imageVector = Icons.AutoMirrored.Filled.ArrowForward,
162+
imageVector = MifosIcons.ArrowForward,
166163
contentDescription = "ArrowForward",
167164
)
168165
}
@@ -179,20 +176,15 @@ internal fun LoginScreen(
179176
) {
180177
Spacer(modifier = Modifier.height(80.dp))
181178

182-
MifosAndroidClientIcon(imageVector = painterResource(R.drawable.feature_auth_mifos_logo))
179+
MifosAndroidClientIcon(imageVector = painterResource(Res.drawable.feature_auth_mifos_logo))
183180

184181
Text(
185182
modifier = Modifier
186183
.fillMaxWidth()
187184
.padding(top = 8.dp),
188-
text = stringResource(id = R.string.feature_auth_enter_credentials),
185+
text = stringResource(Res.string.feature_auth_enter_credentials),
189186
textAlign = TextAlign.Center,
190-
style = TextStyle(
191-
fontSize = 16.sp,
192-
fontWeight = FontWeight.Bold,
193-
fontStyle = FontStyle.Normal,
194-
color = DarkGray,
195-
),
187+
style = MaterialTheme.typography.bodyMedium,
196188
)
197189

198190
Spacer(modifier = Modifier.height(16.dp))
@@ -202,12 +194,12 @@ internal fun LoginScreen(
202194
onValueChanged = { value ->
203195
userName = value
204196
},
205-
icon = Icons.Filled.Person,
206-
label = stringResource(R.string.feature_auth_username),
197+
icon = MifosIcons.Person,
198+
label = stringResource(Res.string.feature_auth_username),
207199
error = usernameError.value?.let { it1 -> stringResource(it1) },
208200
trailingIcon = {
209201
if (usernameError.value != null) {
210-
Icon(imageVector = Icons.Filled.Error, contentDescription = null)
202+
Icon(imageVector = MifosIcons.Error, contentDescription = "Error Icon")
211203
}
212204
},
213205
)
@@ -220,29 +212,33 @@ internal fun LoginScreen(
220212
password = value
221213
},
222214
visualTransformation = if (passwordVisibility) VisualTransformation.None else PasswordVisualTransformation(),
223-
icon = Icons.Filled.Lock,
224-
label = stringResource(R.string.feature_auth_password),
215+
icon = MifosIcons.Lock,
216+
label = stringResource(Res.string.feature_auth_password),
225217
error = passwordError.value?.let { it1 -> stringResource(it1) },
226218
trailingIcon = {
227219
if (passwordError.value == null) {
228220
val image = if (passwordVisibility) {
229-
Icons.Filled.Visibility
221+
MifosIcons.Visibility
230222
} else {
231-
Icons.Filled.VisibilityOff
223+
MifosIcons.VisibilityOff
232224
}
233225
IconButton(onClick = { passwordVisibility = !passwordVisibility }) {
234-
Icon(imageVector = image, null)
226+
Icon(imageVector = image, "PasswordVisibility Icon")
235227
}
236228
} else {
237-
Icon(imageVector = Icons.Filled.Error, contentDescription = null)
229+
Icon(MifosIcons.Error, contentDescription = null)
238230
}
239231
},
240232
)
241233

242234
Spacer(modifier = Modifier.height(8.dp))
243235

244236
Button(
245-
onClick = { loginViewModel.validateUserInputs(userName.text, password.text) },
237+
onClick = {
238+
coroutineScope.launch {
239+
loginViewModel.validateUserInputs(userName.text, password.text)
240+
}
241+
},
246242
modifier = Modifier
247243
.fillMaxWidth()
248244
.heightIn(44.dp)
@@ -266,7 +262,7 @@ internal fun LoginScreen(
266262
}
267263
}
268264

269-
@Preview(showSystemUi = true, device = "id:pixel_7")
265+
@DevicePreview()
270266
@Composable
271267
private fun LoginScreenPreview() {
272268
LoginScreen({}, {}, {})

feature/auth/src/main/java/com/mifos/feature/auth/login/LoginUiState.kt renamed to feature/auth/src/commonMain/kotlin/com/mifos/feature/auth/login/LoginUiState.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*/
1010
package com.mifos.feature.auth.login
1111

12+
import org.jetbrains.compose.resources.StringResource
13+
1214
/**
1315
* Created by Aditya Gupta on 06/08/23.
1416
*/
@@ -19,9 +21,9 @@ sealed class LoginUiState {
1921

2022
data object ShowProgress : LoginUiState()
2123

22-
data class ShowError(val message: Int) : LoginUiState()
24+
data class ShowError(val message: StringResource) : LoginUiState()
2325

24-
data class ShowValidationError(val usernameError: Int? = null, val passwordError: Int? = null) :
26+
data class ShowValidationError(val usernameError: StringResource? = null, val passwordError: StringResource? = null) :
2527
LoginUiState()
2628

2729
data object HomeActivityIntent : LoginUiState()

0 commit comments

Comments
 (0)