Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmp-android/dependencies/demoDebugRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ org.jetbrains.compose.ui:ui-util:1.7.0-rc01
org.jetbrains.compose.ui:ui:1.7.0-rc01
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.1.0
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.1.0
org.jetbrains.kotlin:kotlin-reflect:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20
Expand Down
1 change: 1 addition & 0 deletions cmp-android/dependencies/demoReleaseRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ org.jetbrains.compose.ui:ui-util:1.7.0-rc01
org.jetbrains.compose.ui:ui:1.7.0-rc01
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.1.0
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.1.0
org.jetbrains.kotlin:kotlin-reflect:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20
Expand Down
1 change: 1 addition & 0 deletions cmp-android/dependencies/prodDebugRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ org.jetbrains.compose.ui:ui-util:1.7.0-rc01
org.jetbrains.compose.ui:ui:1.7.0-rc01
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.1.0
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.1.0
org.jetbrains.kotlin:kotlin-reflect:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20
Expand Down
1 change: 1 addition & 0 deletions cmp-android/dependencies/prodReleaseRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ org.jetbrains.compose.ui:ui-util:1.7.0-rc01
org.jetbrains.compose.ui:ui:1.7.0-rc01
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.1.0
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.1.0
org.jetbrains.kotlin:kotlin-reflect:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20
Expand Down
2 changes: 1 addition & 1 deletion cmp-desktop/src/jvmMain/kotlin/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun main() {
Window(
onCloseRequest = ::exitApplication,
state = windowState,
title = "DesktopApp",
title = "Mifos Mobile",
) {
// Sets the content of the window.
SharedApp()
Expand Down
3 changes: 3 additions & 0 deletions cmp-navigation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ plugins {
kotlin {
sourceSets {
commonMain.dependencies {

implementation(projects.feature.auth)

// Core Modules
implementation(projects.core.data)
implementation(projects.core.common)
Expand Down
34 changes: 32 additions & 2 deletions cmp-navigation/src/commonMain/kotlin/cmp/navigation/ComposeApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,54 @@
*/
package cmp.navigation

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import cmp.navigation.navigation.NavGraphRoute.AUTH_GRAPH
import cmp.navigation.navigation.NavGraphRoute.PASSCODE_GRAPH
import cmp.navigation.navigation.RootNavGraph
import org.koin.compose.koinInject
import org.koin.compose.viewmodel.koinViewModel
import org.mifos.mobile.core.data.util.NetworkMonitor
import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme

@Composable
fun ComposeApp(
modifier: Modifier = Modifier,
networkMonitor: NetworkMonitor = koinInject(),
viewModel: ComposeAppViewModel = koinViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val navController = rememberNavController()

val navDestination = when (uiState) {
is MainUiState.Loading -> AUTH_GRAPH
is MainUiState.Success -> if ((uiState as MainUiState.Success).userData.isAuthenticated) {
PASSCODE_GRAPH
} else {
AUTH_GRAPH
}

else -> AUTH_GRAPH
}

MifosMobileTheme {
RootNavGraph(
modifier = modifier.fillMaxSize(),
networkMonitor = networkMonitor,
navHostController = rememberNavController(),
modifier = modifier,
navHostController = navController,
startDestination = navDestination,
// onClickLogout = {
// viewModel.logOut()
// navController.navigate(AUTH_GRAPH) {
// popUpTo(navController.graph.id) {
// inclusive = true
// }
// }
// },
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
*/
package cmp.navigation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.mifos.mobile.core.common.DataState
import org.mifos.mobile.core.data.repository.UserDataRepository
import org.mifos.mobile.core.model.UserData

class ComposeAppViewModel(
private val userDataRepository: UserDataRepository,
// private val passcodeManager: PasscodeManager,
) : ViewModel() {

val uiState: StateFlow<MainUiState> = userDataRepository.userData.map { dataState ->
when (dataState) {
is DataState.Success -> MainUiState.Success(dataState.data)
is DataState.Error -> MainUiState.Error(dataState.exception.message ?: "Unknown error")
DataState.Loading -> MainUiState.Loading
}
}.stateIn(
scope = viewModelScope,
initialValue = MainUiState.Loading,
started = SharingStarted.WhileSubscribed(5_000),
)

fun logOut() {
viewModelScope.launch {
userDataRepository.logOut()
// passcodeManager.clearPasscode()
}
}
}

sealed interface MainUiState {
data object Loading : MainUiState
data class Error(val error: String) : MainUiState
data class Success(val userData: UserData) : MainUiState
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
*/
package cmp.navigation.di

import cmp.navigation.ComposeAppViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module
import org.mifos.mobile.core.common.di.DispatchersModule
import org.mifos.mobile.core.data.di.RepositoryModule
import org.mifos.mobile.core.datastore.di.PreferencesModule
import org.mifos.mobile.core.network.di.NetworkModule
import org.mifos.mobile.feature.auth.di.AuthModule

object KoinModules {
private val commonModules = module {
Expand All @@ -28,14 +31,14 @@ object KoinModules {
private val networkModules = module {
includes(NetworkModule)
}
// private val sharedModule = module {
// viewModelOf(::MifosMobileViewModel)
// }
// private val featureModules = module {
// includes(
// AuthModule,
// )
// }
private val sharedModule = module {
viewModelOf(::ComposeAppViewModel)
}
private val featureModules = module {
includes(
AuthModule,
)
}
// private val LibraryModule = module {
// includes(PasscodeModule)
// }
Expand All @@ -45,7 +48,7 @@ object KoinModules {
dataModules,
coreDataStoreModules,
networkModules,
// featureModules,
// sharedModule,
featureModules,
sharedModule,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ fun NavGraphBuilder.homeScreen() {
}

@Composable
fun WelcomeScreen(
modifier: Modifier = Modifier,
) {
fun WelcomeScreen(modifier: Modifier = Modifier) {
Column(
modifier = modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,36 @@ import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import cmp.navigation.navigation.NavGraphRoute.AUTH_GRAPH
import cmp.navigation.navigation.NavGraphRoute.MAIN_GRAPH
import cmp.navigation.ui.App
import org.mifos.mobile.core.data.util.NetworkMonitor
import org.mifos.mobile.feature.auth.navigation.authenticationNavGraph

@Composable
fun RootNavGraph(
networkMonitor: NetworkMonitor,
navHostController: NavHostController,
startDestination: String,
modifier: Modifier = Modifier,
// onClickLogout: () -> Unit,
) {
NavHost(
navController = navHostController,
startDestination = MAIN_GRAPH,
startDestination = startDestination,
route = NavGraphRoute.ROOT_GRAPH,
modifier = modifier,
) {
authenticationNavGraph(
navController = navHostController,
route = AUTH_GRAPH,
// navigateToPasscodeScreen = navHostController::navigateToPasscodeScreen,
navigateToPasscodeScreen = { },
)
composable(MAIN_GRAPH) {
App(
modifier = modifier,
networkMonitor = networkMonitor,
// onClickLogout = onClickLogout,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import org.mifos.mobile.core.designsystem.theme.MifosBackground
fun App(
networkMonitor: NetworkMonitor,
modifier: Modifier = Modifier,
// onClickLogout: () -> Unit,
) {
MifosBackground(modifier) {
val snackbarHostState = remember { SnackbarHostState() }
Expand Down Expand Up @@ -79,7 +80,7 @@ fun App(
) {
FeatureNavHost(
appState = appState,
// onClickLogout = {},
// onClickLogout = onClickLogout,
modifier = Modifier,
)
}
Expand Down
2 changes: 1 addition & 1 deletion cmp-web/src/wasmJsMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fun main() {
* This window uses the canvas element with the ID "ComposeTarget" and has the title "WebApp".
*/
CanvasBasedWindow(
title = "WebApp", // Window title
title = "Mifos Mobile", // Window title
canvasElementId = "ComposeTarget", // The canvas element where the Compose UI will be rendered
) {
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
package org.mifos.mobile.core.data.repositoryImpl

import io.ktor.client.statement.bodyAsText
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import org.mifos.mobile.core.common.DataState
Expand Down Expand Up @@ -47,8 +48,12 @@ class UserAuthRepositoryImp(
)
return try {
withContext(ioDispatcher) {
dataManager.registrationApi.registerUser(registerPayload)
DataState.Success("User registered Successfully")
val result = dataManager.registrationApi.registerUser(registerPayload)
val errorMessage = result.bodyAsText()
when (result.status.value) {
200 -> DataState.Success("User registered Successfully")
else -> DataState.Error(Exception("Error in registering user: $errorMessage"), null)
}
}
} catch (e: Exception) {
DataState.Error(e, null)
Expand All @@ -63,7 +68,11 @@ class UserAuthRepositoryImp(
return try {
withContext(ioDispatcher) {
val user = dataManager.authenticationApi.authenticate(loginPayload)
DataState.Success(user)
if (user.base64EncodedAuthenticationKey != null) {
DataState.Success(user)
} else {
DataState.Error(Exception("Invalid Credentials"), null)
}
}
} catch (e: Exception) {
DataState.Error(e, null)
Expand All @@ -80,9 +89,16 @@ class UserAuthRepositoryImp(
)
return try {
withContext(ioDispatcher) {
dataManager.registrationApi.verifyUser(userVerify)
val result = dataManager.registrationApi.verifyUser(userVerify)
val errorMessage = result.bodyAsText()
when (result.status.value) {
200 -> DataState.Success("User Verified Successfully")
else -> DataState.Error(
Exception("Error in verifying user: $errorMessage"),
null,
)
}
}
DataState.Success("User Verified Successfully")
} catch (e: Exception) {
DataState.Error(e, null)
}
Expand All @@ -98,7 +114,15 @@ class UserAuthRepositoryImp(
)
return try {
withContext(ioDispatcher) {
dataManager.userDetailsApi.updateAccountPassword(payload)
val result = dataManager.userDetailsApi.updateAccountPassword(payload)
val errorMessage = result.bodyAsText()
when (result.status.value) {
200 -> DataState.Success("User Verified Successfully")
else -> DataState.Error(
Exception("Error in verifying user: $errorMessage"),
null,
)
}
}
DataState.Success("Password Updated Successfully")
} catch (e: Exception) {
Expand Down
Loading
Loading