Skip to content

Commit df938ab

Browse files
[MW-225] feat(auth): Implement full Sign In & Sign Up flow with validation (#1872)
1 parent 3992e6f commit df938ab

File tree

42 files changed

+22972
-416
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+22972
-416
lines changed

.run/mifospay-ios.run.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<component name="ProjectRunConfigurationManager">
2-
<configuration default="false" name="mifospay-ios" type="KmmRunConfiguration" factoryName="iOS Application" CONFIG_VERSION="1" XCODE_PROJECT="$PROJECT_DIR$/mifospay-ios/iosApp.xcodeproj">
2+
<configuration default="false" name="mifospay-ios" type="KmmRunConfiguration" factoryName="iOS Application" CONFIG_VERSION="1" XCODE_PROJECT="$PROJECT_DIR$/mifospay-ios/iosApp.xcodeproj" XCODE_CONFIGURATION="Debug" XCODE_SCHEME="iosApp">
33
<method v="2">
44
<option name="com.jetbrains.kmm.ios.BuildIOSAppTask" enabled="true" />
55
</method>

core/common/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
plugins {
1111
alias(libs.plugins.mifospay.kmp.library)
1212
alias(libs.plugins.kotlin.parcelize)
13+
alias(libs.plugins.compose.compiler)
14+
alias(libs.plugins.jetbrainsCompose)
1315
}
1416

1517
android {
@@ -40,6 +42,8 @@ kotlin {
4042
api(libs.squareup.okio)
4143
api(libs.jb.kotlin.stdlib)
4244
api(libs.kotlinx.datetime)
45+
implementation(compose.components.resources)
46+
implementation(libs.jb.composeRuntime)
4347
}
4448

4549
androidMain.dependencies {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
9+
*/
10+
package org.mifospay.core.common.dialogManager
11+
12+
import kotlinx.coroutines.flow.MutableStateFlow
13+
import kotlinx.coroutines.flow.StateFlow
14+
import kotlinx.coroutines.flow.asStateFlow
15+
import org.jetbrains.compose.resources.StringResource
16+
17+
/**
18+
* A singleton for managing dialog state across the app.
19+
* It works with [DialogMessage] to determine what kind of dialog should be shown.
20+
*
21+
* This is typically observed in the UI to display a loading spinner or error message.
22+
*/
23+
object DialogManager {
24+
25+
private val _dialogMessage = MutableStateFlow<DialogMessage>(DialogMessage.None)
26+
27+
/**
28+
* Public read-only dialog message flow.
29+
* UI layers should collect this to react to dialog state changes.
30+
*/
31+
val dialogMessage: StateFlow<DialogMessage> = _dialogMessage.asStateFlow()
32+
33+
/**
34+
* Dismisses any currently shown dialog.
35+
*
36+
* ### Example:
37+
* ```
38+
* DialogManager.dismissDialog()
39+
* ```
40+
*/
41+
fun dismissDialog() {
42+
_dialogMessage.value = DialogMessage.None
43+
}
44+
45+
/**
46+
* Shows a loading dialog.
47+
*
48+
* ### Example:
49+
* ```
50+
* DialogManager.showLoading()
51+
* ```
52+
*/
53+
fun showLoading() {
54+
_dialogMessage.value = DialogMessage.Loading
55+
}
56+
57+
/**
58+
* Shows a plain string message in a dialog.
59+
*
60+
* @param message The text to display.
61+
*
62+
* ### Example:
63+
* ```
64+
* DialogManager.showMessage("Invalid email address.")
65+
* ```
66+
*/
67+
fun showMessage(message: String) {
68+
_dialogMessage.value = DialogMessage.StringMessage(message)
69+
}
70+
71+
/**
72+
* Shows a localized string resource message in a dialog.
73+
*
74+
* @param message The resource ID to display.
75+
*
76+
* ### Example:
77+
* ```
78+
* DialogManager.showMessage(Res.string.feature_auth_error_email_required)
79+
* ```
80+
*/
81+
fun showMessage(message: StringResource) {
82+
_dialogMessage.value = DialogMessage.ResourceMessage(message)
83+
}
84+
85+
/**
86+
* Allows setting any [DialogMessage] manually.
87+
*
88+
* @param message The [DialogMessage] to show.
89+
*
90+
* ### Example:
91+
* ```
92+
* DialogManager.showMessage(DialogMessage.Loading)
93+
* ```
94+
*/
95+
fun showMessage(message: DialogMessage) {
96+
_dialogMessage.value = message
97+
}
98+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
9+
*/
10+
package org.mifospay.core.common.dialogManager
11+
12+
import org.jetbrains.compose.resources.StringResource
13+
14+
/**
15+
* Represents the possible types of dialog messages shown in the application.
16+
* Used in combination with [DialogManager] to control dialog visibility and content.
17+
*/
18+
sealed interface DialogMessage {
19+
20+
/**
21+
* Represents the absence of a dialog message.
22+
* Used to indicate that no dialog should be displayed.
23+
*/
24+
data object None : DialogMessage
25+
26+
/**
27+
* Represents a loading dialog.
28+
* Used to indicate an ongoing operation to the user.
29+
*/
30+
data object Loading : DialogMessage
31+
32+
/**
33+
* Represents a dialog that shows a plain string message.
34+
*
35+
* @property message The message to be displayed in the dialog.
36+
*/
37+
class StringMessage(val message: String) : DialogMessage
38+
39+
/**
40+
* Represents a dialog that shows a localized string resource message.
41+
*
42+
* @property message A [StringResource] ID for localization.
43+
*/
44+
class ResourceMessage(val message: StringResource) : DialogMessage
45+
46+
companion object {
47+
48+
/**
49+
* Converts a [Throwable] into a [DialogMessage].
50+
* Uses [StringMessage] if the exception has a non-blank message,
51+
* otherwise falls back to a generic error.
52+
*
53+
* @return [StringMessage] based on content.
54+
*
55+
* ### Example:
56+
* ```
57+
* try {
58+
* doSomethingRisky()
59+
* } catch (e: Exception) {
60+
* DialogManager.showMessage(e.toDialogMessage())
61+
* }
62+
* ```
63+
*/
64+
fun Throwable.toDialogMessage(): DialogMessage {
65+
return StringMessage(message ?: "Unknown error occurred.")
66+
}
67+
}
68+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2025 Mifos Initiative
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
9+
*/
10+
package org.mifospay.core.common.utils
11+
12+
/**
13+
* Formats a list of strings into a bullet-pointed multiline string.
14+
*
15+
* Each non-blank line is trimmed and prefixed with a Unicode bullet (•) followed by a space.
16+
* Empty or whitespace-only strings are ignored.
17+
*
18+
* @param lines A list of strings to be formatted.
19+
* @return A single string where each line is prefixed with a bullet point and separated by a newline.
20+
*
21+
* ### Example:
22+
* ```
23+
* val feedback = listOf(
24+
* "The password must be at least 12 characters long",
25+
* "Include at least one number"
26+
* )
27+
*
28+
* val result = formatAsBulletPoints(feedback)
29+
* println(result)
30+
* ```
31+
*
32+
* ### Output:
33+
* ```
34+
* • The password must be at least 12 characters long
35+
* • Include at least one number
36+
* ```
37+
*/
38+
fun formatAsBulletPoints(lines: List<String>): String {
39+
return lines
40+
.map { it.trim() }
41+
.filter { it.isNotEmpty() }
42+
.joinToString(separator = "\n") { "$it" }
43+
}

core/data/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ plugins {
1111
alias(libs.plugins.mifospay.kmp.library)
1212
alias(libs.plugins.kotlin.parcelize)
1313
id("kotlinx-serialization")
14+
alias(libs.plugins.compose.compiler)
15+
alias(libs.plugins.jetbrainsCompose)
1416
}
1517

1618
android {
@@ -32,6 +34,8 @@ kotlin {
3234
implementation(projects.core.network)
3335
implementation(projects.core.analytics)
3436
implementation(libs.kotlinx.serialization.json)
37+
implementation(libs.jb.composeRuntime)
38+
implementation(compose.components.resources)
3539
}
3640

3741
androidMain.dependencies {

0 commit comments

Comments
 (0)