diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 149894513..50bf3108e 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -85,7 +85,8 @@ dependencies { implementation(projects.core.model) implementation(projects.core.data) implementation(projects.core.datastore) - implementation(projects.ui) + implementation(projects.core.ui) + implementation(projects.core.designsystem) implementation(projects.feature.loan) implementation(projects.feature.beneficiary) diff --git a/androidApp/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt b/androidApp/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt index 0318315fd..090848eda 100644 --- a/androidApp/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt +++ b/androidApp/src/main/java/org/mifos/mobile/ui/activities/HomeActivity.kt @@ -19,7 +19,7 @@ import com.google.android.gms.common.GoogleApiAvailability import dagger.hilt.android.AndroidEntryPoint import org.mifos.mobile.R import org.mifos.mobile.core.common.Constants -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.home.navigation.HomeNavigation import org.mifos.mobile.feature.user_profile.viewmodel.UserDetailViewModel import org.mifos.mobile.navigation.RootNavGraph diff --git a/androidApp/src/main/java/org/mifos/mobile/ui/activities/LoginActivity.kt b/androidApp/src/main/java/org/mifos/mobile/ui/activities/LoginActivity.kt index 518ba7974..679d61763 100644 --- a/androidApp/src/main/java/org/mifos/mobile/ui/activities/LoginActivity.kt +++ b/androidApp/src/main/java/org/mifos/mobile/ui/activities/LoginActivity.kt @@ -6,7 +6,7 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.navigation.compose.rememberNavController import dagger.hilt.android.AndroidEntryPoint -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.auth.navigation.AuthenticationNavigation import org.mifos.mobile.navigation.RootNavGraph diff --git a/androidApp/src/main/java/org/mifos/mobile/ui/activities/PassCodeActivity.kt b/androidApp/src/main/java/org/mifos/mobile/ui/activities/PassCodeActivity.kt index aac696fbc..ad5ea3485 100644 --- a/androidApp/src/main/java/org/mifos/mobile/ui/activities/PassCodeActivity.kt +++ b/androidApp/src/main/java/org/mifos/mobile/ui/activities/PassCodeActivity.kt @@ -9,7 +9,7 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.ui.Modifier import androidx.navigation.compose.rememberNavController import dagger.hilt.android.AndroidEntryPoint -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.navigation.PASSCODE_SCREEN import org.mifos.mobile.navigation.RootNavGraph diff --git a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt index 3b445cf1f..c4df45845 100644 --- a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt @@ -3,6 +3,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.kotlin import org.mifos.mobile.libs class AndroidFeatureConventionPlugin : Plugin { @@ -20,12 +21,28 @@ class AndroidFeatureConventionPlugin : Plugin { } dependencies { - add("implementation", project(":ui")) - //add("implementation", project(":core:designsystem")) + add("implementation", project(":core:designsystem")) + add("implementation", project(":core:ui")) + add("implementation", project(":core:data")) + + add("implementation", project(":libs:material3-navigation")) + + add("implementation", libs.findLibrary("kotlinx.collections.immutable").get()) add("implementation", libs.findLibrary("androidx.hilt.navigation.compose").get()) add("implementation", libs.findLibrary("androidx.lifecycle.runtimeCompose").get()) add("implementation", libs.findLibrary("androidx.lifecycle.viewModelCompose").get()) + + add("androidTestImplementation", libs.findLibrary("androidx.lifecycle.runtimeTesting").get()) + + add("testImplementation", kotlin("test")) + add("testImplementation", libs.findLibrary("hilt.android.testing").get()) + + add("debugImplementation", libs.findLibrary("androidx.compose.ui.test.manifest").get()) + add("androidTestImplementation", libs.findLibrary("androidx.navigation.testing").get()) + add("androidTestImplementation", libs.findLibrary("androidx.compose.ui.test").get()) + add("androidTestImplementation", libs.findLibrary("hilt.android.testing").get()) + add("androidTestImplementation", libs.findLibrary("androidx.lifecycle.runtimeTesting").get()) } } } diff --git a/build-logic/convention/src/main/kotlin/org/mifos/mobile/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/org/mifos/mobile/AndroidCompose.kt index 1836ba3a4..bfcf93b12 100644 --- a/build-logic/convention/src/main/kotlin/org/mifos/mobile/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/org/mifos/mobile/AndroidCompose.kt @@ -25,6 +25,9 @@ internal fun Project.configureAndroidCompose( val bom = libs.findLibrary("androidx-compose-bom").get() add("implementation", platform(bom)) add("androidTestImplementation", platform(bom)) + + add("implementation", libs.findLibrary("androidx-compose-ui-tooling-preview").get()) + add("debugImplementation", libs.findLibrary("androidx-compose-ui-tooling").get()) } testOptions { diff --git a/ci-prebuild.bat b/ci-prebuild.bat new file mode 100644 index 000000000..a7fbd8a4d --- /dev/null +++ b/ci-prebuild.bat @@ -0,0 +1,32 @@ +@echo off +setlocal enabledelayedexpansion + +rem Check if gradlew exists in the project +if not exist "%~dp0gradlew" ( + echo Error: gradlew not found in the project. + exit /b 1 +) + +echo Starting all checks and tests... + +call :run_gradle_task "check -p build-logic" +call :run_gradle_task "spotlessApply --no-configuration-cache" +call :run_gradle_task "dependencyGuardBaseline" +call :run_gradle_task "detekt" +call :run_gradle_task "testDemoDebug :lint:test :androidApp:lintProdRelease :lint:lint" +call :run_gradle_task "build" +call :run_gradle_task "updateProdReleaseBadging" + +echo All checks and tests completed successfully. +exit /b 0 + +:run_gradle_task +echo ######################################################## +echo Running: %~1 +call "%~dp0gradlew" %~1 +if %ERRORLEVEL% neq 0 ( + echo Error: Task %~1 failed + exit /b 1 +) +echo ######################################################## +exit /b 0 \ No newline at end of file diff --git a/ci-prebuild.sh b/ci-prebuild.sh new file mode 100644 index 000000000..2bcc5ce8e --- /dev/null +++ b/ci-prebuild.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Check if gradlew exists in the project +if [ ! -f "./gradlew" ]; then + echo "Error: gradlew not found in the project." + exit 1 +fi + +echo "Starting all checks and tests..." + +failed_tasks=() +successful_tasks=() + +run_gradle_task() { + echo "Running: $1" + "./gradlew" $1 + if [ $? -ne 0 ]; then + echo "Warning: Task $1 failed" + failed_tasks+=("$1") + else + echo "Task $1 completed successfully" + successful_tasks+=("$1") + fi +} + +tasks=( + "check -p build-logic" + "spotlessApply --no-configuration-cache" + "dependencyGuardBaseline" + "detekt" + "testDemoDebug :lint:test :lint:lint :androidApp:lintProdRelease" + "build" + "updateProdReleaseBadging" +) + +for task in "${tasks[@]}"; do + run_gradle_task "$task" +done + +echo "All tasks have finished." + +echo "Successful tasks:" +for task in "${successful_tasks[@]}"; do + echo "- $task" +done + +if [ ${#failed_tasks[@]} -eq 0 ]; then + echo "All checks and tests completed successfully." +else + echo "Failed tasks:" + for task in "${failed_tasks[@]}"; do + echo "- $task" + done + echo "Please review the output above for more details on the failures." +fi + +echo "Total tasks: ${#tasks[@]}" +echo "Successful tasks: ${#successful_tasks[@]}" +echo "Failed tasks: ${#failed_tasks[@]}" \ No newline at end of file diff --git a/core/designsystem/build.gradle.kts b/core/designsystem/build.gradle.kts new file mode 100644 index 000000000..d1b606897 --- /dev/null +++ b/core/designsystem/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright 2024 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 + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) +} + +android { + defaultConfig { + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + namespace = "org.mifos.mobile.core.designsystem" +} + +dependencies { + lintPublish(projects.lint) + + api(libs.androidx.compose.ui) + api(libs.androidx.compose.foundation) + api(libs.androidx.compose.foundation.layout) + api(libs.androidx.compose.material.iconsExtended) + api(libs.androidx.compose.material3) + api(libs.androidx.compose.runtime) + api(libs.androidx.compose.ui.util) + api(libs.androidx.activity.compose) + + testImplementation(libs.androidx.compose.ui.test) + androidTestImplementation(libs.androidx.compose.ui.test) +} diff --git a/ui/consumer-rules.pro b/core/designsystem/consumer-rules.pro similarity index 100% rename from ui/consumer-rules.pro rename to core/designsystem/consumer-rules.pro diff --git a/ui/proguard-rules.pro b/core/designsystem/proguard-rules.pro similarity index 100% rename from ui/proguard-rules.pro rename to core/designsystem/proguard-rules.pro diff --git a/core/designsystem/src/main/AndroidManifest.xml b/core/designsystem/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4ee22a4fb --- /dev/null +++ b/core/designsystem/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosOutlinedTextField.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosOutlinedTextField.kt similarity index 73% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosOutlinedTextField.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosOutlinedTextField.kt index 1f2ad50cb..3626b472a 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosOutlinedTextField.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosOutlinedTextField.kt @@ -1,18 +1,25 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components import androidx.compose.foundation.Image import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text import androidx.compose.material3.TextFieldColors -import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -31,12 +38,13 @@ import androidx.compose.ui.unit.sp @OptIn(ExperimentalMaterial3Api::class) @Composable fun MifosOutlinedTextField( + label: Int, value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, + modifier: Modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), maxLines: Int = 1, singleLine: Boolean = true, icon: Int? = null, - label: Int, visualTransformation: VisualTransformation = VisualTransformation.None, trailingIcon: @Composable (() -> Unit)? = null, error: Boolean = false, @@ -45,10 +53,9 @@ fun MifosOutlinedTextField( enabled: Boolean = true, readOnly: Boolean = false, imeAction: ImeAction = ImeAction.Next, - modifier: Modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), - colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors( - focusedBorderColor = MaterialTheme.colorScheme.primary - ) + colors: TextFieldColors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = MaterialTheme.colorScheme.primary, + ), ) { OutlinedTextField( value = value, @@ -60,11 +67,16 @@ fun MifosOutlinedTextField( Image( painter = painterResource(id = icon), contentDescription = null, - colorFilter = if (isSystemInDarkTheme()) ColorFilter.tint(Color.White) - else ColorFilter.tint(Color.Black) + colorFilter = if (isSystemInDarkTheme()) { + ColorFilter.tint(Color.White) + } else { + ColorFilter.tint(Color.Black) + }, ) } - } else null, + } else { + null + }, trailingIcon = trailingIcon, maxLines = maxLines, singleLine = singleLine, @@ -76,8 +88,8 @@ fun MifosOutlinedTextField( }, keyboardOptions = KeyboardOptions.Default.copy( imeAction = imeAction, - keyboardType = keyboardType - ), + keyboardType = keyboardType, + ), visualTransformation = visualTransformation, isError = error, supportingText = { @@ -85,10 +97,11 @@ fun MifosOutlinedTextField( Text( modifier = Modifier.fillMaxWidth(), text = supportingText ?: "", - color = MaterialTheme.colorScheme.error + color = MaterialTheme.colorScheme.error, ) - } else null + } else { + null + } }, ) } - diff --git a/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosRadioButton.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosRadioButton.kt new file mode 100644 index 000000000..548df9b1c --- /dev/null +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosRadioButton.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components + +import androidx.compose.foundation.layout.Row +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme + +@Composable +fun MifosRadioButton( + selected: Boolean, + onClick: () -> Unit, + textResId: Int, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + ) { + RadioButton( + selected = selected, + onClick = onClick, + ) + Text(text = stringResource(id = textResId)) + } +} + +@Preview(showSystemUi = true) +@Composable +private fun MifosRadioButtonPreview() { + MifosMobileTheme { + MifosRadioButton( + selected = false, + onClick = {}, + textResId = 1, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosScaffold.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosScaffold.kt similarity index 73% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosScaffold.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosScaffold.kt index 553ea7b7a..a7e09154c 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosScaffold.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosScaffold.kt @@ -1,5 +1,15 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components +import androidx.annotation.StringRes import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.padding @@ -15,65 +25,29 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.LayoutDirection - -data class FloatingActionButtonContent( - val onClick: (() -> Unit), - val contentColor: Color, - val content: (@Composable () -> Unit) -) - @Composable -fun MFScaffold( +fun MifosScaffold( + @StringRes topBarTitleResId: Int, navigateBack: () -> Unit, + modifier: Modifier = Modifier, floatingActionButtonContent: FloatingActionButtonContent? = null, snackbarHost: @Composable () -> Unit = {}, - scaffoldContent: @Composable (PaddingValues) -> Unit + content: @Composable (PaddingValues) -> Unit, ) { var padding by remember { mutableStateOf(PaddingValues()) } Scaffold( topBar = { MifosTopBarTitle( topBarTitleResId = topBarTitleResId, - navigateBack = navigateBack + navigateBack = navigateBack, ) }, floatingActionButton = { floatingActionButtonContent?.let { content -> FloatingActionButton( modifier = Modifier.padding( - end = padding.calculateEndPadding(LayoutDirection.Ltr) - ), - onClick = content.onClick, - contentColor = content.contentColor, - containerColor = MaterialTheme.colorScheme.primary, - content = content.content - ) - } - }, - snackbarHost = snackbarHost, - content = { - padding = it - scaffoldContent(it) - } - ) -} - -@Composable -fun MFScaffold( - topBar: @Composable () -> Unit, - floatingActionButtonContent: FloatingActionButtonContent? = null, - snackbarHost: @Composable () -> Unit = {}, - scaffoldContent: @Composable (PaddingValues) -> Unit -) { - var padding by remember { mutableStateOf(PaddingValues()) } - Scaffold( - topBar = topBar, - floatingActionButton = { - floatingActionButtonContent?.let { content -> - FloatingActionButton( - modifier = Modifier.padding( - end = padding.calculateEndPadding(LayoutDirection.Ltr) + end = padding.calculateEndPadding(LayoutDirection.Ltr), ), onClick = content.onClick, contentColor = content.contentColor, @@ -83,9 +57,49 @@ fun MFScaffold( } }, snackbarHost = snackbarHost, + modifier = modifier, content = { padding = it - scaffoldContent(it) - } + content(it) + }, ) } + +@Composable +fun MifosScaffold( + topBar: @Composable () -> Unit, + modifier: Modifier = Modifier, + floatingActionButtonContent: FloatingActionButtonContent? = null, + snackbarHost: @Composable () -> Unit = {}, + content: @Composable (PaddingValues) -> Unit, +) { + var padding by remember { mutableStateOf(PaddingValues()) } + Scaffold( + topBar = topBar, + floatingActionButton = { + floatingActionButtonContent?.let { content -> + FloatingActionButton( + modifier = Modifier.padding( + end = padding.calculateEndPadding(LayoutDirection.Ltr), + ), + onClick = content.onClick, + contentColor = content.contentColor, + containerColor = MaterialTheme.colorScheme.primary, + content = content.content, + ) + } + }, + snackbarHost = snackbarHost, + modifier = modifier, + content = { + padding = it + content(it) + }, + ) +} + +data class FloatingActionButtonContent( + val onClick: (() -> Unit), + val contentColor: Color, + val content: (@Composable () -> Unit), +) diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosSearchTextField.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosSearchTextField.kt similarity index 64% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosSearchTextField.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosSearchTextField.kt index c88fdb09e..0dcba14ff 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosSearchTextField.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosSearchTextField.kt @@ -1,4 +1,13 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.text.KeyboardActions @@ -18,15 +27,16 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue - +import androidx.compose.ui.tooling.preview.Preview +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun MifosSearchTextField( - modifier: Modifier = Modifier, value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, - onSearchDismiss: () -> Unit + onSearchDismiss: () -> Unit, + modifier: Modifier = Modifier, ) { val focusManager = LocalFocusManager.current @@ -37,13 +47,13 @@ fun MifosSearchTextField( Icon( imageVector = Icons.Default.Search, contentDescription = null, - tint = Color.DarkGray + tint = Color.DarkGray, ) }, - onValueChange = { onValueChange(it) }, + onValueChange = onValueChange, textStyle = MaterialTheme.typography.bodyLarge, trailingIcon = { - IconButton(onClick = { onSearchDismiss.invoke() }) { + IconButton(onClick = onSearchDismiss) { Icon( imageVector = Icons.Default.Close, contentDescription = "Close Icon", @@ -51,21 +61,36 @@ fun MifosSearchTextField( ) } }, - colors = TextFieldDefaults.textFieldColors( - containerColor = Color.Transparent, + colors = TextFieldDefaults.colors().copy( + focusedContainerColor = Color.Transparent, focusedIndicatorColor = Color.LightGray, unfocusedIndicatorColor = Color.LightGray, focusedTextColor = if (isSystemInDarkTheme()) Color.White else Color.Black, - unfocusedTextColor = if (isSystemInDarkTheme()) Color.White else Color.Black + unfocusedTextColor = if (isSystemInDarkTheme()) Color.White else Color.Black, ), keyboardOptions = KeyboardOptions( - imeAction = ImeAction.Search + imeAction = ImeAction.Search, ), keyboardActions = KeyboardActions( onSearch = { focusManager.clearFocus() - } + }, ), - singleLine = true + singleLine = true, ) -} \ No newline at end of file +} + +@Preview +@Composable +private fun MifosSearchTextFieldPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosSearchTextField( + value = TextFieldValue("Search"), + onValueChange = {}, + onSearchDismiss = {}, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTabPager.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTabPager.kt similarity index 80% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTabPager.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTabPager.kt index 4e073d735..4132729e2 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTabPager.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTabPager.kt @@ -1,4 +1,13 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.isSystemInDarkTheme @@ -7,7 +16,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Tab import androidx.compose.material3.TabRow @@ -17,7 +25,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.colorResource import androidx.compose.ui.unit.dp @OptIn(ExperimentalFoundationApi::class) @@ -25,10 +32,10 @@ import androidx.compose.ui.unit.dp fun MifosTabPager( pagerState: PagerState, currentPage: Int, - modifier: Modifier, tabs: List, setCurrentPage: (Int) -> Unit, - pageContent: @Composable (Int) -> Unit + modifier: Modifier = Modifier, + content: @Composable (Int) -> Unit, ) { Column(modifier = modifier) { TabRow( @@ -43,7 +50,7 @@ fun MifosTabPager( .padding(start = 36.dp, end = 36.dp), color = MaterialTheme.colorScheme.surfaceTint, ) - } + }, ) { tabs.forEachIndexed { index, tabTitle -> Tab( @@ -51,7 +58,7 @@ fun MifosTabPager( selectedContentColor = MaterialTheme.colorScheme.surfaceTint, unselectedContentColor = if (isSystemInDarkTheme()) Color.White else Color.Black, selected = currentPage == index, - onClick = { setCurrentPage(index) } + onClick = { setCurrentPage(index) }, ) { Text(text = tabTitle) } @@ -62,9 +69,8 @@ fun MifosTabPager( state = pagerState, modifier = Modifier.fillMaxWidth(), pageContent = { page -> - pageContent(page) - } + content(page) + }, ) } - -} \ No newline at end of file +} diff --git a/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTextButton.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTextButton.kt new file mode 100644 index 000000000..364185cf5 --- /dev/null +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTextButton.kt @@ -0,0 +1,124 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components + +import androidx.annotation.StringRes +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ButtonElevation +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource + +@Composable +fun MifosTextButton( + @StringRes + textResId: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Button( + modifier = modifier, + onClick = onClick, + content = { + Text(text = stringResource(id = textResId)) + }, + ) +} + +@Composable +fun MifosTextButton( + text: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + TextButton( + modifier = modifier, + onClick = onClick, + content = { + Text(text = text) + }, + ) +} + +@Composable +fun MifosTextButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + shape: Shape = ButtonDefaults.textShape, + colors: ButtonColors = ButtonDefaults.textButtonColors(), + elevation: ButtonElevation? = null, + border: BorderStroke? = null, + contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + content: @Composable (RowScope.() -> Unit), +) { + TextButton( + modifier = modifier, + onClick = onClick, + enabled = enabled, + shape = shape, + colors = colors, + elevation = elevation, + border = border, + contentPadding = contentPadding, + interactionSource = interactionSource, + content = content, + ) +} + +@Composable +fun MifosOutlinedTextButton( + textResId: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Button( + onClick = onClick, + modifier = modifier, + content = { + Text(text = stringResource(id = textResId)) + }, + ) +} + +@Composable +fun MifosIconTextButton( + text: String, + enabled: Boolean, + imageVector: ImageVector, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + TextButton( + onClick = onClick, + modifier = modifier, + enabled = enabled, + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(imageVector = imageVector, contentDescription = null) + Text(text = text) + } + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTopBar.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTopBar.kt similarity index 65% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTopBar.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTopBar.kt index fc1617e90..6fc08fed0 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTopBar.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/components/MifosTopBar.kt @@ -1,57 +1,57 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.components +import androidx.annotation.StringRes import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import org.mifos.mobile.core.ui.theme.MifosMobileTheme - +import org.mifos.mobile.core.designsystem.icons.MifosIcons @OptIn(ExperimentalMaterial3Api::class) @Composable fun MifosTopBar( - modifier: Modifier = Modifier, navigateBack: () -> Unit, title: @Composable () -> Unit, - actions: @Composable RowScope.() -> Unit = {} + modifier: Modifier = Modifier, + actions: @Composable RowScope.() -> Unit = {}, ) { TopAppBar( modifier = modifier, title = title, navigationIcon = { IconButton( - onClick = { navigateBack.invoke() } + onClick = navigateBack, ) { Icon( - imageVector = Icons.Filled.ArrowBack, + imageVector = MifosIcons.ArrowBack, contentDescription = "Back Arrow", tint = if (isSystemInDarkTheme()) Color.White else Color.Black, ) } }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = if (isSystemInDarkTheme()) + containerColor = if (isSystemInDarkTheme()) { Color(0xFF1B1B1F) - else + } else { Color(0xFFFEFBFF) + }, ), actions = actions, ) @@ -60,30 +60,31 @@ fun MifosTopBar( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MifosTopBarTitle( - modifier: Modifier = Modifier, - navigateBack: () -> Unit, + @StringRes topBarTitleResId: Int, + navigateBack: () -> Unit, + modifier: Modifier = Modifier, ) { TopAppBar( modifier = modifier, title = { Text(text = stringResource(id = topBarTitleResId)) }, navigationIcon = { IconButton( - onClick = { navigateBack.invoke() } + onClick = navigateBack, ) { Icon( - imageVector = Icons.Filled.ArrowBack, + imageVector = MifosIcons.ArrowBack, contentDescription = "Back Arrow", tint = if (isSystemInDarkTheme()) Color.White else Color.Black, ) } }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = if (isSystemInDarkTheme()) + containerColor = if (isSystemInDarkTheme()) { Color(0xFF1B1B1F) - else + } else { Color(0xFFFEFBFF) + }, ), ) } - diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosIcons.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/icons/MifosIcons.kt similarity index 52% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosIcons.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/icons/MifosIcons.kt index f8a0311ba..7b7db2da1 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosIcons.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/icons/MifosIcons.kt @@ -1,22 +1,36 @@ -package org.mifos.mobile.core.ui.component +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.icons import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.List -import androidx.compose.material.icons.automirrored.filled.MenuBook -import androidx.compose.material.icons.automirrored.filled.MenuOpen +import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.ArrowDropUp import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Error import androidx.compose.material.icons.filled.FilterList import androidx.compose.material.icons.filled.FlashOff import androidx.compose.material.icons.filled.FlashOn -import androidx.compose.material.icons.filled.List +import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Notifications import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.WifiOff +import androidx.compose.ui.graphics.vector.ImageVector object MifosIcons { + val Info: ImageVector = Icons.Default.Info + val ArrowDropUp: ImageVector = Icons.Default.ArrowDropUp + val ArrowDropDown: ImageVector = Icons.Default.ArrowDropDown + val ArrowBack = Icons.AutoMirrored.Default.ArrowBack val Edit = Icons.Default.Edit val FilterList = Icons.Filled.FilterList val FlashOn = Icons.Default.FlashOn @@ -27,4 +41,4 @@ object MifosIcons { val Error = Icons.Filled.Error val Notifications = Icons.Filled.Notifications val NavigationDrawer = Icons.Default.Menu -} \ No newline at end of file +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Color.kt similarity index 61% rename from ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Color.kt index 87440bade..5f6ec2a0b 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Color.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Color.kt @@ -1,4 +1,13 @@ -package org.mifos.mobile.core.ui.theme +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.theme import androidx.compose.ui.graphics.Color @@ -25,4 +34,4 @@ val DarkGray = Color(0xBB666666) val GreenSuccess = Color(0xff14c416) val LightSurfaceTint = Color(0xFF325CA8) -val DarkSurfaceTint = Color(0xFFAEC6FF) \ No newline at end of file +val DarkSurfaceTint = Color(0xFFAEC6FF) diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Theme.kt similarity index 61% rename from ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt rename to core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Theme.kt index b0d7064e0..b3e2da1f8 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/theme/Theme.kt +++ b/core/designsystem/src/main/kotlin/org/mifos/mobile/core/designsystem/theme/Theme.kt @@ -1,12 +1,20 @@ -package org.mifos.mobile.core.ui.theme +/* + * Copyright 2024 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 org.mifos.mobile.core.designsystem.theme -import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.* +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext private val LightThemeColors = lightColorScheme( primary = LightPrimary, @@ -16,7 +24,7 @@ private val LightThemeColors = lightColorScheme( onSurface = Black2, onSecondary = Color.Gray, outlineVariant = Color.Gray, - surfaceTint = LightSurfaceTint + surfaceTint = LightSurfaceTint, ) private val DarkThemeColors = darkColorScheme( @@ -29,7 +37,7 @@ private val DarkThemeColors = darkColorScheme( onSurface = Color.White, onSecondary = Color.White, outlineVariant = Color.White, - surfaceTint = DarkSurfaceTint + surfaceTint = DarkSurfaceTint, ) @Composable @@ -37,18 +45,13 @@ fun MifosMobileTheme( useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit, ) { - val context = LocalContext.current val colors = when { -// (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { -// if (useDarkTheme) dynamicDarkColorScheme(context) -// else dynamicLightColorScheme(context) -// } useDarkTheme -> DarkThemeColors else -> LightThemeColors } MaterialTheme( colorScheme = colors, - content = content + content = content, ) -} \ No newline at end of file +} diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 61a898f6e..a0ad276c6 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 + */ plugins { alias(libs.plugins.mifos.android.library) alias(libs.plugins.kotlin.android) diff --git a/core/model/src/androidTest/java/org/mifos/mobile/core/model/ExampleInstrumentedTest.kt b/core/model/src/androidTest/java/org/mifos/mobile/core/model/ExampleInstrumentedTest.kt deleted file mode 100644 index 50cd5a4b7..000000000 --- a/core/model/src/androidTest/java/org/mifos/mobile/core/model/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.mifos.mobile.core.model - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("org.mifos.mobile.core.model.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/core/model/src/main/AndroidManifest.xml b/core/model/src/main/AndroidManifest.xml index a5918e68a..4ee22a4fb 100644 --- a/core/model/src/main/AndroidManifest.xml +++ b/core/model/src/main/AndroidManifest.xml @@ -1,4 +1,13 @@ - + + \ No newline at end of file diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/AboutUsItem.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/AboutUsItem.kt index ffc571189..900e9b30e 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/AboutUsItem.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/AboutUsItem.kt @@ -1,11 +1,19 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import org.mifos.mobile.core.model.enums.AboutUsListItemId - data class AboutUsItem( val title: String?, val subtitle: Int? = null, val iconUrl: Int? = null, - val itemId: AboutUsListItemId + val itemId: AboutUsListItemId, ) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/AccountOptionAndBeneficiary.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/AccountOptionAndBeneficiary.kt index 38a5f68bc..78d6ca6f4 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/AccountOptionAndBeneficiary.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/AccountOptionAndBeneficiary.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeCalculationType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeCalculationType.kt index 483662502..526fea707 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeCalculationType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeCalculationType.kt @@ -1,15 +1,20 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by michaelsosnick on 12/11/16. - */ - @Parcelize data class ChargeCalculationType( var id: Int = 0, - var code: String? = null, // example "chargeCalculationType.flat" + var code: String? = null, var value: String? = null, ) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeTimeType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeTimeType.kt index 921e48934..6173c05a8 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeTimeType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/ChargeTimeType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/CheckboxStatus.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/CheckboxStatus.kt index 9d3721f07..055cb0a71 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/CheckboxStatus.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/CheckboxStatus.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Currency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Currency.kt index cda8c0aaf..8fc44de67 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Currency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Currency.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/FAQ.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/FAQ.kt index 6ca4efba3..87c89b85e 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/FAQ.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/FAQ.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable @@ -8,7 +17,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize - data class FAQ @JvmOverloads constructor( var question: String? = null, var answer: String? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Page.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Page.kt index 4c125aa73..0c64f35fa 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Page.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Page.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Timeline.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Timeline.kt index 60a89d6eb..bca1999c1 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Timeline.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Timeline.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Transaction.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Transaction.kt index 926ba0eae..ad5b2b2ba 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/Transaction.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/Transaction.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity import android.os.Parcelable @@ -30,4 +39,4 @@ data class Transaction( var reversed: Boolean? = null, - ) : Parcelable +) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/UpdatePasswordPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/UpdatePasswordPayload.kt index f47e3204e..b0fb94910 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/UpdatePasswordPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/UpdatePasswordPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity /* diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/User.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/User.kt index 63e951f65..6ff7a6b94 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/User.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/User.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/Account.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/Account.kt index 42b8e413b..5512b8887 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/Account.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/Account.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/LoanAccountsListResponse.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/LoanAccountsListResponse.kt index 6cc1f591e..bc36d7242 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/LoanAccountsListResponse.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/LoanAccountsListResponse.kt @@ -1,11 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts import org.mifos.mobile.core.model.entity.accounts.loan.LoanAccount -/** - * @author Vishwajeet - * @since 13/08/16 - */ data class LoanAccountsListResponse( var loanAccounts: List = ArrayList(), ) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/SavingAccountsListResponse.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/SavingAccountsListResponse.kt index 00efc47a4..8739fa48b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/SavingAccountsListResponse.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/SavingAccountsListResponse.kt @@ -1,11 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts import org.mifos.mobile.core.model.entity.accounts.savings.SavingAccount -/** - * @author Vishwajeet - * @since 13/08/16 - */ data class SavingAccountsListResponse( var savingsAccounts: List = ArrayList(), ) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/AmortizationType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/AmortizationType.kt index b0fb49d1e..ba640fef3 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/AmortizationType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/AmortizationType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class AmortizationType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Currency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Currency.kt index 4d4932cf3..78421f136 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Currency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Currency.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 27/2/17. - */ - @Parcelize data class Currency( var code: String? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInMonthType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInMonthType.kt index 79738e337..459dc0d27 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInMonthType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInMonthType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class DaysInMonthType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInYearType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInYearType.kt index 7155554b7..ce9e6b63c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInYearType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/DaysInYearType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class DaysInYearType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestCalculationPeriodType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestCalculationPeriodType.kt index 7b88d0320..15abed611 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestCalculationPeriodType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestCalculationPeriodType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class InterestCalculationPeriodType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRateFrequencyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRateFrequencyType.kt index d6ab56b3b..530692b06 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRateFrequencyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRateFrequencyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class InterestRateFrequencyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationCompoundingType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationCompoundingType.kt index 43f3596a8..b1e6cf981 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationCompoundingType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationCompoundingType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class InterestRecalculationCompoundingType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationData.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationData.kt index 1bd76f524..79ca2d93f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationData.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestRecalculationData.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable @@ -5,10 +14,6 @@ import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.accounts.loan.calendardata.CalendarData -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class InterestRecalculationData( var id: Int? = null, @@ -32,4 +37,4 @@ data class InterestRecalculationData( var allowCompoundingOnEod: Boolean? = null, - ) : Parcelable +) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestType.kt index d53059398..c96ce088f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/InterestType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class InterestType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanAccount.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanAccount.kt index 3bd608fa4..432c21cfa 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanAccount.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanAccount.kt @@ -1,13 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcel import android.os.Parcelable import org.mifos.mobile.core.model.entity.accounts.Account -/** - * @author Vishwajeet - * @since 22/06/16. - */ data class LoanAccount( var loanProductId: Long = 0, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanType.kt index 487ce06d2..ea32bfd0c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithAssociations.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithAssociations.kt index b105fc88b..feb8f1d45 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithAssociations.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithAssociations.kt @@ -1,14 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.Transaction -import java.util.* - -/** - * Created by Rajan Maurya on 04/03/17. - */ @Parcelize data class LoanWithAssociations( diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt index 8e6b422fa..b49dbff71 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/LoanWithdraw.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 7/6/17. - */ - @Parcelize data class LoanWithdraw( var withdrawnOnDate: String? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Periods.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Periods.kt index 77c195301..b964c3214 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Periods.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Periods.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class Periods( var period: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationCompoundingFrequencyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationCompoundingFrequencyType.kt index fca805a3f..dc7c34234 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationCompoundingFrequencyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationCompoundingFrequencyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RecalculationCompoundingFrequencyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationRestFrequencyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationRestFrequencyType.kt index 9d91f4599..4db369d53 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationRestFrequencyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RecalculationRestFrequencyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RecalculationRestFrequencyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentFrequencyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentFrequencyType.kt index d426d367e..8dde6dbea 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentFrequencyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentFrequencyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RepaymentFrequencyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentSchedule.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentSchedule.kt index 1aa25fe97..0781d95a8 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentSchedule.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RepaymentSchedule.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RepaymentSchedule( var currency: Currency? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RescheduleStrategyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RescheduleStrategyType.kt index 23339199d..2f3d930e5 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RescheduleStrategyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/RescheduleStrategyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RescheduleStrategyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt index 095401959..f1a705808 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Status.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Summary.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Summary.kt index 2dd05cf99..c2abf8fbc 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Summary.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Summary.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/TermPeriodFrequencyType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/TermPeriodFrequencyType.kt index 7b4a15174..fc2c54947 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/TermPeriodFrequencyType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/TermPeriodFrequencyType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class TermPeriodFrequencyType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Timeline.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Timeline.kt index a4f380704..49d780426 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Timeline.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/Timeline.kt @@ -1,13 +1,18 @@ /* - * This project is licensed under the open source MPL V2. - * See https://github.com/openMF/android-client/blob/master/LICENSE.md + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan import android.os.Parcel import android.os.Parcelable +@Suppress("ktlint:standard:property-naming") data class Timeline( var submittedOnDate: List? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/CalendarData.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/CalendarData.kt index 51a7b55cc..e6bfc806f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/CalendarData.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/CalendarData.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.calendardata import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class CalendarData( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/EntityType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/EntityType.kt index 7b4428f5f..80a2856a1 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/EntityType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/EntityType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.calendardata import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class EntityType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Frequency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Frequency.kt index a3033a5bc..87f227c59 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Frequency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Frequency.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.calendardata import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class Frequency( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/RepeatsOnNthDayOfMonth.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/RepeatsOnNthDayOfMonth.kt index 93b05fb1b..ba56b5514 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/RepeatsOnNthDayOfMonth.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/RepeatsOnNthDayOfMonth.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.calendardata import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class RepeatsOnNthDayOfMonth( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Type.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Type.kt index b1f72860e..6dd7cb096 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Type.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/calendardata/Type.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.calendardata import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 04/03/17. - */ - @Parcelize data class Type( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/Cell.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/Cell.kt index 4a8aaf2be..338c3ef66 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/Cell.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/Cell.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.tableview data class Cell(val data: Any) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/ColumnHeader.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/ColumnHeader.kt index 6e55d999d..90812947c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/ColumnHeader.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/ColumnHeader.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.tableview data class ColumnHeader(val data: Any) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/RowHeader.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/RowHeader.kt index d0281e835..f5e44781f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/RowHeader.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/loan/tableview/RowHeader.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.loan.tableview data class RowHeader(val data: Any) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Currency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Currency.kt index 9779dfc8f..c2dd41788 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Currency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Currency.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentDetailData.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentDetailData.kt index 99981b466..a5a1e4dc4 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentDetailData.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentDetailData.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 05/03/17. - */ - @Parcelize data class PaymentDetailData( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentType.kt index 8c8eeb43b..c73262f46 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/PaymentType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 05/03/17. - */ - @Parcelize data class PaymentType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingAccount.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingAccount.kt index 2b3489fef..407e32a18 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingAccount.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingAccount.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable @@ -5,11 +14,6 @@ import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.accounts.Account import org.mifos.mobile.core.model.entity.client.DepositType -/** - * @author Vishwajeet - * @since 22/06/16 - */ - @Parcelize data class SavingAccount( diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountApplicationPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountApplicationPayload.kt index a8d34c665..50ad756ba 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountApplicationPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountApplicationPayload.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/* - * Created by saksham on 01/July/2018 - */ - @Parcelize data class SavingsAccountApplicationPayload( diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt index 78ebc67b4..4d73910c8 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountUpdatePayload.kt @@ -1,8 +1,13 @@ -package org.mifos.mobile.core.model.entity.accounts.savings - /* - * Created by saksham on 03/July/2018 + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt index a13d0ddda..107f1666c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsAccountWithdrawPayload.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/* - * Created by saksham on 02/July/2018 - */ - @Parcelize data class SavingsAccountWithdrawPayload( var locale: String = "en", diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsWithAssociations.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsWithAssociations.kt index e9bc22cff..7f5f0cc1c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsWithAssociations.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/SavingsWithAssociations.kt @@ -1,14 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.client.DepositType -/** - * @author Vishwajeet - * @since 22/06/16 - */ - @Parcelize data class SavingsWithAssociations( @@ -58,7 +62,7 @@ data class SavingsWithAssociations( var transactions: List = ArrayList(), - ) : Parcelable { +) : Parcelable { fun isRecurring(): Boolean { return this.depositType != null && (this.depositType?.isRecurring() == true) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Status.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Status.kt index e1e124f45..46db557de 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Status.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Status.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Summary.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Summary.kt index efee806dc..738d7d563 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Summary.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Summary.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 05/03/17. - */ - @Parcelize data class Summary( diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TimeLine.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TimeLine.kt index 99d54393f..12d87fd29 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TimeLine.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TimeLine.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcel import android.os.Parcelable -/** - * Created by Rajan Maurya on 05/03/17. - */ - data class TimeLine( var submittedOnDate: List = ArrayList(), diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TransactionType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TransactionType.kt index 24b87a404..cdecc297e 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TransactionType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/TransactionType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 05/03/17. - */ - @Parcelize data class TransactionType( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Transactions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Transactions.kt index 81fb2b33c..a554faa51 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Transactions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/savings/Transactions.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.savings import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 05/03/17. - */ - @Parcelize data class Transactions( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/ShareAccount.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/ShareAccount.kt index 0518adee0..a8de034e8 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/ShareAccount.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/ShareAccount.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.share import android.os.Parcelable @@ -6,7 +15,6 @@ import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.accounts.Account import org.mifos.mobile.core.model.entity.accounts.savings.Currency - @Parcelize data class ShareAccount( @@ -37,4 +45,4 @@ data class ShareAccount( @Expose var timeline: Timeline? = null, - ) : Account(), Parcelable +) : Account(), Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Status.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Status.kt index a0227fdd8..b17c13391 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Status.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Status.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.share import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Timeline.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Timeline.kt index 41825f5a8..187fa90b0 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Timeline.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/accounts/share/Timeline.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.accounts.share import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/Beneficiary.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/Beneficiary.kt index 378b4845c..b8b68d61f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/Beneficiary.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/Beneficiary.kt @@ -1,13 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.beneficiary import android.os.Parcelable import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.templates.account.AccountType -/** - * Created by dilpreet on 14/6/17. - */ - @Parcelize data class Beneficiary( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryDetail.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryDetail.kt index ea549e910..3d04973cc 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryDetail.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryDetail.kt @@ -1,6 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.beneficiary -/* - * Created by saksham on 18/June/2018 - */ class BeneficiaryDetail(var accountNumber: String?, var beneficiaryName: String?) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryPayload.kt index 988171e9c..2ac17ad23 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryPayload.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.beneficiary import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 16/6/17. - */ - @Parcelize data class BeneficiaryPayload( internal var locale: String = "en_GB", diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryUpdatePayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryUpdatePayload.kt index ca671dddc..f18f92f73 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryUpdatePayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/beneficiary/BeneficiaryUpdatePayload.kt @@ -1,8 +1,13 @@ -package org.mifos.mobile.core.model.entity.beneficiary - -/** - * Created by dilpreet on 16/6/17. +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.beneficiary data class BeneficiaryUpdatePayload @JvmOverloads constructor( var name: String? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Client.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Client.kt index 9dbfc3b36..e6bcae81c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Client.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Client.kt @@ -1,13 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.model.entity.Timeline -/** - * @author Vishwajeet - * @since 20/06/16 - */ @Parcelize data class Client( var id: Int = 0, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientAccounts.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientAccounts.kt index 6b535fbf3..176510f81 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientAccounts.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientAccounts.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable @@ -6,7 +15,6 @@ import org.mifos.mobile.core.model.entity.accounts.loan.LoanAccount import org.mifos.mobile.core.model.entity.accounts.savings.SavingAccount import org.mifos.mobile.core.model.entity.accounts.share.ShareAccount - @Parcelize data class ClientAccounts( var loanAccounts: List = ArrayList(), @@ -14,7 +22,7 @@ data class ClientAccounts( var shareAccounts: List = ArrayList(), - ) : Parcelable { +) : Parcelable { fun recurringSavingsAccounts(): List { return getSavingsAccounts(true) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientClassification.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientClassification.kt index 5ba9cb265..a93631ef9 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientClassification.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientClassification.kt @@ -1,11 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 10/7/17. - */ @Parcelize data class ClientClassification( var id: Int, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientType.kt index 24b8fdb93..e9c39547b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/ClientType.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 10/7/17. - */ - @Parcelize data class ClientType( var id: Int, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Currency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Currency.kt index 4c5e2d783..5b526f29b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Currency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Currency.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/DepositType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/DepositType.kt index 94560902b..f6bdc79f9 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/DepositType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/DepositType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable @@ -31,7 +40,8 @@ data class DepositType( ) { SAVINGS(100, "depositAccountType.savingsDeposit", ApiEndPoints.SAVINGS_ACCOUNTS), FIXED(200, "depositAccountType.fixedDeposit", ApiEndPoints.SAVINGS_ACCOUNTS), - RECURRING(300, "depositAccountType.recurringDeposit", ApiEndPoints.RECURRING_ACCOUNTS); + RECURRING(300, "depositAccountType.recurringDeposit", ApiEndPoints.RECURRING_ACCOUNTS), + ; companion object { diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Gender.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Gender.kt index 423996f32..5b3411089 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Gender.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Gender.kt @@ -1,11 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 10/7/17. - */ @Parcelize data class Gender( var id: Int, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Group.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Group.kt index 2c3cf638a..87ca0ce21 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Group.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Group.kt @@ -1,11 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by dilpreet on 10/7/17. - */ @Parcelize data class Group( var id: Int, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Status.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Status.kt index 3c71f1de7..1af4e8a88 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Status.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Status.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 22/10/16. - */ - @Parcelize data class Status( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Type.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Type.kt index ecf18563a..8c07f846b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Type.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/client/Type.kt @@ -1,12 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.client import android.os.Parcelable import kotlinx.parcelize.Parcelize -/** - * Created by Rajan Maurya on 23/02/17. - */ - @Parcelize data class Type( var id: Int? = null, diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorApplicationPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorApplicationPayload.kt index 22993d852..86d091516 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorApplicationPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorApplicationPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.guarantor import com.google.gson.annotations.SerializedName @@ -18,5 +27,5 @@ data class GuarantorApplicationPayload( var lastName: String?, @SerializedName("city") - var city: String? = "" + var city: String? = "", ) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorPayload.kt index ba85a240f..9cf9ebd3b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.guarantor /* @@ -5,8 +14,8 @@ package org.mifos.mobile.core.model.entity.guarantor */ import android.os.Parcelable -import kotlinx.parcelize.Parcelize import kotlinx.android.parcel.RawValue +import kotlinx.parcelize.Parcelize @Parcelize data class GuarantorPayload( @@ -25,5 +34,5 @@ data class GuarantorPayload( var loanId: Long? = null, - var status: Boolean? = true + var status: Boolean? = true, ) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorTemplatePayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorTemplatePayload.kt index 31f2c0fd4..e469998e3 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorTemplatePayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorTemplatePayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.guarantor /* diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorType.kt index d81f049ad..4c4d11f13 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/guarantor/GuarantorType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.guarantor import android.os.Parcelable @@ -12,4 +21,4 @@ class GuarantorType( var id: Long? = null, var value: String? = null, var code: String? = null, -): Parcelable +) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Arg.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Arg.kt index 57d582edc..0ae6ad61a 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Arg.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Arg.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.mifoserror import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt index a104f531d..5d7d10c27 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/Errors.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.mifoserror import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt index c53e68f2d..196d3620b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/mifoserror/MifosError.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.mifoserror import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationRegisterPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationRegisterPayload.kt index b587b66fd..e6c59f19b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationRegisterPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationRegisterPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.notification /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationUserDetail.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationUserDetail.kt index e18952bef..63d9bf540 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationUserDetail.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/notification/NotificationUserDetail.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.notification /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/AccountDetail.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/AccountDetail.kt index 4f79a98dd..aab08639b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/AccountDetail.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/AccountDetail.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.payload /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoansPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoansPayload.kt index 1298ce80b..696c7a4d5 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoansPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoansPayload.kt @@ -1,6 +1,11 @@ /* - * This project is licensed under the open source MPL V2. - * See https://github.com/openMF/android-client/blob/master/LICENSE.md + * Copyright 2024 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 org.mifos.mobile.core.model.entity.payload diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoginPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoginPayload.kt index 819b77bae..64e49ab18 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoginPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/LoginPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.payload /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/ReviewTransferPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/ReviewTransferPayload.kt index ae5ce801d..eef3040a9 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/ReviewTransferPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/ReviewTransferPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.payload import org.mifos.mobile.core.model.entity.templates.account.AccountOption @@ -6,5 +15,5 @@ data class ReviewTransferPayload( var payToAccount: AccountOption? = null, var payFromAccount: AccountOption? = null, var amount: String = "", - var review: String = "" -) \ No newline at end of file + var review: String = "", +) diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/TransferPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/TransferPayload.kt index 045339537..2144c423c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/TransferPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/payload/TransferPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.payload import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/RegisterPayload.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/RegisterPayload.kt index f8fdf9e8d..3bc767a5d 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/RegisterPayload.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/RegisterPayload.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.register /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/UserVerify.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/UserVerify.kt index 0ffc62738..8bdd6002a 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/UserVerify.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/register/UserVerify.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.register /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOption.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOption.kt index a4ec406ca..777d2f768 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOption.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOption.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.account import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOptionsTemplate.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOptionsTemplate.kt index 4bfd55775..463ab71c9 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOptionsTemplate.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountOptionsTemplate.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.account import android.os.Parcelable @@ -16,5 +25,5 @@ data class AccountOptionsTemplate( var fromAccountTypeOptions: List = ArrayList(), - var toAccountTypeOptions: List = ArrayList() + var toAccountTypeOptions: List = ArrayList(), ) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountType.kt index f7fbe9dbe..df804ef2a 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/account/AccountType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.account import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/AccountTypeOption.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/AccountTypeOption.kt index 595da58aa..d4b78be7d 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/AccountTypeOption.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/AccountTypeOption.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.beneficiary import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/BeneficiaryTemplate.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/BeneficiaryTemplate.kt index d055625ce..5df1acae7 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/BeneficiaryTemplate.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/beneficiary/BeneficiaryTemplate.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.beneficiary import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountLinkingOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountLinkingOptions.kt index f713340cb..13fbc4f9f 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountLinkingOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountLinkingOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountingRule.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountingRule.kt index 1aa6a29d1..675ce0a8a 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountingRule.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AccountingRule.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AllowAttributeOverrides.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AllowAttributeOverrides.kt index bf6745d04..813dc78ef 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AllowAttributeOverrides.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AllowAttributeOverrides.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AmortizationTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AmortizationTypeOptions.kt index 515e218c2..e6f8566b5 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AmortizationTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/AmortizationTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeAppliesTo.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeAppliesTo.kt index ca9b80ff0..44e2c6c1c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeAppliesTo.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeAppliesTo.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeOptions.kt index a74cc102a..5ca7351df 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable @@ -34,4 +43,4 @@ data class ChargeOptions( var taxGroup: TaxGroup? = null, - ) : Parcelable +) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargePaymentMode.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargePaymentMode.kt index 2f3f4a9fc..04a1ffc44 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargePaymentMode.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ChargePaymentMode.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Currency.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Currency.kt index 3e0326a0e..a73969ed1 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Currency.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Currency.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/FundOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/FundOptions.kt index 5e194a812..a2063b881 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/FundOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/FundOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestRateFrequencyTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestRateFrequencyTypeOptions.kt index 9ef0a2b1f..2c325386c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestRateFrequencyTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestRateFrequencyTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestTypeOptions.kt index 795f1593f..d9c07b690 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/InterestTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanCollateralOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanCollateralOptions.kt index af4785f11..3164fd0e4 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanCollateralOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanCollateralOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanOfficerOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanOfficerOptions.kt index 8b1b5291e..70ced22ad 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanOfficerOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanOfficerOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanPurposeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanPurposeOptions.kt index 333264a26..f1c9f9239 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanPurposeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanPurposeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanTemplate.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanTemplate.kt index e84b4f8c5..9e824d657 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanTemplate.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/LoanTemplate.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable @@ -11,7 +20,6 @@ import org.mifos.mobile.core.model.entity.accounts.loan.InterestRateFrequencyTyp import org.mifos.mobile.core.model.entity.accounts.loan.InterestType import org.mifos.mobile.core.model.entity.accounts.loan.RepaymentFrequencyType import org.mifos.mobile.core.model.entity.accounts.loan.TermPeriodFrequencyType -import java.util.* /** * Created by Rajan Maurya on 15/07/16. @@ -132,7 +140,7 @@ data class LoanTemplate( var accountLinkingOptions: List = ArrayList(), - ) : Parcelable { +) : Parcelable { /** * Required to set default value to the Fund spinner * diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Product.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Product.kt index f2b185146..9b3b40a62 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Product.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Product.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable @@ -118,4 +127,4 @@ data class Product( var allowAttributeOverrides: AllowAttributeOverrides? = null, - ) : Parcelable +) : Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ProductOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ProductOptions.kt index 49658f25f..64684b943 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ProductOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/ProductOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyDaysOfWeekTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyDaysOfWeekTypeOptions.kt index 6656c05ae..608fcdd01 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyDaysOfWeekTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyDaysOfWeekTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyNthDayTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyNthDayTypeOptions.kt index a6457a4a2..bae54ff1e 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyNthDayTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyNthDayTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyTypeOptions.kt index f620b4673..753470d1b 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/RepaymentFrequencyTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TaxGroup.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TaxGroup.kt index 3697fb556..9cc691860 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TaxGroup.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TaxGroup.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TermFrequencyTypeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TermFrequencyTypeOptions.kt index f36783ab2..4da109917 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TermFrequencyTypeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TermFrequencyTypeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Timeline.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Timeline.kt index fd08aa5a1..85c618a50 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Timeline.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/Timeline.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TransactionProcessingStrategyOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TransactionProcessingStrategyOptions.kt index e01004718..2f6b81abd 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TransactionProcessingStrategyOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/loans/TransactionProcessingStrategyOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.loans import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeAppliesTo.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeAppliesTo.kt index 85e5748c0..ea68571bf 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeAppliesTo.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeAppliesTo.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeCalculationType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeCalculationType.kt index c6e3164f3..96cd8d6bf 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeCalculationType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeCalculationType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeOptions.kt index 3b7ef1b71..b293b6165 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargePaymentMode.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargePaymentMode.kt index a94e175c2..82d09f441 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargePaymentMode.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargePaymentMode.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeTimeType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeTimeType.kt index 971a9a348..121600af0 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeTimeType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ChargeTimeType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ProductOptions.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ProductOptions.kt index e84dcb878..426398fe7 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ProductOptions.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/ProductOptions.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings import android.os.Parcelable diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/SavingsAccountTemplate.kt b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/SavingsAccountTemplate.kt index cdd01bd7e..398b2e1de 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/SavingsAccountTemplate.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/entity/templates/savings/SavingsAccountTemplate.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.entity.templates.savings /* diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AboutUsListItemId.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AboutUsListItemId.kt index 7fa3aae92..f04632b45 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AboutUsListItemId.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AboutUsListItemId.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums enum class AboutUsListItemId { @@ -13,4 +22,4 @@ enum class AboutUsListItemId { SOURCE_CODE, LICENSES_STRING_WITH_VALUE, -} \ No newline at end of file +} diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AccountType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AccountType.kt index 0deaa6c18..84e396670 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AccountType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AccountType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AppTheme.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AppTheme.kt index f34492c78..e8305c37a 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/AppTheme.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/AppTheme.kt @@ -1,11 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums -import android.os.Build - enum class AppTheme( - val themeName: String + val themeName: String, ) { SYSTEM(themeName = "System Theme"), LIGHT(themeName = "Light Theme"), - DARK(themeName = "Dark Theme") + DARK(themeName = "Dark Theme"), } diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/BeneficiaryState.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/BeneficiaryState.kt index bacc32422..3e55880e2 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/BeneficiaryState.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/BeneficiaryState.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/BiometricCapability.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/BiometricCapability.kt index 46699bb59..dff8bfb1c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/BiometricCapability.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/BiometricCapability.kt @@ -1,5 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums enum class BiometricCapability { - HAS_BIOMETRIC_AUTH, NOT_ENROLLED, NOT_SUPPORTED + HAS_BIOMETRIC_AUTH, + NOT_ENROLLED, + NOT_SUPPORTED, } diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/ChargeType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/ChargeType.kt index 941422958..8c3295e67 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/ChargeType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/ChargeType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/GuarantorState.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/GuarantorState.kt index 69f030af9..a3b9edf3c 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/GuarantorState.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/GuarantorState.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /* diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/LoanState.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/LoanState.kt index 70009d2a2..56c6dbee8 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/LoanState.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/LoanState.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/MifosAppLanguage.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/MifosAppLanguage.kt index 040d3da8b..fa07f0350 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/MifosAppLanguage.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/MifosAppLanguage.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums enum class MifosAppLanguage(val code: String, val displayName: String) { @@ -18,7 +27,8 @@ enum class MifosAppLanguage(val code: String, val displayName: String) { PORTUGUESE("pt", "Português"), RUSSIAN("ru", "русский"), SWAHILI("sw", "Kiswahili"), - FARSI("fa", "فارسی"); + FARSI("fa", "فارسی"), + ; companion object { fun fromCode(code: String): MifosAppLanguage { diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/RequestAccessType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/RequestAccessType.kt index 4a729cdec..3b41cd047 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/RequestAccessType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/RequestAccessType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** @@ -11,5 +20,5 @@ enum class RequestAccessType { EXTERNAL_STORAGE_WRITE, - READ_MEDIA_IMAGES + READ_MEDIA_IMAGES, } diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/SavingsAccountState.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/SavingsAccountState.kt index bb7cf5987..719f259a2 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/SavingsAccountState.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/SavingsAccountState.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /* diff --git a/core/model/src/main/java/org/mifos/mobile/core/model/enums/TransferType.kt b/core/model/src/main/java/org/mifos/mobile/core/model/enums/TransferType.kt index 6bf786c0a..8550405e6 100644 --- a/core/model/src/main/java/org/mifos/mobile/core/model/enums/TransferType.kt +++ b/core/model/src/main/java/org/mifos/mobile/core/model/enums/TransferType.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.model.enums /** diff --git a/core/model/src/test/java/org/mifos/mobile/core/model/ExampleUnitTest.kt b/core/model/src/test/java/org/mifos/mobile/core/model/ExampleUnitTest.kt deleted file mode 100644 index a0aeba03f..000000000 --- a/core/model/src/test/java/org/mifos/mobile/core/model/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.mifos.mobile.core.model - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index 0f9222282..812db0897 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 + */ plugins { alias(libs.plugins.mifos.android.library) alias(libs.plugins.mifos.android.hilt) diff --git a/core/network/src/androidTest/java/org/mifos/mobile/core/network/ExampleInstrumentedTest.kt b/core/network/src/androidTest/java/org/mifos/mobile/core/network/ExampleInstrumentedTest.kt deleted file mode 100644 index 0055f46b4..000000000 --- a/core/network/src/androidTest/java/org/mifos/mobile/core/network/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.mifos.mobile.core.network - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.mifos.mobile.core.network.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/core/network/src/main/AndroidManifest.xml b/core/network/src/main/AndroidManifest.xml index a5918e68a..4ee22a4fb 100644 --- a/core/network/src/main/AndroidManifest.xml +++ b/core/network/src/main/AndroidManifest.xml @@ -1,4 +1,13 @@ - + + \ No newline at end of file diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/BaseApiManager.kt b/core/network/src/main/java/org/mifos/mobile/core/network/BaseApiManager.kt index 4a327d31b..6508a6242 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/BaseApiManager.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/BaseApiManager.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network import org.mifos.mobile.core.network.services.AuthenticationService @@ -12,12 +21,8 @@ import org.mifos.mobile.core.network.services.RegistrationService import org.mifos.mobile.core.network.services.SavingAccountsListService import org.mifos.mobile.core.network.services.ThirdPartyTransferService import org.mifos.mobile.core.network.services.UserDetailsService -import org.mifos.mobile.core.network.services.* import javax.inject.Inject -/** - * @since 13/6/16 - */ class BaseApiManager @Inject constructor( private val authenticationService: AuthenticationService, private val clientsService: ClientService, @@ -30,7 +35,7 @@ class BaseApiManager @Inject constructor( private val registrationService: RegistrationService, private val notificationService: NotificationService, private val userDetailsService: UserDetailsService, - private val guarantorService: GuarantorService + private val guarantorService: GuarantorService, ) { val authenticationApi: AuthenticationService get() = authenticationService diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/DataManager.kt b/core/network/src/main/java/org/mifos/mobile/core/network/DataManager.kt index f0cdbe7ca..d49650a80 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/DataManager.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/DataManager.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network import io.reactivex.Observable @@ -6,15 +15,32 @@ import org.mifos.mobile.core.datastore.DatabaseHelper import org.mifos.mobile.core.datastore.PreferencesHelper import org.mifos.mobile.core.datastore.model.Charge import org.mifos.mobile.core.datastore.model.MifosNotification -import org.mifos.mobile.core.model.entity.* -import org.mifos.mobile.core.model.entity.accounts.loan.* -import org.mifos.mobile.core.model.entity.accounts.savings.* -import org.mifos.mobile.core.model.entity.beneficiary.* -import org.mifos.mobile.core.model.entity.client.* -import org.mifos.mobile.core.model.entity.guarantor.* -import org.mifos.mobile.core.model.entity.notification.* -import org.mifos.mobile.core.model.entity.payload.* -import org.mifos.mobile.core.model.entity.register.* +import org.mifos.mobile.core.model.entity.Page +import org.mifos.mobile.core.model.entity.Transaction +import org.mifos.mobile.core.model.entity.UpdatePasswordPayload +import org.mifos.mobile.core.model.entity.User +import org.mifos.mobile.core.model.entity.accounts.loan.LoanAccount +import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations +import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithdraw +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountWithdrawPayload +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations +import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary +import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload +import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryUpdatePayload +import org.mifos.mobile.core.model.entity.client.Client +import org.mifos.mobile.core.model.entity.client.ClientAccounts +import org.mifos.mobile.core.model.entity.guarantor.GuarantorApplicationPayload +import org.mifos.mobile.core.model.entity.guarantor.GuarantorPayload +import org.mifos.mobile.core.model.entity.guarantor.GuarantorTemplatePayload +import org.mifos.mobile.core.model.entity.notification.NotificationRegisterPayload +import org.mifos.mobile.core.model.entity.notification.NotificationUserDetail +import org.mifos.mobile.core.model.entity.payload.LoansPayload +import org.mifos.mobile.core.model.entity.payload.LoginPayload +import org.mifos.mobile.core.model.entity.payload.TransferPayload +import org.mifos.mobile.core.model.entity.register.RegisterPayload +import org.mifos.mobile.core.model.entity.register.UserVerify import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate import org.mifos.mobile.core.model.entity.templates.beneficiary.BeneficiaryTemplate import org.mifos.mobile.core.model.entity.templates.loans.LoanTemplate @@ -22,10 +48,8 @@ import org.mifos.mobile.core.model.entity.templates.savings.SavingsAccountTempla import javax.inject.Inject import javax.inject.Singleton -/** - * @since 13/6/16. - */ @Singleton +@Suppress("TooManyFunctions") class DataManager @Inject constructor( val preferencesHelper: PreferencesHelper, private val baseApiManager: BaseApiManager, @@ -56,7 +80,11 @@ class DataManager @Inject constructor( } suspend fun getRecentTransactions(offset: Int, limit: Int): Page { - return baseApiManager.recentTransactionsApi.getRecentTransactionsList(clientId, offset, limit) + return baseApiManager.recentTransactionsApi.getRecentTransactionsList( + clientId, + offset, + limit, + ) } suspend fun getClientCharges(clientId: Long): Page { @@ -73,11 +101,20 @@ class DataManager @Inject constructor( return baseApiManager.clientChargeApi.getSavingsAccountChargeList(savingsId) } - suspend fun getSavingsWithAssociations(accountId: Long?, associationType: String?): SavingsWithAssociations { - return baseApiManager.savingAccountsListApi.getSavingsWithAssociations(accountId, associationType) + suspend fun getSavingsWithAssociations( + accountId: Long?, + associationType: String?, + ): SavingsWithAssociations { + return baseApiManager.savingAccountsListApi.getSavingsWithAssociations( + accountId, + associationType, + ) } - suspend fun accountTransferTemplate(accountId: Long?, accountType: Long?): AccountOptionsTemplate = + suspend fun accountTransferTemplate( + accountId: Long?, + accountType: Long?, + ): AccountOptionsTemplate = baseApiManager.savingAccountsListApi.accountTransferTemplate(accountId, accountType) suspend fun makeTransfer(transferPayload: TransferPayload?): ResponseBody { @@ -92,11 +129,17 @@ class DataManager @Inject constructor( return baseApiManager.savingAccountsListApi.submitSavingAccountApplication(payload) } - suspend fun updateSavingsAccount(accountId: Long?, payload: SavingsAccountUpdatePayload?): ResponseBody { + suspend fun updateSavingsAccount( + accountId: Long?, + payload: SavingsAccountUpdatePayload?, + ): ResponseBody { return baseApiManager.savingAccountsListApi.updateSavingsAccountUpdate(accountId, payload) } - suspend fun submitWithdrawSavingsAccount(accountId: String?, payload: SavingsAccountWithdrawPayload?): ResponseBody { + suspend fun submitWithdrawSavingsAccount( + accountId: String?, + payload: SavingsAccountWithdrawPayload?, + ): ResponseBody { return baseApiManager.savingAccountsListApi.submitWithdrawSavingsAccount(accountId, payload) } @@ -104,11 +147,15 @@ class DataManager @Inject constructor( return baseApiManager.loanAccountsListApi.getLoanAccountsDetail(loanId) } - suspend fun getLoanWithAssociations(associationType: String?, loanId: Long?): LoanWithAssociations { + suspend fun getLoanWithAssociations( + associationType: String?, + loanId: Long?, + ): LoanWithAssociations { return baseApiManager.loanAccountsListApi.getLoanWithAssociations(loanId, associationType) } - suspend fun loanTemplate(): LoanTemplate = baseApiManager.loanAccountsListApi.getLoanTemplate(clientId) + suspend fun loanTemplate(): LoanTemplate = + baseApiManager.loanAccountsListApi.getLoanTemplate(clientId) suspend fun getLoanTemplateByProduct(productId: Int?): LoanTemplate { return baseApiManager.loanAccountsListApi.getLoanTemplateByProduct(clientId, productId) @@ -126,15 +173,20 @@ class DataManager @Inject constructor( return baseApiManager.loanAccountsListApi.withdrawLoanAccount(loanId, loanWithdraw) } - suspend fun beneficiaryList(): List = baseApiManager.beneficiaryApi.beneficiaryList() + suspend fun beneficiaryList(): List = + baseApiManager.beneficiaryApi.beneficiaryList() - suspend fun beneficiaryTemplate(): BeneficiaryTemplate = baseApiManager.beneficiaryApi.beneficiaryTemplate() + suspend fun beneficiaryTemplate(): BeneficiaryTemplate = + baseApiManager.beneficiaryApi.beneficiaryTemplate() suspend fun createBeneficiary(beneficiaryPayload: BeneficiaryPayload?): ResponseBody { return baseApiManager.beneficiaryApi.createBeneficiary(beneficiaryPayload) } - suspend fun updateBeneficiary(beneficiaryId: Long?, payload: BeneficiaryUpdatePayload?): ResponseBody { + suspend fun updateBeneficiary( + beneficiaryId: Long?, + payload: BeneficiaryUpdatePayload?, + ): ResponseBody { return baseApiManager.beneficiaryApi.updateBeneficiary(beneficiaryId, payload) } @@ -157,7 +209,7 @@ class DataManager @Inject constructor( return baseApiManager.registrationApi.verifyUser(userVerify) } - suspend fun clientLocalCharges(): Page = databaseHelper.clientCharges() + fun clientLocalCharges(): Page = databaseHelper.clientCharges() fun notifications(): List = databaseHelper.notifications() @@ -169,7 +221,10 @@ class DataManager @Inject constructor( return baseApiManager.notificationApi.registerNotification(payload) } - suspend fun updateRegisterNotification(id: Long, payload: NotificationRegisterPayload?): ResponseBody { + suspend fun updateRegisterNotification( + id: Long, + payload: NotificationRegisterPayload?, + ): ResponseBody { return baseApiManager.notificationApi.updateRegisterNotification(id, payload) } @@ -189,11 +244,18 @@ class DataManager @Inject constructor( return baseApiManager.guarantorApi.getGuarantorList(loanId) } - suspend fun createGuarantor(loanId: Long?, payload: GuarantorApplicationPayload?): ResponseBody { + suspend fun createGuarantor( + loanId: Long?, + payload: GuarantorApplicationPayload?, + ): ResponseBody { return baseApiManager.guarantorApi.createGuarantor(loanId, payload) } - suspend fun updateGuarantor(payload: GuarantorApplicationPayload?, loanId: Long?, guarantorId: Long?): ResponseBody { + suspend fun updateGuarantor( + payload: GuarantorApplicationPayload?, + loanId: Long?, + guarantorId: Long?, + ): ResponseBody { return baseApiManager.guarantorApi.updateGuarantor(payload, loanId, guarantorId) } diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/Result.kt b/core/network/src/main/java/org/mifos/mobile/core/network/Result.kt index 4d198909c..980cbdb3f 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/Result.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/Result.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network import kotlinx.coroutines.flow.Flow diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/SelfServiceOkHttpClient.kt b/core/network/src/main/java/org/mifos/mobile/core/network/SelfServiceOkHttpClient.kt index 90db53ca6..0ed48eefc 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/SelfServiceOkHttpClient.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/SelfServiceOkHttpClient.kt @@ -1,8 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network -import org.mifos.mobile.core.datastore.PreferencesHelper import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor +import org.mifos.mobile.core.datastore.PreferencesHelper import org.mifos.mobile.core.datastore.SelfServiceInterceptor import java.security.SecureRandom import java.security.cert.CertificateException @@ -15,7 +24,7 @@ import javax.net.ssl.X509TrustManager class SelfServiceOkHttpClient(private val preferences: PreferencesHelper) { // Create a trust manager that does not validate certificate chains val mifosOkHttpClient: OkHttpClient - //Interceptor :> Full Body Logger and ApiRequest Header + // Interceptor :> Full Body Logger and ApiRequest Header get() { val builder = OkHttpClient.Builder() try { @@ -25,21 +34,21 @@ class SelfServiceOkHttpClient(private val preferences: PreferencesHelper) { @Throws(CertificateException::class) override fun checkClientTrusted( chain: Array, - authType: String + authType: String, ) { } @Throws(CertificateException::class) override fun checkServerTrusted( chain: Array, - authType: String + authType: String, ) { } override fun getAcceptedIssuers(): Array { return emptyArray() } - } + }, ) // Install the all-trusting trust manager @@ -48,11 +57,11 @@ class SelfServiceOkHttpClient(private val preferences: PreferencesHelper) { // Create an ssl socket factory with our all-trusting manager val sslSocketFactory = sslContext.socketFactory - //Enable Full Body Logging + // Enable Full Body Logging val logger = HttpLoggingInterceptor() logger.level = HttpLoggingInterceptor.Level.BODY - //Set SSL certificate to OkHttpClient Builder + // Set SSL certificate to OkHttpClient Builder // builder.sslSocketFactory(sslSocketFactory) builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager) builder.hostnameVerifier { hostname, session -> true } diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/di/NetworkModule.kt b/core/network/src/main/java/org/mifos/mobile/core/network/di/NetworkModule.kt index fa6dcdf11..5cad594b8 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/di/NetworkModule.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/di/NetworkModule.kt @@ -1,11 +1,20 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.di -import org.mifos.mobile.core.datastore.PreferencesHelper import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import org.mifos.mobile.core.datastore.BaseURL +import org.mifos.mobile.core.datastore.PreferencesHelper import org.mifos.mobile.core.network.SelfServiceOkHttpClient import org.mifos.mobile.core.network.services.AuthenticationService import org.mifos.mobile.core.network.services.BeneficiaryService @@ -24,11 +33,6 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton -/** - * @author pratyush - * @since 21/8/23 - */ - @Module @InstallIn(SingletonComponent::class) object NetworkModule { @@ -115,4 +119,4 @@ object NetworkModule { fun providesUserDetailsService(retrofit: Retrofit): UserDetailsService { return retrofit.create(UserDetailsService::class.java) } -} \ No newline at end of file +} diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/AuthenticationService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/AuthenticationService.kt index e836dc1d0..d6cf6c972 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/AuthenticationService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/AuthenticationService.kt @@ -1,8 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.User import org.mifos.mobile.core.model.entity.payload.LoginPayload -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.Body import retrofit2.http.POST diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/BeneficiaryService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/BeneficiaryService.kt index f31e03194..bd2cc6a0f 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/BeneficiaryService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/BeneficiaryService.kt @@ -1,16 +1,27 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryUpdatePayload import org.mifos.mobile.core.model.entity.templates.beneficiary.BeneficiaryTemplate -import org.mifos.mobile.core.common.ApiEndPoints -import retrofit2.http.* +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path -/** - * Created by dilpreet on 14/6/17. - */ interface BeneficiaryService { @GET(ApiEndPoints.BENEFICIARIES + "/tpt") suspend fun beneficiaryList(): List diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientChargeService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientChargeService.kt index 2ff49ed9f..f8e90d532 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientChargeService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientChargeService.kt @@ -1,8 +1,17 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.datastore.model.Charge import org.mifos.mobile.core.model.entity.Page -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.GET import retrofit2.http.Path diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientService.kt index 10d880561..ce87bc438 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/ClientService.kt @@ -1,10 +1,19 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.Page import org.mifos.mobile.core.model.entity.client.Client import org.mifos.mobile.core.model.entity.client.ClientAccounts -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.GET import retrofit2.http.Path import retrofit2.http.Query diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/GuarantorService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/GuarantorService.kt index 29d7316a3..b80fef371 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/GuarantorService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/GuarantorService.kt @@ -1,14 +1,26 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody import org.mifos.mobile.core.model.entity.guarantor.GuarantorApplicationPayload import org.mifos.mobile.core.model.entity.guarantor.GuarantorPayload import org.mifos.mobile.core.model.entity.guarantor.GuarantorTemplatePayload -import retrofit2.http.* +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path -/* -* Created by saksham on 23/July/2018 -*/ interface GuarantorService { +interface GuarantorService { @GET("loans/{loanId}/guarantors/template") suspend fun getGuarantorTemplate(@Path("loanId") loanId: Long?): GuarantorTemplatePayload diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/LoanAccountsListService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/LoanAccountsListService.kt index d9a09bb8c..d53f0840f 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/LoanAccountsListService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/LoanAccountsListService.kt @@ -1,19 +1,29 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import io.reactivex.Observable import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.accounts.loan.LoanAccount import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithdraw import org.mifos.mobile.core.model.entity.payload.LoansPayload import org.mifos.mobile.core.model.entity.templates.loans.LoanTemplate -import org.mifos.mobile.core.common.ApiEndPoints -import retrofit2.http.* +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path +import retrofit2.http.Query -/** - * @author Vishwajeet - * @since 23/6/16. - */ interface LoanAccountsListService { @GET(ApiEndPoints.LOANS + "/{loanId}/") fun getLoanAccountsDetail(@Path("loanId") loanId: Long): Observable? diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/NotificationService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/NotificationService.kt index 5ddb95cea..82679b01b 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/NotificationService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/NotificationService.kt @@ -1,14 +1,24 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.notification.NotificationRegisterPayload import org.mifos.mobile.core.model.entity.notification.NotificationUserDetail -import org.mifos.mobile.core.common.ApiEndPoints -import retrofit2.http.* +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path -/** - * Created by dilpreet on 26/09/17. - */ interface NotificationService { @GET(ApiEndPoints.DEVICE + "/registration/client/{clientId}") suspend fun getUserNotificationId(@Path("clientId") clientId: Long): NotificationUserDetail diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/RecentTransactionsService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/RecentTransactionsService.kt index 324b6697f..1f54d6173 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/RecentTransactionsService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/RecentTransactionsService.kt @@ -1,16 +1,21 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.Page import org.mifos.mobile.core.model.entity.Transaction -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.GET import retrofit2.http.Path import retrofit2.http.Query -/** - * @author Vishwajeet - * @since 10/08/2016 - */ interface RecentTransactionsService { @GET(ApiEndPoints.CLIENTS + "/{clientId}/transactions") suspend fun getRecentTransactionsList( diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/RegistrationService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/RegistrationService.kt index 7d3cdd080..861c56b4c 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/RegistrationService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/RegistrationService.kt @@ -1,15 +1,21 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.register.RegisterPayload import org.mifos.mobile.core.model.entity.register.UserVerify -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.Body import retrofit2.http.POST -/** - * Created by dilpreet on 31/7/17. - */ interface RegistrationService { @POST(ApiEndPoints.REGISTRATION) suspend fun registerUser(@Body registerPayload: RegisterPayload?): ResponseBody diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/SavingAccountsListService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/SavingAccountsListService.kt index 31cff8076..4cf293164 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/SavingAccountsListService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/SavingAccountsListService.kt @@ -1,6 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountApplicationPayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountUpdatePayload import org.mifos.mobile.core.model.entity.accounts.savings.SavingsAccountWithdrawPayload @@ -8,13 +18,13 @@ import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociatio import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate import org.mifos.mobile.core.model.entity.templates.savings.SavingsAccountTemplate -import org.mifos.mobile.core.common.ApiEndPoints -import retrofit2.http.* +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path +import retrofit2.http.Query -/** - * @author Vishwajeet - * @since 21/6/16. - */ interface SavingAccountsListService { @GET(ApiEndPoints.SAVINGS_ACCOUNTS + "/{accountId}") suspend fun getSavingsWithAssociations( diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt index d8dcc1f0d..a0d33f5f3 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/ThirdPartyTransferService.kt @@ -1,16 +1,22 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody +import org.mifos.mobile.core.common.ApiEndPoints import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.model.entity.templates.account.AccountOptionsTemplate -import org.mifos.mobile.core.common.ApiEndPoints import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.POST -/** - * Created by dilpreet on 21/6/17. - */ interface ThirdPartyTransferService { @GET(ApiEndPoints.ACCOUNT_TRANSFER + "/template?type=tpt") suspend fun accountTransferTemplate(): AccountOptionsTemplate diff --git a/core/network/src/main/java/org/mifos/mobile/core/network/services/UserDetailsService.kt b/core/network/src/main/java/org/mifos/mobile/core/network/services/UserDetailsService.kt index bfe2b661e..31a14b1f3 100644 --- a/core/network/src/main/java/org/mifos/mobile/core/network/services/UserDetailsService.kt +++ b/core/network/src/main/java/org/mifos/mobile/core/network/services/UserDetailsService.kt @@ -1,14 +1,21 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.network.services import okhttp3.ResponseBody -import org.mifos.mobile.core.model.entity.UpdatePasswordPayload import org.mifos.mobile.core.common.ApiEndPoints +import org.mifos.mobile.core.model.entity.UpdatePasswordPayload import retrofit2.http.Body import retrofit2.http.PUT -/* -* Created by saksham on 13/July/2018 -*/ interface UserDetailsService { +interface UserDetailsService { @PUT(ApiEndPoints.USER) suspend fun updateAccountPassword(@Body payload: UpdatePasswordPayload?): ResponseBody } diff --git a/core/network/src/test/java/org/mifos/mobile/core/network/ExampleUnitTest.kt b/core/network/src/test/java/org/mifos/mobile/core/network/ExampleUnitTest.kt deleted file mode 100644 index 75c4346a8..000000000 --- a/core/network/src/test/java/org/mifos/mobile/core/network/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.mifos.mobile.core.network - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/ui/.gitignore b/core/ui/.gitignore similarity index 100% rename from ui/.gitignore rename to core/ui/.gitignore diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts new file mode 100644 index 000000000..46f16bd0c --- /dev/null +++ b/core/ui/build.gradle.kts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 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 + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) +} + +android { + defaultConfig { + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + namespace = "org.mifos.mobile.core" +} + +dependencies { + api(projects.core.designsystem) + api(projects.core.model) + api(projects.core.common) + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.9.0") + + testImplementation(libs.androidx.compose.ui.test) + androidTestImplementation(libs.bundles.androidx.compose.ui.test) +} diff --git a/core/ui/consumer-rules.pro b/core/ui/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb diff --git a/core/ui/proguard-rules.pro b/core/ui/proguard-rules.pro new file mode 100644 index 000000000..ff59496d8 --- /dev/null +++ b/core/ui/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle.kts. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/core/ui/src/main/AndroidManifest.xml b/core/ui/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4ee22a4fb --- /dev/null +++ b/core/ui/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt new file mode 100644 index 000000000..1ffca5488 --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews + +@Composable +fun AboutUsItemCard( + title: String, + @StringRes subtitle: Int?, + @DrawableRes iconUrl: Int?, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier.padding(16.dp), + ) { + iconUrl?.let { painterResource(id = it) }?.let { + Image( + painter = it, + contentDescription = null, + modifier = Modifier.padding(end = 8.dp), + ) + } + Column { + Text( + text = title, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.padding(end = 8.dp), + ) + if (subtitle != null) { + Text( + text = stringResource(id = subtitle), + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.padding(end = 8.dp), + ) + } + } + } +} + +@DevicePreviews +@Composable +private fun AboutUsItemCardPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + AboutUsItemCard( + title = "About Us", + modifier = modifier, + subtitle = null, + iconUrl = null, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt similarity index 53% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt index e04cf4b9d..3b94a30a4 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/EmptyDataView.kt @@ -1,9 +1,19 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon @@ -13,42 +23,63 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun EmptyDataView( - modifier: Modifier = Modifier.fillMaxSize(), - icon: Int? = null, + @StringRes error: Int, + modifier: Modifier = Modifier.fillMaxSize(), + @DrawableRes + icon: Int? = null, errorString: String? = null, ) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( modifier = Modifier .size(100.dp) .padding(bottom = 12.dp), - imageVector = if(icon != null) ImageVector.vectorResource(id = icon) - else MifosIcons.Error, + imageVector = if (icon != null) { + ImageVector.vectorResource(id = icon) + } else { + MifosIcons.Error + }, contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondary + tint = MaterialTheme.colorScheme.onSecondary, ) Text( - modifier= Modifier.padding(horizontal = 20.dp), + modifier = Modifier.padding(horizontal = 20.dp), text = errorString ?: stringResource(id = error), style = TextStyle(fontSize = 20.sp), color = MaterialTheme.colorScheme.onSecondary, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun EmptyDataViewPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + EmptyDataView( + error = R.string.no_internet, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt similarity index 62% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt index 7a849068d..849ee2143 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/FaqItemHolder.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.animation.AnimatedVisibility @@ -11,9 +20,7 @@ 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.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -23,19 +30,23 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun FaqItemHolder( - question: String?, - answer: String?, + index: Int, isSelected: Boolean, onItemSelected: (Int) -> Unit, - index: Int + question: String?, + answer: String?, + modifier: Modifier = Modifier, ) { Column( - modifier = Modifier + modifier = modifier .fillMaxWidth() - .padding(horizontal = 16.dp) + .padding(horizontal = 16.dp), ) { Row( modifier = Modifier @@ -43,7 +54,7 @@ fun FaqItemHolder( onItemSelected.invoke(index) } .padding(vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( text = question.orEmpty(), @@ -55,11 +66,11 @@ fun FaqItemHolder( ) Icon( - imageVector = Icons.Default.ArrowDropDown, + imageVector = MifosIcons.ArrowDropDown, contentDescription = "drop down", tint = if (isSystemInDarkTheme()) Color.White else Color.Gray, modifier = Modifier - .scale(1f, if (isSelected) -1f else 1f) + .scale(1f, if (isSelected) -1f else 1f), ) } @@ -67,9 +78,9 @@ fun FaqItemHolder( visible = isSelected, enter = fadeIn() + expandVertically( animationSpec = spring( - stiffness = Spring.StiffnessMedium - ) - ) + stiffness = Spring.StiffnessMedium, + ), + ), ) { Text( text = answer.orEmpty(), @@ -77,10 +88,27 @@ fun FaqItemHolder( color = if (isSystemInDarkTheme()) Color.White else Color.Black, modifier = Modifier .fillMaxWidth() - .padding(bottom = 8.dp) + .padding(bottom = 8.dp), ) } - Divider() + HorizontalDivider() + } +} + +@DevicePreviews +@Composable +private fun FaqItemHolderPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + FaqItemHolder( + index = 0, + isSelected = false, + onItemSelected = {}, + question = "What is Mifos?", + answer = "Mifos is a platform for financial inclusion.", + modifier = modifier, + ) } } diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt similarity index 60% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt index 56cb420f0..8295af7ef 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MFStepProcess.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.background @@ -5,7 +14,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -24,42 +32,42 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.colorResource -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp - - -enum class StepProcessState { - COMPLETED, - ACTIVE, - INACTIVE -} +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MFStepProcess( stepNumber: String, - processState: StepProcessState = StepProcessState.INACTIVE, activateColor: Color, deactivateColor: Color, + modifier: Modifier = Modifier, isLastStep: Boolean = false, - processContent: @Composable (Modifier) -> Unit + processState: StepProcessState = StepProcessState.INACTIVE, + content: @Composable (Modifier) -> Unit, ) { var barHeight by remember { mutableStateOf(0.dp) } val localDensity = LocalDensity.current - Row { + Row(modifier) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Column( modifier = Modifier .size(40.dp) .clip(CircleShape) - .background(color = if (processState == StepProcessState.INACTIVE) deactivateColor else activateColor), + .background( + color = if (processState == StepProcessState.INACTIVE) { + deactivateColor + } else { + activateColor + }, + ), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Text( text = if (processState == StepProcessState.COMPLETED) "✔" else stepNumber, - color = MaterialTheme.colorScheme.onPrimary + color = MaterialTheme.colorScheme.onPrimary, ) } if (!isLastStep) { @@ -67,22 +75,53 @@ fun MFStepProcess( modifier = Modifier .height(barHeight) .width(4.dp) - .background(color = if (processState == StepProcessState.INACTIVE) deactivateColor else activateColor), - ) {} + .background( + color = if (processState == StepProcessState.INACTIVE) { + deactivateColor + } else { + activateColor + }, + ), + ) } } - processContent( + content( Modifier .padding(start = 10.dp, end = 6.dp) - .onGloballyPositioned { barHeight = with(localDensity) { it.size.height.toDp() } } + .onGloballyPositioned { barHeight = with(localDensity) { it.size.height.toDp() } }, ) } } +enum class StepProcessState { + COMPLETED, + ACTIVE, + INACTIVE, +} + fun getStepState(targetStep: Int, currentStep: Int): StepProcessState { return when { currentStep == targetStep -> StepProcessState.ACTIVE currentStep > targetStep -> StepProcessState.COMPLETED else -> StepProcessState.INACTIVE } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun Preview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MFStepProcess( + stepNumber = "1", + activateColor = Color.Red, + deactivateColor = Color.Gray, + modifier = modifier, + isLastStep = false, + processState = StepProcessState.ACTIVE, + ) { + Text(text = "Step 1") + } + } +} diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt new file mode 100644 index 000000000..c87a49027 --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import org.mifos.mobile.core.designsystem.components.MifosTextButton +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews + +@Composable +fun MifosAlertDialog( + dialogTitle: String, + dialogText: String, + dismissText: String, + confirmationText: String, + onDismissRequest: () -> Unit, + onConfirmation: () -> Unit, + modifier: Modifier = Modifier, + icon: ImageVector? = null, +) { + AlertDialog( + icon = { + if (icon != null) { + Icon(imageVector = icon, contentDescription = null) + } + }, + title = { Text(text = dialogTitle) }, + text = { Text(text = dialogText) }, + modifier = modifier, + onDismissRequest = onDismissRequest, + confirmButton = { + MifosTextButton( + text = confirmationText, + onClick = onConfirmation, + ) + }, + dismissButton = { + MifosTextButton( + text = dismissText, + onClick = onDismissRequest, + ) + }, + ) +} + +@DevicePreviews +@Composable +private fun MifosAlertDialogPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosAlertDialog( + dialogTitle = "Dialog Title", + dialogText = "Dialog Text", + dismissText = "Dismiss", + confirmationText = "Confirm", + onDismissRequest = {}, + onConfirmation = {}, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt similarity index 56% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt index dc0873f56..85724dbe9 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosCheckBox.kt @@ -1,46 +1,54 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.layout.Row import androidx.compose.material3.Checkbox import androidx.compose.material3.CheckboxColors import androidx.compose.material3.CheckboxDefaults -import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import org.mifos.mobile.core.ui.theme.MifosMobileTheme - +import androidx.compose.ui.Modifier +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosCheckBox( + text: String, checked: Boolean, onCheckChanged: (Boolean) -> Unit, - text: String, + modifier: Modifier = Modifier, checkboxColors: CheckboxColors = CheckboxDefaults.colors(), ) { Row( - verticalAlignment = Alignment.CenterVertically + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, ) { Checkbox( checked = checked, onCheckedChange = { onCheckChanged.invoke(it) }, - colors = checkboxColors + colors = checkboxColors, ) Text(text = text) } } -@Preview(showSystemUi = true) +@DevicePreviews @Composable fun MifosCheckBoxPreview() { MifosMobileTheme { MifosCheckBox( checked = false, onCheckChanged = {}, - text = "" + text = "", ) } -} \ No newline at end of file +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt similarity index 60% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt index 113956628..f0e02cac6 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosComposeView.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import android.content.Context @@ -5,7 +14,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.fragment.app.Fragment -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme fun Fragment.mifosComposeView(context: Context, content: @Composable () -> Unit): ComposeView { return ComposeView(context).apply { @@ -16,4 +25,4 @@ fun Fragment.mifosComposeView(context: Context, content: @Composable () -> Unit) } } } -} \ No newline at end of file +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt similarity index 66% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt index ad4ec34f6..4c03cffd6 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosDropDownTextField.kt @@ -1,25 +1,27 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.clickable +import androidx.annotation.StringRes import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material.icons.filled.ArrowDropUp import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldColors import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -29,36 +31,38 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosDropDownTextField( - optionsList: List = listOf(), - selectedOption: String? = null, + onClick: (Int, String) -> Unit, + modifier: Modifier = Modifier, + @StringRes labelResId: Int = 0, isEnabled: Boolean = true, supportingText: String? = null, error: Boolean = false, - onClick: (Int, String) -> Unit, + optionsList: List = listOf(), + selectedOption: String? = null, ) { - var expanded by rememberSaveable { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() LaunchedEffect(key1 = isPressed) { - if(isPressed) expanded = true && isEnabled + if (isPressed) expanded = true && isEnabled } Box( - modifier = Modifier.alpha(if (!isEnabled) 0.4f else 1f), + modifier = modifier.alpha(if (!isEnabled) 0.4f else 1f), ) { OutlinedTextField( value = selectedOption ?: "", - onValueChange = { }, + onValueChange = { }, label = { Text(stringResource(id = labelResId)) }, interactionSource = interactionSource, modifier = Modifier @@ -70,11 +74,14 @@ fun MifosDropDownTextField( isError = error, trailingIcon = { Icon( - imageVector = if (expanded) Icons.Filled.ArrowDropUp - else Icons.Filled.ArrowDropDown, + imageVector = if (expanded) { + MifosIcons.ArrowDropUp + } else { + MifosIcons.ArrowDropDown + }, contentDescription = null, ) - } + }, ) DropdownMenu( @@ -90,7 +97,7 @@ fun MifosDropDownTextField( expanded = false onClick(index, item) }, - text = { Text(text = item) } + text = { Text(text = item) }, ) } } @@ -99,22 +106,22 @@ fun MifosDropDownTextField( @Composable fun MifosDropDownDoubleTextField( + onClick: (Int, Pair) -> Unit, modifier: Modifier = Modifier, - optionsList: List> = listOf(), - selectedOption: String? = null, + @StringRes labelResId: Int = 0, isEnabled: Boolean = true, supportingText: String? = null, error: Boolean = false, - onClick: (Int, Pair) -> Unit, + optionsList: List> = listOf(), + selectedOption: String? = null, ) { - var expanded by rememberSaveable { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() LaunchedEffect(key1 = isPressed) { - if(isPressed) expanded = true && isEnabled + if (isPressed) expanded = true && isEnabled } Box( @@ -122,7 +129,7 @@ fun MifosDropDownDoubleTextField( ) { OutlinedTextField( value = selectedOption ?: "", - onValueChange = { }, + onValueChange = { }, label = { Text(stringResource(id = labelResId)) }, interactionSource = interactionSource, modifier = Modifier @@ -134,11 +141,14 @@ fun MifosDropDownDoubleTextField( isError = error, trailingIcon = { Icon( - imageVector = if (expanded) Icons.Filled.ArrowDropUp - else Icons.Filled.ArrowDropDown, + imageVector = if (expanded) { + MifosIcons.ArrowDropUp + } else { + MifosIcons.ArrowDropDown + }, contentDescription = null, ) - } + }, ) DropdownMenu( @@ -159,11 +169,52 @@ fun MifosDropDownDoubleTextField( Text(text = item.first) Text(text = item.second) } - - } + }, ) } } } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun MifosDropDownTextFieldPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosDropDownTextField( + onClick = { _, _ -> }, + modifier = modifier, + labelResId = 0, + isEnabled = true, + supportingText = null, + error = false, + optionsList = listOf("Option 1", "Option 2", "Option 3"), + selectedOption = null, + ) + } +} + +@DevicePreviews +@Composable +private fun MifosDropDownDoubleTextFieldPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosDropDownDoubleTextField( + onClick = { _, _ -> }, + modifier = modifier, + labelResId = 0, + isEnabled = true, + supportingText = null, + error = false, + optionsList = listOf( + Pair("Option 1", "Option 1 Description"), + Pair("Option 2", "Option 2 Description"), + Pair("Option 3", "Option 3 Description"), + ), + selectedOption = null, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt similarity index 61% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt index 495b25ab1..ce3555a40 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosErrorComponent.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.background @@ -8,10 +17,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CompareArrows -import androidx.compose.material.icons.filled.Info -import androidx.compose.material.icons.filled.WifiOff import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -23,56 +28,60 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.mifos.mobile.core.R -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosErrorComponent( + modifier: Modifier = Modifier, isNetworkConnected: Boolean = true, message: String? = null, isEmptyData: Boolean = false, isRetryEnabled: Boolean = false, - onRetry: () -> Unit = {} + onRetry: () -> Unit = {}, ) { when { !isNetworkConnected -> NoInternetComponent(isRetryEnabled = isRetryEnabled) { onRetry() } else -> EmptyDataComponent( + modifier = modifier, isEmptyData = isEmptyData, message = message, isRetryEnabled = isRetryEnabled, - onRetry = onRetry + onRetry = onRetry, ) } } @Composable fun NoInternetComponent( - modifier: Modifier = Modifier.fillMaxSize(), + modifier: Modifier = Modifier, isRetryEnabled: Boolean = false, - onRetry: () -> Unit = {} + onRetry: () -> Unit = {}, ) { Column( modifier = modifier + .fillMaxSize() .background(MaterialTheme.colorScheme.background), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( modifier = Modifier .size(100.dp) .padding(bottom = 12.dp), - imageVector = Icons.Filled.WifiOff, + imageVector = MifosIcons.WifiOff, contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondary + tint = MaterialTheme.colorScheme.onSecondary, ) Text( text = stringResource(id = R.string.no_internet), style = TextStyle(fontSize = 20.sp), - color = MaterialTheme.colorScheme.onSecondary + color = MaterialTheme.colorScheme.onSecondary, ) Spacer(modifier = Modifier.height(12.dp)) @@ -87,38 +96,42 @@ fun NoInternetComponent( @Composable fun EmptyDataComponent( - modifier: Modifier = Modifier.fillMaxSize(), + modifier: Modifier = Modifier, isEmptyData: Boolean = false, message: String? = null, isRetryEnabled: Boolean = false, - onRetry: () -> Unit = {} + onRetry: () -> Unit = {}, ) { Column( - modifier = modifier, + modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( modifier = Modifier .size(100.dp) .padding(bottom = 12.dp), - imageVector = Icons.Filled.Info, + imageVector = MifosIcons.Info, contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondary + tint = MaterialTheme.colorScheme.onSecondary, ) Text( modifier = Modifier.padding(horizontal = 20.dp), - text = message ?: if (isEmptyData) stringResource(id = R.string.no_data) else stringResource(id = R.string.something_went_wrong), + text = message ?: if (isEmptyData) { + stringResource(id = R.string.no_data) + } else { + stringResource(id = R.string.something_went_wrong) + }, style = TextStyle(fontSize = 20.sp), color = MaterialTheme.colorScheme.onSecondary, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) if (isRetryEnabled) { FilledTonalButton( modifier = Modifier.padding(top = 8.dp), - onClick = { onRetry.invoke() } + onClick = { onRetry.invoke() }, ) { Text(text = stringResource(id = R.string.retry)) } @@ -128,37 +141,36 @@ fun EmptyDataComponent( @Composable fun EmptyDataComponentWithModifiedMessageAndIcon( - modifier: Modifier = Modifier.fillMaxSize(), - isEmptyData: Boolean = false, message: String, - icon: ImageVector + icon: ImageVector, + modifier: Modifier = Modifier, + isEmptyData: Boolean = false, ) { Column( - modifier = modifier, + modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( modifier = Modifier .size(100.dp) .padding(bottom = 12.dp), - imageVector = if(isEmptyData) icon else Icons.Filled.Info, + imageVector = if (isEmptyData) icon else MifosIcons.Info, contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondary + tint = MaterialTheme.colorScheme.onSecondary, ) Text( - modifier= Modifier.padding(horizontal = 20.dp), - text = if(isEmptyData) message else stringResource(id = R.string.something_went_wrong), + modifier = Modifier.padding(horizontal = 20.dp), + text = if (isEmptyData) message else stringResource(id = R.string.something_went_wrong), style = TextStyle(fontSize = 20.sp), color = MaterialTheme.colorScheme.onSecondary, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } } - -@Preview(showSystemUi = true) +@DevicePreviews @Composable fun NoInternetPreview() { MifosMobileTheme { @@ -166,10 +178,25 @@ fun NoInternetPreview() { } } -@Preview(showSystemUi = true) +@DevicePreviews @Composable fun EmptyDataPreview() { MifosMobileTheme { EmptyDataComponent() } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun EmptyDataComponentWithModifiedMessageAndIconPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + EmptyDataComponentWithModifiedMessageAndIcon( + message = "No data found", + icon = MifosIcons.Error, + modifier = modifier, + isEmptyData = true, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt similarity index 54% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt index 54c7523fa..657802e15 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosHiddenTextRow.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.clickable @@ -20,46 +29,77 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosHiddenTextRow( - modifier: Modifier = Modifier, title: String, hiddenText: String, hiddenColor: Color, hidingText: String, visibilityIconId: Int, visibilityOffIconId: Int, - onClick: () -> Unit + onClick: () -> Unit, + modifier: Modifier = Modifier, ) { var isHidden by remember { mutableStateOf(true) } - Row(modifier.clickable { onClick.invoke() }, verticalAlignment = Alignment.CenterVertically) { + + Row( + modifier.clickable { onClick.invoke() }, + verticalAlignment = Alignment.CenterVertically, + ) { Text( text = title, style = MaterialTheme.typography.labelMedium, modifier = Modifier .alpha(0.7f) - .weight(1f) + .weight(1f), ) Text( - text = if (isHidden) hidingText - else hiddenText, + text = if (isHidden) { + hidingText + } else { + hiddenText + }, style = MaterialTheme.typography.bodyLarge, fontWeight = FontWeight.Bold, - color = hiddenColor + color = hiddenColor, ) IconButton( onClick = { isHidden = !isHidden }, modifier = Modifier .padding(start = 6.dp) - .size(24.dp) + .size(24.dp), ) { Icon( - painter = if (isHidden) painterResource(id = visibilityIconId) - else painterResource(id = visibilityOffIconId), + painter = if (isHidden) { + painterResource(id = visibilityIconId) + } else { + painterResource(id = visibilityOffIconId) + }, contentDescription = "Show or hide total amount", tint = MaterialTheme.colorScheme.primary, ) } } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun MifosHiddenTextRowPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosHiddenTextRow( + title = "Title", + hiddenText = "Hidden Text", + hiddenColor = MaterialTheme.colorScheme.primary, + hidingText = "Hiding Text", + visibilityIconId = 0, + visibilityOffIconId = 0, + onClick = {}, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt similarity index 50% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt index 050786782..72dea308b 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosItemCard.kt @@ -1,26 +1,36 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component - import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosItemCard( - modifier: Modifier = Modifier, - shape: Shape = RoundedCornerShape(8.dp), - elevation: Dp = 1.dp, onClick: () -> Unit, - content: @Composable ColumnScope.() -> Unit + modifier: Modifier = Modifier, + elevation: Dp = 1.dp, + shape: Shape = RoundedCornerShape(8.dp), + content: @Composable ColumnScope.() -> Unit, ) { Card( shape = shape, @@ -28,8 +38,23 @@ fun MifosItemCard( .fillMaxWidth() .clickable(onClick = onClick), elevation = CardDefaults.cardElevation( - defaultElevation = elevation + defaultElevation = elevation, ), - content = content + content = content, ) -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun MifosItemCardPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosItemCard( + onClick = {}, + modifier = modifier, + ) { + Text(text = "Card Content") + } + } +} diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt new file mode 100644 index 000000000..e09e38741 --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews + +@Composable +fun MifosLinkText( + text: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + isUnderlined: Boolean = true, +) { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.primary, + textDecoration = if (isUnderlined) TextDecoration.Underline else null, + ), + modifier = modifier + .padding(vertical = 2.dp) + .clickable { + onClick() + }, + ) +} + +@DevicePreviews +@Composable +private fun MifosLinkTextPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosLinkText( + text = "Link Text", + onClick = {}, + modifier = modifier, + ) + } +} diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt new file mode 100644 index 000000000..7b6439a54 --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews + +@Composable +fun MifosMobileIcon( + @DrawableRes + id: Int, + modifier: Modifier = Modifier, +) { + Column(modifier) { + Image( + painter = painterResource(id = id), + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.CenterHorizontally) + .padding(0.dp, 56.dp), + ) + } +} + +@DevicePreviews +@Composable +private fun MifosMobileIconPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosMobileIcon( + id = R.drawable.core_common_circular_background, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt similarity index 65% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt index 08146b24a..88041d598 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosProgressIndicator.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.background @@ -14,12 +23,12 @@ import androidx.compose.ui.tooling.preview.Preview @Preview(showSystemUi = true) @Composable fun MifosProgressIndicator( - modifier: Modifier = Modifier.fillMaxSize() + modifier: Modifier = Modifier.fillMaxSize(), ) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { CircularProgressIndicator() } @@ -28,15 +37,14 @@ fun MifosProgressIndicator( @Preview(showSystemUi = true) @Composable fun MifosProgressIndicatorOverlay( - modifier: Modifier = Modifier.fillMaxSize() + modifier: Modifier = Modifier.fillMaxSize(), ) { Column( modifier = modifier .background(MaterialTheme.colorScheme.background.copy(alpha = 0.7f)), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { CircularProgressIndicator() } } - diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt new file mode 100644 index 000000000..bd161c328 --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.annotation.StringRes +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.Card +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun MifosRadioButtonDialog( + @StringRes + titleResId: Int, + selectedItem: String, + items: Array, + selectItem: (item: String, index: Int) -> Unit, + onDismissRequest: () -> Unit, + modifier: Modifier = Modifier, +) { + BasicAlertDialog( + onDismissRequest = onDismissRequest, + modifier = modifier, + ) { + Card { + Column(modifier = Modifier.padding(20.dp)) { + Text(text = stringResource(id = titleResId)) + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 500.dp), + ) { + itemsIndexed(items = items) { index, item -> + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .clickable { + onDismissRequest.invoke() + selectItem.invoke(item, index) + } + .fillMaxWidth(), + ) { + RadioButton( + selected = (item == selectedItem), + onClick = { + onDismissRequest.invoke() + selectItem.invoke(item, index) + }, + ) + Text( + text = item, + modifier = Modifier.padding(start = 4.dp), + ) + } + } + } + } + } + } +} + +@Preview +@Composable +fun PreviewRadioButtonDialog() { + MifosMobileTheme { + MifosRadioButtonDialog( + titleResId = R.string.core_common_working, + items = arrayOf("1", "2", "3"), + selectedItem = "1", + onDismissRequest = { }, + selectItem = { _, _ -> }, + ) + } +} diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt new file mode 100644 index 000000000..2dd12fb2a --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews + +@Composable +fun MifosRoundIcon( + @DrawableRes + iconId: Int, + modifier: Modifier = Modifier, + contentDescription: String? = null, +) { + Surface( + color = MaterialTheme.colorScheme.surfaceVariant, + modifier = modifier + .clip(CircleShape), + ) { + Image( + modifier = Modifier.padding(all = 6.dp), + painter = painterResource(id = iconId), + contentDescription = contentDescription, + ) + } +} + +@DevicePreviews +@Composable +private fun MifosRoundIconPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosRoundIcon( + iconId = R.drawable.core_common_circular_background, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt similarity index 52% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt index d739125ca..510162bdf 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButtonWithTopDrawable.kt @@ -1,48 +1,55 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component -import android.graphics.drawable.Drawable -import androidx.compose.foundation.isSystemInDarkTheme +import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Phone import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp - +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.components.MifosTextButton +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosTextButtonWithTopDrawable( - modifier: Modifier = Modifier, - onClick: () -> Unit, + @StringRes textResourceId: Int, icon: ImageVector, - contentDescription: String? + onClick: () -> Unit, + contentDescription: String?, + modifier: Modifier = Modifier, ) { - TextButton( - onClick = { onClick.invoke() }, + MifosTextButton( + onClick = onClick, modifier = modifier, colors = ButtonDefaults.textButtonColors( - contentColor = MaterialTheme.colorScheme.primary + contentColor = MaterialTheme.colorScheme.primary, ), content = { Column( horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.Center, ) { Icon( imageVector = icon, @@ -51,9 +58,25 @@ fun MifosTextButtonWithTopDrawable( Spacer(modifier = Modifier.height(4.dp)) Text( text = stringResource(id = textResourceId), - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } - } + }, ) } + +@DevicePreviews +@Composable +private fun MifosTextButtonWithTopDrawablePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTextButtonWithTopDrawable( + textResourceId = R.string.core_common_working, + icon = MifosIcons.Add, + onClick = {}, + contentDescription = null, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt similarity index 61% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt index 92ecb5017..1a2de0af7 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextUserImage.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.background @@ -16,10 +25,15 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews import kotlin.math.min @Composable -fun MifosTextUserImage(modifier: Modifier = Modifier, text: String) { +fun MifosTextUserImage( + text: String, + modifier: Modifier = Modifier, +) { var boxSize by remember { mutableStateOf(Size.Zero) } Box( modifier = modifier @@ -28,17 +42,30 @@ fun MifosTextUserImage(modifier: Modifier = Modifier, text: String) { .onGloballyPositioned { coordinates -> boxSize = Size( coordinates.size.width.toFloat(), - coordinates.size.height.toFloat() + coordinates.size.height.toFloat(), ) }, - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { Text( text = text, color = MaterialTheme.colorScheme.onPrimary, fontSize = with(LocalDensity.current) { (min(boxSize.width, boxSize.height) / 2).toSp() - } + }, ) } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun MifosTextUserImagePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTextUserImage( + text = "A", + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt similarity index 53% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt index ef3167dea..1bd0e0f92 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTexts.kt @@ -1,5 +1,15 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component +import androidx.annotation.DrawableRes import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -19,103 +29,111 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosTextTitleDescSingleLine( - modifier: Modifier = Modifier, title: String, - description: String + description: String, + modifier: Modifier = Modifier, ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, - modifier = modifier.fillMaxWidth() + modifier = modifier.fillMaxWidth(), ) { Text( style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurface, text = title, modifier = Modifier - .alpha(0.7f) + .alpha(0.7f), ) Text( style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, - text = description + text = description, ) } } - @Composable fun MifosTextTitleDescDoubleLine( title: String, description: String, descriptionStyle: TextStyle, + modifier: Modifier = Modifier, ) { - Column(modifier = Modifier.fillMaxWidth()) { + Column(modifier = modifier.fillMaxWidth()) { Text( text = title, style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurface, modifier = Modifier .alpha(0.7f) - .fillMaxWidth() + .fillMaxWidth(), ) Text( text = description, style = descriptionStyle, color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) } } @Composable fun MifosTextTitleDescDrawableSingleLine( - modifier: Modifier = Modifier, title: String, description: String, + @DrawableRes imageResId: Int, + modifier: Modifier = Modifier, imageSize: Dp = 14.dp, - onDrawableClick: () -> Unit = {} + onDrawableClick: () -> Unit = {}, ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, - modifier = modifier.fillMaxWidth() + modifier = modifier.fillMaxWidth(), ) { Text( style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.onSurface, text = title, - modifier = Modifier.weight(1f).alpha(0.7f) + modifier = Modifier + .weight(1f) + .alpha(0.7f), ) Text( style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, - text = description + text = description, ) - Spacer(modifier = modifier.width(5.dp)) + Spacer(modifier = Modifier.width(5.dp)) Image( painter = painterResource(id = imageResId), contentDescription = null, - modifier = Modifier.size(imageSize).clickable { onDrawableClick() }, + modifier = Modifier + .size(imageSize) + .clickable { onDrawableClick() }, ) } } @Composable fun MifosTitleDescSingleLineEqual( - modifier: Modifier = Modifier, title: String, - description: String + description: String, + modifier: Modifier = Modifier, ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, - modifier = modifier.fillMaxWidth() + modifier = modifier.fillMaxWidth(), ) { Text( style = MaterialTheme.typography.labelMedium, @@ -123,14 +141,72 @@ fun MifosTitleDescSingleLineEqual( text = title, modifier = Modifier .alpha(0.7f) - .weight(1f) + .weight(1f), ) Text( style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface, text = description, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), + ) + } +} + +@DevicePreviews +@Composable +private fun MifosTextTitleDescSingleLinePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTextTitleDescSingleLine( + title = "MifosTextTitleDescSingleLine Title", + description = "MifosTextTitleDescSingleLine Description", + modifier = modifier, + ) + } +} + +@DevicePreviews +@Composable +private fun MifosTextTitleDescDoubleLinePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTextTitleDescDoubleLine( + title = "MifosTextTitleDescDoubleLine Title", + description = "MifosTextTitleDescDoubleLine Description", + descriptionStyle = MaterialTheme.typography.bodyMedium, + modifier = modifier, + ) + } +} + +@DevicePreviews +@Composable +private fun MifosTextTitleDescDrawableSingleLinePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTextTitleDescDrawableSingleLine( + title = "MifosTextTitleDescDrawableSingleLine Title", + description = "MifosTextTitleDescDrawableSingleLine Description", + imageResId = R.drawable.core_common_circular_background, + modifier = modifier, + ) + } +} + +@DevicePreviews +@Composable +private fun MifosTitleDescSingleLineEqualPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTitleDescSingleLineEqual( + title = "MifosTitleDescSingleLineEqual Title", + description = "MifosTitleDescSingleLineEqual Description", + modifier = modifier, ) } } diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt similarity index 65% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt index 9ba942569..b390b7fd6 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTitleSearchCard.kt @@ -1,11 +1,18 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component -import androidx.compose.foundation.isSystemInDarkTheme +import androidx.annotation.StringRes import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -17,28 +24,35 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.components.MifosSearchTextField +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosTitleSearchCard( - searchQuery: (String) -> Unit, + @StringRes titleResourceId: Int, - onSearchDismiss: () -> Unit + searchQuery: (String) -> Unit, + onSearchDismiss: () -> Unit, + modifier: Modifier = Modifier, ) { var isSearching by rememberSaveable { mutableStateOf(false) } var searchedQuery by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf( - TextFieldValue("") + TextFieldValue(""), ) } if (!isSearching) { Row( + modifier = modifier, verticalAlignment = Alignment.CenterVertically, ) { Text( @@ -46,12 +60,12 @@ fun MifosTitleSearchCard( color = MaterialTheme.colorScheme.onSurface, style = TextStyle(fontSize = 24.sp), modifier = Modifier.weight(1f), - maxLines = 1 + maxLines = 1, ) IconButton(onClick = { isSearching = true }) { Icon( - imageVector = Icons.Default.Search, + imageVector = MifosIcons.Search, contentDescription = "Search Icon", tint = MaterialTheme.colorScheme.onSurface, ) @@ -61,7 +75,7 @@ fun MifosTitleSearchCard( Row( modifier = Modifier .padding(horizontal = 4.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { MifosSearchTextField( modifier = Modifier.fillMaxWidth(), @@ -79,3 +93,18 @@ fun MifosTitleSearchCard( } } } + +@DevicePreviews +@Composable +private fun MifosTitleSearchCardPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosTitleSearchCard( + titleResourceId = R.string.core_common_working, + searchQuery = {}, + onSearchDismiss = {}, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt similarity index 55% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt index 72bca7019..f1b6b9c5f 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosUserImage.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import android.graphics.Bitmap @@ -10,22 +19,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale - -/** - * @author pratyush - * @since 20/12/2023 - */ +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MifosUserImage( bitmap: Bitmap?, modifier: Modifier = Modifier, - username: String? = null + username: String? = null, ) { if (bitmap == null) { MifosTextUserImage( + text = username?.firstOrNull()?.toString() ?: "M", modifier = modifier, - text = username?.firstOrNull()?.toString() ?: "M" ) } else { Image( @@ -38,3 +44,17 @@ fun MifosUserImage( ) } } + +@DevicePreviews +@Composable +private fun MifosUserImagePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MifosUserImage( + bitmap = null, + modifier = modifier, + username = "John Doe", + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt similarity index 58% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt index 6138da053..faddb190d 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/MonitorListItemWithIcon.kt @@ -1,5 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -16,24 +27,27 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun MonitorListItemWithIcon( + @StringRes titleId: Int, + @StringRes subTitleId: Int, + @DrawableRes iconId: Int, + onClick: () -> Unit, modifier: Modifier = Modifier, - titleId: Int, - subTitleId: Int, - iconId: Int, - onClick: () -> Unit ) { Row( modifier = modifier .clickable { onClick.invoke() } .padding(8.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { MifosRoundIcon( iconId = iconId, - modifier = Modifier.size(39.dp) + modifier = Modifier.size(39.dp), ) Spacer(modifier = Modifier.width(8.dp)) Column { @@ -54,3 +68,19 @@ fun MonitorListItemWithIcon( } } } + +@DevicePreviews +@Composable +private fun MonitorListItemWithIconPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + MonitorListItemWithIcon( + titleId = R.string.core_common_working, + subTitleId = R.string.something_went_wrong, + iconId = R.drawable.core_common_circular_background, + onClick = {}, + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt similarity index 53% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt index 1a26637ad..29bedc79d 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/NoInternet.kt @@ -1,6 +1,16 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component -import android.content.res.Configuration +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -9,9 +19,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccessTime -import androidx.compose.material.icons.filled.WifiOff import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -20,56 +27,71 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import androidx.compose.ui.res.vectorResource - - -/** - * @author pratyush - * @since 20/12/2023 - */ +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun NoInternet( - icon: Int? = null, - error: Int, + @StringRes error: Int, + modifier: Modifier = Modifier, isRetryEnabled: Boolean = true, - retry: () -> Unit = {} + @DrawableRes icon: Int? = null, + retry: () -> Unit = {}, ) { Column( - modifier = Modifier + modifier = modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( modifier = Modifier .size(100.dp) .padding(bottom = 12.dp), - imageVector = if(icon != null) ImageVector.vectorResource(id = icon) - else MifosIcons.WifiOff, + imageVector = if (icon != null) { + ImageVector.vectorResource(id = icon) + } else { + MifosIcons.WifiOff + }, contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondary + tint = MaterialTheme.colorScheme.onSecondary, ) Text( text = stringResource(id = error), style = TextStyle(fontSize = 20.sp), - color = MaterialTheme.colorScheme.onSecondary + color = MaterialTheme.colorScheme.onSecondary, ) Spacer(modifier = Modifier.height(12.dp)) - if(isRetryEnabled) { + if (isRetryEnabled) { FilledTonalButton(onClick = { retry.invoke() }) { Text(text = "Retry") } } } -} \ No newline at end of file +} + +@DevicePreviews +@Composable +private fun NoInternetPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + NoInternet( + error = R.string.no_internet, + modifier = modifier, + isRetryEnabled = true, + icon = R.drawable.core_common_circular_background, + retry = {}, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt similarity index 52% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt index feb51ecea..20b41deec 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileField.kt @@ -1,12 +1,23 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -18,22 +29,23 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp - -/** - * @author pratyush - * @since 20/12/2023 - */ +import org.mifos.mobile.core.R +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.utils.DevicePreviews @Composable fun UserProfileField( - text: Int, icon: Int, onClick: (() -> Unit) + @StringRes text: Int, + @DrawableRes icon: Int, + onClick: (() -> Unit), + modifier: Modifier = Modifier, ) { Row( - modifier = Modifier + modifier = modifier .fillMaxWidth() .clickable(onClick = onClick) .padding(top = 16.dp, bottom = 16.dp, start = 8.dp, end = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(id = text), @@ -46,18 +58,20 @@ fun UserProfileField( tint = if (isSystemInDarkTheme()) Color.White else Color.Black, ) } - Divider(color = if (isSystemInDarkTheme()) Color(0xFF8E9099) else Color.Black) + HorizontalDivider(color = if (isSystemInDarkTheme()) Color(0xFF8E9099) else Color.Black) } @Composable fun UserProfileField( - label: Int, value: String + @StringRes label: Int, + value: String, + modifier: Modifier = Modifier, ) { Row( - modifier = Modifier + modifier = modifier .fillMaxWidth() .padding(top = 16.dp, bottom = 16.dp, start = 8.dp, end = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(id = label), @@ -70,5 +84,34 @@ fun UserProfileField( style = TextStyle(fontSize = 14.sp), ) } - Divider(color = Color(0xFF8E9099)) -} \ No newline at end of file + HorizontalDivider(color = Color(0xFF8E9099)) +} + +@DevicePreviews +@Composable +private fun UserProfileFieldPreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + UserProfileField( + text = R.string.core_common_working, + icon = R.drawable.core_common_circular_background, + onClick = {}, + modifier = modifier, + ) + } +} + +@DevicePreviews +@Composable +private fun UserProfileFieldValuePreview( + modifier: Modifier = Modifier, +) { + MifosMobileTheme { + UserProfileField( + label = R.string.core_common_working, + value = "UserProfileFieldValue", + modifier = modifier, + ) + } +} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt similarity index 73% rename from ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt index 60aa7b5a8..1f9346992 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/component/UserProfileTopBar.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.component import androidx.compose.foundation.clickable @@ -9,9 +18,6 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material.icons.filled.Edit import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -25,27 +31,24 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp - -/** - * @author pratyush - * @since 20/12/2023 - */ +import org.mifos.mobile.core.designsystem.icons.MifosIcons @OptIn(ExperimentalMaterial3Api::class) @Composable fun UserProfileTopBar( - home : () -> Unit, text: Int, + home: () -> Unit, + modifier: Modifier = Modifier, ) { TopAppBar( - modifier = Modifier.height(64.dp), + modifier = modifier.height(64.dp), title = { Row( modifier = Modifier .fillMaxSize() .padding(start = 16.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(id = text), @@ -53,7 +56,7 @@ fun UserProfileTopBar( style = TextStyle(fontSize = 24.sp), ) Icon( - imageVector = Icons.Default.Edit, + imageVector = MifosIcons.Edit, contentDescription = null, tint = if (isSystemInDarkTheme()) Color.White else Color.Black, ) @@ -65,22 +68,26 @@ fun UserProfileTopBar( .fillMaxHeight() .padding(start = 8.dp), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( - imageVector = Icons.Default.ArrowBack, + imageVector = MifosIcons.ArrowBack, contentDescription = null, modifier = Modifier.clickable(onClick = { - home.invoke() + home.invoke() }), tint = if (isSystemInDarkTheme()) Color.White else Color.Black, ) } }, - colors = TopAppBarDefaults.smallTopAppBarColors( - containerColor = if (isSystemInDarkTheme()) Color( - 0xFF1B1B1F - ) else Color(0xFFFEFBFF) - ) + colors = TopAppBarDefaults.topAppBarColors( + containerColor = if (isSystemInDarkTheme()) { + Color( + 0xFF1B1B1F, + ) + } else { + Color(0xFFFEFBFF) + }, + ), ) } diff --git a/core/ui/src/main/java/org/mifos/mobile/core/ui/utils/DevicePreviews.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/utils/DevicePreviews.kt new file mode 100644 index 000000000..d5f9461ca --- /dev/null +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/utils/DevicePreviews.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.utils + +import androidx.compose.ui.tooling.preview.Preview + +/** + * Multipreview annotation that represents various device sizes. Add this annotation to a composable + * to render various devices. + */ +@Preview(name = "phone", device = "spec:width=360dp,height=640dp,dpi=480") +@Preview(name = "landscape", device = "spec:width=640dp,height=360dp,dpi=480") +@Preview(name = "foldable", device = "spec:width=673dp,height=841dp,dpi=480") +@Preview(name = "tablet", device = "spec:width=1280dp,height=800dp,dpi=480") +annotation class DevicePreviews diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/utils/SelectableDates.kt b/core/ui/src/main/java/org/mifos/mobile/core/ui/utils/PresentOrFutureSelectableDates.kt similarity index 56% rename from ui/src/main/java/org/mifos/mobile/core/ui/utils/SelectableDates.kt rename to core/ui/src/main/java/org/mifos/mobile/core/ui/utils/PresentOrFutureSelectableDates.kt index 75a7458da..9526fa3e9 100644 --- a/ui/src/main/java/org/mifos/mobile/core/ui/utils/SelectableDates.kt +++ b/core/ui/src/main/java/org/mifos/mobile/core/ui/utils/PresentOrFutureSelectableDates.kt @@ -1,3 +1,12 @@ +/* + * Copyright 2024 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 org.mifos.mobile.core.ui.utils import androidx.compose.material3.ExperimentalMaterial3Api @@ -5,7 +14,7 @@ import androidx.compose.material3.SelectableDates import java.time.LocalDate @OptIn(ExperimentalMaterial3Api::class) -object PresentOrFutureSelectableDates: SelectableDates { +object PresentOrFutureSelectableDates : SelectableDates { @ExperimentalMaterial3Api override fun isSelectableDate(utcTimeMillis: Long): Boolean { return utcTimeMillis >= System.currentTimeMillis() @@ -14,4 +23,4 @@ object PresentOrFutureSelectableDates: SelectableDates { override fun isSelectableYear(year: Int): Boolean { return year >= LocalDate.now().year } -} \ No newline at end of file +} diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml new file mode 100644 index 000000000..2f7ca73f0 --- /dev/null +++ b/core/ui/src/main/res/values/strings.xml @@ -0,0 +1,16 @@ + + + + No Internet + Retry + No Data + Something went wrong + \ No newline at end of file diff --git a/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/AboutUsScreen.kt b/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/AboutUsScreen.kt index 710fcef8e..d43154546 100644 --- a/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/AboutUsScreen.kt +++ b/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/AboutUsScreen.kt @@ -1,7 +1,10 @@ package org.mifos.mobile.feature.about.ui import android.content.Context -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable @@ -9,11 +12,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.AboutUsItem import org.mifos.mobile.core.model.enums.AboutUsListItemId import org.mifos.mobile.core.ui.component.AboutUsItemCard import org.mifos.mobile.core.ui.component.MifosItemCard -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.about.R import java.util.Calendar diff --git a/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/PrivacyPolicyScreen.kt b/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/PrivacyPolicyScreen.kt index eb4d7e7d6..46c595afd 100644 --- a/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/PrivacyPolicyScreen.kt +++ b/feature/about/src/main/java/org/mifos/mobile/feature/about/ui/PrivacyPolicyScreen.kt @@ -18,7 +18,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView -import org.mifos.mobile.core.ui.component.MFScaffold +import org.mifos.mobile.core.designsystem.components.MifosScaffold import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.feature.about.R @@ -27,10 +27,10 @@ fun PrivacyPolicyScreen( navigateBack: () -> Unit, ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId= R.string.privacy_policy, navigateBack= navigateBack, - scaffoldContent = { + content = { WebView( url = context.getString(R.string.privacy_policy_host_url) ) diff --git a/feature/account/build.gradle.kts b/feature/account/build.gradle.kts index 8358bc803..5930b9c54 100644 --- a/feature/account/build.gradle.kts +++ b/feature/account/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/account/src/main/java/org/mifos/mobile/feature/account/account/screens/AccountsScreen.kt b/feature/account/src/main/java/org/mifos/mobile/feature/account/account/screens/AccountsScreen.kt index 19a993684..4234d6ea7 100644 --- a/feature/account/src/main/java/org/mifos/mobile/feature/account/account/screens/AccountsScreen.kt +++ b/feature/account/src/main/java/org/mifos/mobile/feature/account/account/screens/AccountsScreen.kt @@ -14,20 +14,20 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.feature.account.R -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.common.Network import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanAccount import org.mifos.mobile.core.model.entity.accounts.savings.SavingAccount import org.mifos.mobile.core.model.entity.accounts.share.ShareAccount import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay +import org.mifos.mobile.feature.account.R import org.mifos.mobile.feature.account.utils.AccountState import org.mifos.mobile.feature.account.viewmodel.AccountsViewModel diff --git a/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/screens/ClientAccountsScreen.kt b/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/screens/ClientAccountsScreen.kt index f89980a6b..737a46c6f 100644 --- a/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/screens/ClientAccountsScreen.kt +++ b/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/screens/ClientAccountsScreen.kt @@ -1,6 +1,5 @@ package org.mifos.mobile.feature.account.client_account.screens -import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.padding @@ -9,7 +8,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf @@ -23,16 +21,16 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.feature.account.R import org.mifos.mobile.core.common.Constants -import org.mifos.mobile.core.ui.component.FloatingActionButtonContent -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosIcons -import org.mifos.mobile.core.ui.component.MifosTabPager -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.feature.account.account.screens.AccountsScreen +import org.mifos.mobile.core.designsystem.components.FloatingActionButtonContent +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTabPager +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.CheckboxStatus import org.mifos.mobile.core.model.enums.AccountType +import org.mifos.mobile.feature.account.R +import org.mifos.mobile.feature.account.account.screens.AccountsScreen import org.mifos.mobile.feature.account.client_account.utils.ClientAccountFilterDialog import org.mifos.mobile.feature.account.client_account.utils.ClientAccountsScreenTopBar import org.mifos.mobile.feature.account.viewmodel.AccountsViewModel @@ -124,7 +122,7 @@ fun ClientAccountsScreen( ) } - MFScaffold( + MifosScaffold( topBar = { ClientAccountsScreenTopBar( navigateBack = navigateBack, @@ -151,7 +149,7 @@ fun ClientAccountsScreen( } ), - scaffoldContent = { + content = { ClientAccountsTabRow( modifier = Modifier.padding(it), pageChanged = { index -> pageChanged.invoke(index) }, diff --git a/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/utils/ClientAccountScreenTopBar.kt b/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/utils/ClientAccountScreenTopBar.kt index 59b5054a6..b640d6d37 100644 --- a/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/utils/ClientAccountScreenTopBar.kt +++ b/feature/account/src/main/java/org/mifos/mobile/feature/account/client_account/utils/ClientAccountScreenTopBar.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.Icon @@ -29,8 +28,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.ui.component.MifosIcons -import org.mifos.mobile.core.ui.component.MifosSearchTextField +import org.mifos.mobile.core.designsystem.components.MifosSearchTextField +import org.mifos.mobile.core.designsystem.icons.MifosIcons @Composable fun ClientAccountsScreenTopBar( diff --git a/feature/auth/build.gradle.kts b/feature/auth/build.gradle.kts index ae7ac902d..593194866 100644 --- a/feature/auth/build.gradle.kts +++ b/feature/auth/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/login/screens/LoginScreen.kt b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/login/screens/LoginScreen.kt index e1e3e9e96..61e70cc5d 100644 --- a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/login/screens/LoginScreen.kt +++ b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/login/screens/LoginScreen.kt @@ -52,10 +52,10 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosMobileIcon -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.auth.R import org.mifos.mobile.feature.auth.login.viewmodel.LoginUiState import org.mifos.mobile.feature.auth.login.viewmodel.LoginViewModel diff --git a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationScreen.kt b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationScreen.kt index 68fb26b4a..833297465 100644 --- a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationScreen.kt +++ b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationScreen.kt @@ -62,11 +62,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.owlbuddy.www.countrycodechooser.CountryCodeChooser import com.owlbuddy.www.countrycodechooser.utils.enums.CountryCodeType import kotlinx.coroutines.launch -import org.mifos.mobile.core.ui.component.MFScaffold +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosMobileIcon -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.auth.R import org.mifos.mobile.feature.auth.registration.utils.PasswordStrength import org.mifos.mobile.feature.auth.registration.viewmodel.RegistrationUiState @@ -121,11 +121,11 @@ fun RegistrationScreen( SnackbarHostState() } - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.register, navigateBack = navigateBack, snackbarHost = { SnackbarHost(hostState = snackBarHostState) }, - scaffoldContent = { contentPadding -> + content = { contentPadding -> Box( modifier = Modifier diff --git a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationVerificationScreen.kt b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationVerificationScreen.kt index 413a5bc8b..dea2d83db 100644 --- a/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationVerificationScreen.kt +++ b/feature/auth/src/main/java/org/mifos/mobile/feature/auth/registration/screens/RegistrationVerificationScreen.kt @@ -40,10 +40,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.auth.R import org.mifos.mobile.feature.auth.registration.viewmodel.RegistrationUiState import org.mifos.mobile.feature.auth.registration.viewmodel.RegistrationViewModel @@ -102,10 +102,10 @@ fun RegistrationVerificationScreen( ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.register, navigateBack = navigateBack, - scaffoldContent = { contentPadding -> + content = { contentPadding -> Box( modifier = Modifier diff --git a/feature/beneficiary/build.gradle.kts b/feature/beneficiary/build.gradle.kts index 710d66ca7..cca3b949d 100644 --- a/feature/beneficiary/build.gradle.kts +++ b/feature/beneficiary/build.gradle.kts @@ -9,7 +9,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationContent.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationContent.kt index edb33238a..4c96b4b65 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationContent.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationContent.kt @@ -21,14 +21,14 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosTextButton +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload import org.mifos.mobile.core.model.entity.templates.beneficiary.BeneficiaryTemplate import org.mifos.mobile.core.model.enums.BeneficiaryState import org.mifos.mobile.core.ui.component.MifosDropDownTextField -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField -import org.mifos.mobile.core.ui.component.MifosTextButton -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R @Composable diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationScreen.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationScreen.kt index d727241ee..ad86c548d 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationScreen.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_application/BeneficiaryApplicationScreen.kt @@ -14,18 +14,15 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.common.Constants -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.common.utils.ParcelableAndSerializableUtils.getCheckedParcelable -import org.mifos.mobile.core.common.utils.ParcelableAndSerializableUtils.getCheckedSerializable +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.entity.beneficiary.BeneficiaryPayload import org.mifos.mobile.core.model.entity.templates.beneficiary.BeneficiaryTemplate import org.mifos.mobile.core.model.enums.BeneficiaryState +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.feature.beneficiary.R @@ -62,13 +59,13 @@ fun BeneficiaryApplicationScreen( onSubmit: (BeneficiaryPayload) -> Unit ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = when(beneficiaryState) { BeneficiaryState.UPDATE -> R.string.update_beneficiary else -> R.string.add_beneficiary }, navigateBack = navigateBack, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues = paddingValues)) { when(uiState) { is BeneficiaryApplicationUiState.Error -> { diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailContent.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailContent.kt index 8b5ccb4bf..138246033 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailContent.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailContent.kt @@ -14,9 +14,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.ui.component.MifosTitleDescSingleLineEqual -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R @Composable diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailScreen.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailScreen.kt index 3bf1b0992..14acd3472 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailScreen.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_detail/BeneficiaryDetailScreen.kt @@ -31,12 +31,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.common.Constants +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary -import org.mifos.mobile.core.model.enums.BeneficiaryState import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R @Composable diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListContent.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListContent.kt index 3a051abd1..c868b0702 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListContent.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListContent.kt @@ -21,8 +21,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary -import org.mifos.mobile.core.ui.theme.MifosMobileTheme @Composable fun ShowBeneficiary( diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListScreen.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListScreen.kt index dacafc449..2fde51c3d 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListScreen.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/beneficiary_list/BeneficiaryListScreen.kt @@ -23,14 +23,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.FloatingActionButtonContent +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.FloatingActionButtonContent -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.feature.beneficiary.R @Composable @@ -73,7 +73,7 @@ fun BeneficiaryListScreen( val pullRefreshState = rememberPullToRefreshState() val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.beneficiaries, navigateBack = navigateBack, floatingActionButtonContent = FloatingActionButtonContent( diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreen.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreen.kt index a4f586b19..42dfcf005 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreen.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreen.kt @@ -10,13 +10,12 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreenIcons.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreenIcons.kt index 1873011dc..6f0b67524 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreenIcons.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/BeneficiaryScreenIcons.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R import org.mifos.mobile.ui.beneficiary.presentation.RenderIconAndText diff --git a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/RenderIconAndText.kt b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/RenderIconAndText.kt index 430173002..394cef9bf 100644 --- a/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/RenderIconAndText.kt +++ b/feature/beneficiary/src/main/java/org/mifos/mobile/feature/beneficiary/presentation/RenderIconAndText.kt @@ -4,8 +4,6 @@ import android.content.res.Configuration import androidx.annotation.DrawableRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.material3.Icon @@ -18,7 +16,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.beneficiary.R diff --git a/feature/client_charge/build.gradle.kts b/feature/client_charge/build.gradle.kts index 92bf869e9..f9a4a4eb9 100644 --- a/feature/client_charge/build.gradle.kts +++ b/feature/client_charge/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavGraph.kt b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavGraph.kt index 052be0f78..1590dd6c9 100644 --- a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavGraph.kt +++ b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavGraph.kt @@ -7,14 +7,13 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.navigation import androidx.navigation.navArgument import org.mifos.mobile.core.common.Constants.CHARGE_TYPE -import org.mifos.mobile.core.model.entity.client.ClientType import org.mifos.mobile.core.model.enums.ChargeType import org.mifos.mobile.feature.client_charge.screens.ClientChargeScreen fun NavController.navigateToClientChargeScreen( chargeType: ChargeType, ) { - navigate(ClientChargeNavigation.ClientChargeBase.passArguments(chargeType)) + navigate(ClientChargeNavigation.ClientChargeScreen.passArguments(chargeType)) } fun NavGraphBuilder.clientChargeNavGraph( diff --git a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavigation.kt b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavigation.kt index 45c826a47..85ef3c0a4 100644 --- a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavigation.kt +++ b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/navigation/ClientChargeNavigation.kt @@ -1,6 +1,5 @@ package org.mifos.mobile.feature.client_charge.navigation -import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.Constants.CHARGE_TYPE import org.mifos.mobile.core.model.enums.ChargeType @@ -10,9 +9,16 @@ const val CLIENT_CHARGE_SCREEN_ROUTE = "client_charge_screen_route" // Sealed class for Navigation Routes sealed class ClientChargeNavigation(var route: String) { - data object ClientChargeBase : ClientChargeNavigation(route = "$CLIENT_CHARGE_NAVIGATION_ROUTE_BASE/{$CHARGE_TYPE}") { - fun passArguments(chargeType: ChargeType) = "$CLIENT_CHARGE_NAVIGATION_ROUTE_BASE/${chargeType.name}" + data object ClientChargeBase : ClientChargeNavigation( + route = "$CLIENT_CHARGE_NAVIGATION_ROUTE_BASE/{$CHARGE_TYPE}", + ) { + fun passArguments(chargeType: ChargeType) = + "$CLIENT_CHARGE_NAVIGATION_ROUTE_BASE/${chargeType.name}" } - data object ClientChargeScreen : ClientChargeNavigation(route = "$CLIENT_CHARGE_SCREEN_ROUTE") + data object ClientChargeScreen : ClientChargeNavigation( + route = "$CLIENT_CHARGE_SCREEN_ROUTE/{$CHARGE_TYPE}", + ) { + fun passArguments(chargeType: ChargeType) = "$CLIENT_CHARGE_SCREEN_ROUTE/${chargeType.name}" + } } \ No newline at end of file diff --git a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/screens/ClientChargeScreen.kt b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/screens/ClientChargeScreen.kt index 973c4a682..9997e0f25 100644 --- a/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/screens/ClientChargeScreen.kt +++ b/feature/client_charge/src/main/java/org/mifos/mobile/feature/client_charge/screens/ClientChargeScreen.kt @@ -27,19 +27,19 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.feature.client_charge.R +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.common.utils.CurrencyUtil +import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.datastore.model.Charge +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.GreenSuccess +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.RedErrorDark import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosTextTitleDescSingleLine -import org.mifos.mobile.core.ui.theme.GreenSuccess -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.ui.theme.RedErrorDark -import org.mifos.mobile.core.common.utils.CurrencyUtil -import org.mifos.mobile.core.common.utils.DateHelper -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.datastore.model.Charge +import org.mifos.mobile.feature.client_charge.R import org.mifos.mobile.feature.client_charge.utils.ClientChargeState import org.mifos.mobile.feature.client_charge.viewmodel.ClientChargeViewModel @@ -64,10 +64,10 @@ fun ClientChargeScreen( onRetry: () -> Unit ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.client_charges, navigateBack = navigateBack, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box( modifier = Modifier .padding(paddingValues = paddingValues) diff --git a/feature/guarantor/build.gradle.kts b/feature/guarantor/build.gradle.kts index 125f73395..66b4e7bce 100644 --- a/feature/guarantor/build.gradle.kts +++ b/feature/guarantor/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavGraph.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavGraph.kt index 73541e180..1cef1b203 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavGraph.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavGraph.kt @@ -7,19 +7,21 @@ import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.compose.navigation import androidx.navigation.navArgument -import org.mifos.mobile.core.common.Constants +import org.mifos.mobile.core.common.Constants.INDEX +import org.mifos.mobile.core.common.Constants.LOAN_ID import org.mifos.mobile.feature.guarantor.screens.guarantor_add.AddGuarantorScreen import org.mifos.mobile.feature.guarantor.screens.guarantor_details.GuarantorDetailScreen import org.mifos.mobile.feature.guarantor.screens.guarantor_list.GuarantorListScreen -import org.mifos.mobile.core.common.Constants.INDEX -import org.mifos.mobile.core.common.Constants.LOAN_ID -import org.mifos.mobile.feature.guarantor.navigation.GuarantorRoute.GUARANTOR_NAVIGATION_ROUTE_BASE fun NavController.navigateToGuarantorScreen(loanId: Long) { navigate(GuarantorNavigation.GuarantorScreenBase.passArguments(loanId = loanId.toString())) } +fun NavController.navigateToGuarantorListScreen(loanId: Long) { + navigate(GuarantorNavigation.GuarantorList.passArguments(loanId = loanId.toString())) +} + fun NavGraphBuilder.guarantorNavGraph( navController: NavHostController, ) { diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavigation.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavigation.kt index 9f9cad2d2..dc0116779 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavigation.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/navigation/GuarantorNavigation.kt @@ -16,8 +16,10 @@ sealed class GuarantorNavigation(val route: String) { } data object GuarantorList : GuarantorNavigation( - route = GUARANTOR_LIST_SCREEN_ROUTE - ) + route = "$GUARANTOR_LIST_SCREEN_ROUTE/{$LOAN_ID}" + ){ + fun passArguments(loanId: String) = "$GUARANTOR_LIST_SCREEN_ROUTE/$loanId" + } data object GuarantorDetails : GuarantorNavigation( route = "$GUARANTOR_DETAIL_SCREEN_ROUTE/{$LOAN_ID}/{$INDEX}" diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_add/AddGuarantorScreen.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_add/AddGuarantorScreen.kt index 85f11686c..6200c1116 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_add/AddGuarantorScreen.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_add/AddGuarantorScreen.kt @@ -26,16 +26,16 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.guarantor.GuarantorApplicationPayload import org.mifos.mobile.core.model.entity.guarantor.GuarantorPayload import org.mifos.mobile.core.model.entity.guarantor.GuarantorTemplatePayload import org.mifos.mobile.core.model.entity.guarantor.GuarantorType -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosDropDownTextField import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.guarantor.R @@ -70,10 +70,10 @@ fun AddGuarantorScreen( val context = LocalContext.current val guarantorTypeOptions = rememberSaveable { mutableStateOf(listOf()) } - MFScaffold( + MifosScaffold( topBarTitleResId = if(guarantorItem == null) R.string.add_guarantor else R.string.update_guarantor, navigateBack = navigateBack, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { AddGuarantorContent( guarantorItem = guarantorItem, diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailScreen.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailScreen.kt index aa1dab0af..af295c2b9 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailScreen.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailScreen.kt @@ -17,12 +17,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.guarantor.GuarantorPayload -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.guarantor.R @@ -53,7 +53,7 @@ fun GuarantorDetailScreen( var openAlertDialog by rememberSaveable { mutableStateOf(false) } val guarantorItem = rememberSaveable { mutableStateOf(GuarantorPayload()) } - MFScaffold( + MifosScaffold( topBar = { GuarantorDetailTopBar( navigateBack = navigateBack, @@ -61,7 +61,7 @@ fun GuarantorDetailScreen( updateGuarantor = updateGuarantor ) }, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { GuarantorDetailContent(data = guarantorItem.value) when (uiState) { diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailTopBar.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailTopBar.kt index 9855682c3..fa136619f 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailTopBar.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_details/GuarantorDetailTopBar.kt @@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.guarantor.R @OptIn(ExperimentalMaterial3Api::class) diff --git a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_list/GuarantorListScreen.kt b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_list/GuarantorListScreen.kt index 8a815093a..e3c2b57b0 100644 --- a/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_list/GuarantorListScreen.kt +++ b/feature/guarantor/src/main/java/org/mifos/mobile/feature/guarantor/screens/guarantor_list/GuarantorListScreen.kt @@ -29,12 +29,12 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.FloatingActionButtonContent +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.guarantor.GuarantorPayload -import org.mifos.mobile.core.ui.component.FloatingActionButtonContent -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.guarantor.R @@ -61,7 +61,7 @@ fun GuarantorListScreen( addGuarantor: () -> Unit, onGuarantorClicked: (Int) -> Unit ) { - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.view_guarantor, navigateBack = navigateBack, floatingActionButtonContent = FloatingActionButtonContent( @@ -75,7 +75,7 @@ fun GuarantorListScreen( }, contentColor = MaterialTheme.colorScheme.primary ), - scaffoldContent = { + content = { GuarantorListContent( modifier = Modifier.padding(it), uiState = uiState, diff --git a/feature/help/build.gradle.kts b/feature/help/build.gradle.kts index ae9464c86..eb2b78d3b 100644 --- a/feature/help/build.gradle.kts +++ b/feature/help/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/help/src/main/java/org/mifos/mobile/feature/help/HelpScreen.kt b/feature/help/src/main/java/org/mifos/mobile/feature/help/HelpScreen.kt index 57ef5ecc1..ce3c8413c 100644 --- a/feature/help/src/main/java/org/mifos/mobile/feature/help/HelpScreen.kt +++ b/feature/help/src/main/java/org/mifos/mobile/feature/help/HelpScreen.kt @@ -26,14 +26,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.FAQ import org.mifos.mobile.core.ui.component.EmptyDataView import org.mifos.mobile.core.ui.component.FaqItemHolder -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosTextButtonWithTopDrawable import org.mifos.mobile.core.ui.component.MifosTitleSearchCard -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme @Composable fun HelpScreen( @@ -78,7 +78,7 @@ fun HelpScreen( updateFaqPosition: (Int) -> Unit, ) { - MFScaffold( + MifosScaffold( topBar = { MifosTopBar( navigateBack = navigateBack, @@ -91,7 +91,7 @@ fun HelpScreen( } ) }, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { when(uiState) { is HelpUiState.Initial -> Unit @@ -143,11 +143,11 @@ fun HelpContent( ) { itemsIndexed(items = faqArrayList) { index, faqItem -> FaqItemHolder( - question = faqItem?.question, - answer = faqItem?.answer, + index = index, isSelected = selectedFaqPosition == index, onItemSelected = { updateFaqPosition(it) }, - index = index + question = faqItem?.question, + answer = faqItem?.answer ) } } diff --git a/feature/home/build.gradle.kts b/feature/home/build.gradle.kts index 89be54fc2..4d0da2afd 100644 --- a/feature/home/build.gradle.kts +++ b/feature/home/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeNavigationDrawer.kt b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeNavigationDrawer.kt index a867da993..9658aca57 100644 --- a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeNavigationDrawer.kt +++ b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeNavigationDrawer.kt @@ -1,8 +1,6 @@ package org.mifos.mobile.feature.home.components import android.graphics.Bitmap -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -12,7 +10,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Divider import androidx.compose.material3.DrawerState import androidx.compose.material3.DrawerValue import androidx.compose.material3.HorizontalDivider @@ -22,17 +19,15 @@ import androidx.compose.material3.ModalDrawerSheet import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.NavigationDrawerItem import androidx.compose.material3.Text -import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosUserImage -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.home.viewmodel.HomeNavigationItems @Composable diff --git a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeTopBar.kt b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeTopBar.kt index ce63a0d30..eb26163dd 100644 --- a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeTopBar.kt +++ b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/HomeTopBar.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import org.mifos.mobile.core.ui.component.MifosIcons +import org.mifos.mobile.core.designsystem.icons.MifosIcons import org.mifos.mobile.feature.home.R @OptIn(ExperimentalMaterial3Api::class) diff --git a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/TransferDialog.kt b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/TransferDialog.kt index 4fb208438..355b8b4e0 100644 --- a/feature/home/src/main/java/org/mifos/mobile/feature/home/components/TransferDialog.kt +++ b/feature/home/src/main/java/org/mifos/mobile/feature/home/components/TransferDialog.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -16,7 +15,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.home.R diff --git a/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeContent.kt b/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeContent.kt index 5f56d8617..b690e4918 100644 --- a/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeContent.kt +++ b/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeContent.kt @@ -4,7 +4,6 @@ import android.graphics.Bitmap import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow @@ -26,7 +25,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -44,13 +42,13 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch +import org.mifos.mobile.core.common.utils.CurrencyUtil +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.core.ui.component.MifosHiddenTextRow import org.mifos.mobile.core.ui.component.MifosLinkText import org.mifos.mobile.core.ui.component.MifosUserImage -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.utils.CurrencyUtil -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosAlertDialog import org.mifos.mobile.feature.home.R import org.mifos.mobile.feature.home.components.HomeNavigationDrawer import org.mifos.mobile.feature.home.components.HomeTopBar @@ -93,7 +91,7 @@ fun HomeContent( } }, content = { - MFScaffold( + MifosScaffold( topBar = { HomeTopBar( openNavigationDrawer = { diff --git a/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeScreen.kt b/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeScreen.kt index 1dc3b4b7c..79f03e211 100644 --- a/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeScreen.kt +++ b/feature/home/src/main/java/org/mifos/mobile/feature/home/screens/HomeScreen.kt @@ -1,7 +1,6 @@ package org.mifos.mobile.feature.home.screens import android.graphics.Bitmap -import androidx.camera.core.processing.SurfaceProcessorNode.In import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -10,17 +9,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.EmptyDataView import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.home.R import org.mifos.mobile.feature.home.navigation.HomeDestinations -import org.mifos.mobile.feature.home.navigation.HomeNavigation -import org.mifos.mobile.feature.home.navigation.toDestination import org.mifos.mobile.feature.home.utils.HomeState import org.mifos.mobile.feature.home.utils.HomeUiState import org.mifos.mobile.feature.home.viewmodel.HomeCardItem -import org.mifos.mobile.feature.home.viewmodel.HomeNavigationItems import org.mifos.mobile.feature.home.viewmodel.HomeViewModel @Composable diff --git a/feature/loan/build.gradle.kts b/feature/loan/build.gradle.kts index 94880b2ce..3bd34c6d8 100644 --- a/feature/loan/build.gradle.kts +++ b/feature/loan/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailContent.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailContent.kt index 452d86339..112f391e2 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailContent.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailContent.kt @@ -22,10 +22,10 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.mifos.mobile.core.common.utils.CurrencyUtil import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.ui.component.MifosTextTitleDescDoubleLine import org.mifos.mobile.core.ui.component.MonitorListItemWithIcon -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.loan.R @Composable diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailScreen.kt index e7fd8be92..b943fbd2d 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailScreen.kt @@ -2,7 +2,6 @@ package org.mifos.mobile.feature.loan.loan_account import android.widget.Toast import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable @@ -14,16 +13,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.ui.component.EmptyDataView import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.NoInternet -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations -import org.mifos.mobile.core.model.enums.AccountType -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.feature.loan.R @Composable @@ -79,7 +76,7 @@ fun LoanAccountDetailScreen( viewQr: () -> Unit, makePayment: () -> Unit ) { - MFScaffold( + MifosScaffold( topBar = { LoanAccountDetailTopBar( navigateBack = navigateBack, @@ -88,7 +85,7 @@ fun LoanAccountDetailScreen( withdrawLoan = withdrawLoan ) }, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { when (uiState) { is LoanAccountDetailUiState.Success -> { diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailTopBar.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailTopBar.kt index 0ccfdbd0e..f80407dc8 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailTopBar.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account/LoanAccountDetailTopBar.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.loan.R diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationContent.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationContent.kt index 080092b76..23985e19e 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationContent.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationContent.kt @@ -33,11 +33,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.mifos.mobile.core.common.utils.DateHelper import org.mifos.mobile.core.common.utils.DateHelper.FORMAT_MM +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosDropDownTextField -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField import org.mifos.mobile.core.ui.component.MifosTextTitleDescDrawableSingleLine import org.mifos.mobile.core.ui.component.MifosTextTitleDescSingleLine -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.ui.utils.PresentOrFutureSelectableDates import org.mifos.mobile.feature.loan.R diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationScreen.kt index d6ec673da..21ec8de6d 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_application/LoanApplicationScreen.kt @@ -22,12 +22,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.google.gson.Gson import org.mifos.mobile.core.common.Network import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.payload.LoansPayload import org.mifos.mobile.core.model.enums.LoanState import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.loan.R diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_summary/LoanAccountSummaryScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_summary/LoanAccountSummaryScreen.kt index 3b97be5f0..7c37d469b 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_summary/LoanAccountSummaryScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_summary/LoanAccountSummaryScreen.kt @@ -1,6 +1,5 @@ package org.mifos.mobile.feature.loan.loan_account_summary -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedCard -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -23,17 +21,14 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.component.MifosTextTitleDescSingleLine import org.mifos.mobile.core.ui.component.MifosTextTitleDescDrawableSingleLine -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.MifosTextTitleDescSingleLine import org.mifos.mobile.feature.loan.R -import org.mifos.mobile.feature.loan.loan_repayment_schedule.LoanUiState @Composable @@ -60,10 +55,10 @@ fun LoanAccountSummaryScreen( uiState: LoanAccountSummaryUiState ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.loan_summary, navigateBack = navigateBack, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { when (uiState) { is LoanAccountSummaryUiState.Loading -> { diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_transaction/LoanAccountTransactionScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_transaction/LoanAccountTransactionScreen.kt index a7df91cc1..22ef5d038 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_transaction/LoanAccountTransactionScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_transaction/LoanAccountTransactionScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable @@ -34,16 +33,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.Network import org.mifos.mobile.core.common.utils.CurrencyUtil import org.mifos.mobile.core.common.utils.DateHelper.getDateAsString import org.mifos.mobile.core.common.utils.Utils.formatTransactionType +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.Transaction import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.feature.loan.R @Composable diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_withdraw/LoanAccountWithdrawScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_withdraw/LoanAccountWithdrawScreen.kt index 1cf0ff8c9..b1e17b73c 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_withdraw/LoanAccountWithdrawScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_account_withdraw/LoanAccountWithdrawScreen.kt @@ -30,12 +30,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosTitleDescSingleLineEqual -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.loan.R diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_repayment_schedule/LoanRepaymentScheduleScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_repayment_schedule/LoanRepaymentScheduleScreen.kt index 5cf74cf92..fea753a8e 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_repayment_schedule/LoanRepaymentScheduleScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_repayment_schedule/LoanRepaymentScheduleScreen.kt @@ -31,15 +31,15 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.common.Network import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.loan.LoanWithAssociations import org.mifos.mobile.core.model.entity.accounts.loan.Periods -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.EmptyDataView +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.feature.loan.R @Composable @@ -67,7 +67,7 @@ fun LoanRepaymentScheduleScreen( onRetry: () -> Unit ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.loan_repayment_schedule, navigateBack = { navigateBack.invoke() }) { contentPadding -> when (loanRepaymentScheduleUiState) { diff --git a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_review/ReviewLoanApplicationScreen.kt b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_review/ReviewLoanApplicationScreen.kt index 13c4904ed..2d6db33ec 100644 --- a/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_review/ReviewLoanApplicationScreen.kt +++ b/feature/loan/src/main/java/org/mifos/mobile/feature/loan/loan_review/ReviewLoanApplicationScreen.kt @@ -22,12 +22,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.component.NoInternet -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.enums.LoanState +import org.mifos.mobile.core.ui.component.MifosProgressIndicator +import org.mifos.mobile.core.ui.component.NoInternet import org.mifos.mobile.feature.loan.R diff --git a/feature/location/src/main/java/org/mifos/mobile/feature/location/LocationScreen.kt b/feature/location/src/main/java/org/mifos/mobile/feature/location/LocationScreen.kt index f29ab9933..d9e3197c9 100644 --- a/feature/location/src/main/java/org/mifos/mobile/feature/location/LocationScreen.kt +++ b/feature/location/src/main/java/org/mifos/mobile/feature/location/LocationScreen.kt @@ -9,20 +9,16 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView -import com.google.android.gms.maps.MapView import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.GoogleMap import com.google.maps.android.compose.Marker import com.google.maps.android.compose.MarkerState import com.google.maps.android.compose.rememberCameraPositionState -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import kotlin.coroutines.coroutineContext +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme @Composable fun LocationsScreen() { diff --git a/feature/notification/build.gradle.kts b/feature/notification/build.gradle.kts index aea537f97..72e05e333 100644 --- a/feature/notification/build.gradle.kts +++ b/feature/notification/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/notification/src/main/java/org/mifos/mobile/feature/notification/NotificationScreen.kt b/feature/notification/src/main/java/org/mifos/mobile/feature/notification/NotificationScreen.kt index 7aa3d96dc..354f15f41 100644 --- a/feature/notification/src/main/java/org/mifos/mobile/feature/notification/NotificationScreen.kt +++ b/feature/notification/src/main/java/org/mifos/mobile/feature/notification/NotificationScreen.kt @@ -36,14 +36,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.datastore.model.MifosNotification +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.utils.DateHelper -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.datastore.model.MifosNotification @Composable fun NotificationScreen( @@ -73,10 +73,10 @@ fun NotificationScreen( onRefresh: () -> Unit ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.notification, navigateBack = navigateBack, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { when (uiState) { is NotificationUiState.Loading -> { diff --git a/feature/qr/build.gradle.kts b/feature/qr/build.gradle.kts index 110f62b48..2a50422cb 100644 --- a/feature/qr/build.gradle.kts +++ b/feature/qr/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr/QrCodeReaderScreen.kt b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr/QrCodeReaderScreen.kt index e3d2e97e1..0ac13c8e2 100644 --- a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr/QrCodeReaderScreen.kt +++ b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr/QrCodeReaderScreen.kt @@ -20,11 +20,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.google.gson.Gson import com.google.gson.JsonSyntaxException +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.enums.BeneficiaryState -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosIcons -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.qr.R @Composable @@ -36,10 +36,10 @@ fun QrCodeReaderScreen( val gson = Gson() - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.add_beneficiary, navigateBack = navigateBack, - scaffoldContent = { it -> + content = { it -> Box(modifier = Modifier .padding(it) .fillMaxSize()) { diff --git a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_display/QrCodeDisplayScreen.kt b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_display/QrCodeDisplayScreen.kt index a3f5f3679..cf40ca1f5 100644 --- a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_display/QrCodeDisplayScreen.kt +++ b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_display/QrCodeDisplayScreen.kt @@ -30,12 +30,12 @@ import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat.startActivity import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MFScaffold +import org.mifos.mobile.core.common.utils.Utils +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.utils.Utils import org.mifos.mobile.feature.qr.R @@ -60,7 +60,7 @@ fun QrCodeDisplayScreen( val context = LocalContext.current var qrBitmap by rememberSaveable { mutableStateOf(null) } - MFScaffold( + MifosScaffold( topBar = { MifosTopBar( navigateBack = navigateBack, @@ -82,7 +82,7 @@ fun QrCodeDisplayScreen( } ) }, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box( modifier = Modifier .padding(paddingValues = paddingValues) diff --git a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportContent.kt b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportContent.kt index 8731f5a2c..776fc99b4 100644 --- a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportContent.kt +++ b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportContent.kt @@ -1,6 +1,5 @@ package org.mifos.mobile.feature.qr.qr_code_import -import android.Manifest import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap diff --git a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportScreen.kt b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportScreen.kt index 38df73923..691fe485e 100644 --- a/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportScreen.kt +++ b/feature/qr/src/main/java/org/mifos/mobile/feature/qr/qr_code_import/QrCodeImportScreen.kt @@ -1,14 +1,12 @@ package org.mifos.mobile.feature.qr.qr_code_import import android.Manifest -import android.app.Activity import android.graphics.Bitmap import android.graphics.ImageDecoder import android.net.Uri import android.os.Build import android.provider.MediaStore import android.widget.Toast -import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi @@ -26,7 +24,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier @@ -38,8 +35,6 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.canhub.cropper.CropImageContract @@ -50,12 +45,12 @@ import com.google.gson.JsonSyntaxException import com.google.zxing.BarcodeFormat import com.google.zxing.Result import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.enums.BeneficiaryState -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.qr.R @RequiresApi(Build.VERSION_CODES.TIRAMISU) @@ -100,7 +95,7 @@ fun QrCodeImportScreen( ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.import_qr, navigateBack = { navigateBack.invoke() } ) { diff --git a/feature/recent_transaction/build.gradle.kts b/feature/recent_transaction/build.gradle.kts index 9a549b9a5..12b74aaae 100644 --- a/feature/recent_transaction/build.gradle.kts +++ b/feature/recent_transaction/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/recent_transaction/src/main/java/org/mifos/mobile/feature/recent_transaction/screens/RecentTransactionScreen.kt b/feature/recent_transaction/src/main/java/org/mifos/mobile/feature/recent_transaction/screens/RecentTransactionScreen.kt index 4db1e9eff..7f7b0e4d6 100644 --- a/feature/recent_transaction/src/main/java/org/mifos/mobile/feature/recent_transaction/screens/RecentTransactionScreen.kt +++ b/feature/recent_transaction/src/main/java/org/mifos/mobile/feature/recent_transaction/screens/RecentTransactionScreen.kt @@ -35,18 +35,18 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.feature.recent_transaction.R +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.common.utils.CurrencyUtil +import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.common.utils.Utils +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.Transaction import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.utils.CurrencyUtil -import org.mifos.mobile.core.common.utils.DateHelper -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.model.entity.Transaction -import org.mifos.mobile.core.common.utils.Utils +import org.mifos.mobile.feature.recent_transaction.R import org.mifos.mobile.feature.recent_transaction.utils.RecentTransactionState import org.mifos.mobile.feature.recent_transaction.viewmodel.RecentTransactionViewModel @@ -88,10 +88,10 @@ fun RecentTransactionScreen( val context = LocalContext.current val pullRefreshState = rememberPullToRefreshState() - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.recent_transactions, navigateBack = navigateBack, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box( Modifier diff --git a/feature/savings/build.gradle.kts b/feature/savings/build.gradle.kts index ece989e25..729e016c9 100644 --- a/feature/savings/build.gradle.kts +++ b/feature/savings/build.gradle.kts @@ -9,7 +9,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingAccountsDetailViewModel.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingAccountsDetailViewModel.kt index dbd496217..67b61fcfd 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingAccountsDetailViewModel.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingAccountsDetailViewModel.kt @@ -12,15 +12,15 @@ import kotlinx.coroutines.flow.stateIn import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.data.repository.SavingsAccountRepository import org.mifos.mobile.core.datastore.PreferencesHelper +import org.mifos.mobile.core.designsystem.theme.Blue +import org.mifos.mobile.core.designsystem.theme.DepositGreen +import org.mifos.mobile.core.designsystem.theme.LightYellow +import org.mifos.mobile.core.designsystem.theme.RedLight import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations import org.mifos.mobile.core.model.entity.accounts.savings.Status import org.mifos.mobile.core.model.enums.AccountType import org.mifos.mobile.core.network.Result import org.mifos.mobile.core.network.asResult -import org.mifos.mobile.core.ui.theme.Blue -import org.mifos.mobile.core.ui.theme.DepositGreen -import org.mifos.mobile.core.ui.theme.LightYellow -import org.mifos.mobile.core.ui.theme.RedLight import org.mifos.mobile.feature.qr.utils.QrCodeGenerator import org.mifos.mobile.feature.savings.R import javax.inject.Inject diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailScreen.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailScreen.kt index 037c802eb..73116c258 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailScreen.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailScreen.kt @@ -1,26 +1,18 @@ package org.mifos.mobile.feature.savings.savings_account -import android.widget.Toast import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.component.NoInternet -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations -import org.mifos.mobile.core.ui.component.MFScaffold +import org.mifos.mobile.core.ui.component.EmptyDataView import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.feature.savings.R @@ -68,7 +60,7 @@ fun SavingsAccountDetailScreen( callUs: () -> Unit, deposit: () -> Unit, ) { - MFScaffold( + MifosScaffold( topBar = { SavingsAccountDetailTopBar( navigateBack = navigateBack, diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailTopBar.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailTopBar.kt index 18b6f1c6e..072051417 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailTopBar.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account/SavingsAccountDetailTopBar.kt @@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.feature.savings.R @OptIn(ExperimentalMaterial3Api::class) diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationContent.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationContent.kt index b77a8b79b..ee5b7a03c 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationContent.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationContent.kt @@ -37,9 +37,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.model.entity.templates.savings.SavingsAccountTemplate -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.utils.getTodayFormatted +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.templates.savings.SavingsAccountTemplate import org.mifos.mobile.feature.savings.R @Composable diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationScreen.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationScreen.kt index 4d69f42b1..285f431fa 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationScreen.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_application/SavingsAccountApplicationScreen.kt @@ -2,8 +2,6 @@ package org.mifos.mobile.feature.savings.savings_account_application import android.widget.Toast import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -17,15 +15,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.component.NoInternet -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations import org.mifos.mobile.core.model.enums.SavingsAccountState -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.feature.savings.R @@ -55,14 +49,14 @@ fun SavingsAccountApplicationScreen( var topBarTitleText by rememberSaveable { mutableStateOf("") } val context = LocalContext.current - MFScaffold( + MifosScaffold( topBar = { MifosTopBar( navigateBack = navigateBack, title = { Text(text = topBarTitleText) } ) }, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it)) { when (uiState) { is SavingsAccountApplicationUiState.Error -> { diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountTransactionContent.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountTransactionContent.kt index fd2e29946..6d22c94e3 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountTransactionContent.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountTransactionContent.kt @@ -25,10 +25,10 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.model.entity.accounts.savings.Transactions -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.utils.CurrencyUtil import org.mifos.mobile.core.common.utils.DateHelper +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.accounts.savings.Transactions import org.mifos.mobile.feature.savings.R @Composable diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionFilterDialog.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionFilterDialog.kt index d796c17ca..1a00e2328 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionFilterDialog.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionFilterDialog.kt @@ -29,13 +29,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import org.mifos.mobile.core.ui.component.MifosCheckBox -import org.mifos.mobile.core.ui.component.MifosIconTextButton -import org.mifos.mobile.core.ui.component.MifosIcons -import org.mifos.mobile.core.ui.component.MifosRadioButton -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.utils.DateHelper import org.mifos.mobile.core.common.utils.DateHelper.getDateAsStringFromLong +import org.mifos.mobile.core.designsystem.components.MifosIconTextButton +import org.mifos.mobile.core.designsystem.components.MifosRadioButton +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.MifosCheckBox import org.mifos.mobile.feature.savings.R import java.time.Instant diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionScreen.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionScreen.kt index 1dfe385db..e495cff5f 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionScreen.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionScreen.kt @@ -22,15 +22,15 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.EmptyDataView -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosIcons -import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.icons.MifosIcons +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.accounts.savings.Transactions +import org.mifos.mobile.core.ui.component.EmptyDataView +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.feature.savings.R import java.time.Instant @@ -75,7 +75,7 @@ fun SavingsAccountTransactionScreen( ) } - MFScaffold( + MifosScaffold( topBar = { MifosTopBar( navigateBack = navigateBack, @@ -97,7 +97,7 @@ fun SavingsAccountTransactionScreen( } ) }, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues = paddingValues)) { when (uiState) { is SavingsAccountTransactionUiState.Loading -> { diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionViewModel.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionViewModel.kt index 72aaf53a2..6f7028b73 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionViewModel.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_transaction/SavingAccountsTransactionViewModel.kt @@ -14,11 +14,11 @@ import kotlinx.parcelize.Parcelize import org.mifos.mobile.core.common.Constants.SAVINGS_ID import org.mifos.mobile.core.common.utils.DateHelper import org.mifos.mobile.core.data.repository.SavingsAccountRepository +import org.mifos.mobile.core.designsystem.theme.DepositGreen +import org.mifos.mobile.core.designsystem.theme.GreenSuccess +import org.mifos.mobile.core.designsystem.theme.RedLight import org.mifos.mobile.core.model.entity.accounts.savings.TransactionType import org.mifos.mobile.core.model.entity.accounts.savings.Transactions -import org.mifos.mobile.core.ui.theme.DepositGreen -import org.mifos.mobile.core.ui.theme.GreenSuccess -import org.mifos.mobile.core.ui.theme.RedLight import org.mifos.mobile.feature.savings.R import javax.inject.Inject diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_withdraw/SavingsAccountWithdrawScreen.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_withdraw/SavingsAccountWithdrawScreen.kt index 0fa6d8ab3..d530349fa 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_withdraw/SavingsAccountWithdrawScreen.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_account_withdraw/SavingsAccountWithdrawScreen.kt @@ -28,15 +28,15 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.common.utils.getTodayFormatted +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.core.ui.component.MifosTitleDescSingleLineEqual -import org.mifos.mobile.core.ui.component.MifosTopBar import org.mifos.mobile.core.ui.component.NoInternet -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.model.entity.accounts.savings.SavingsWithAssociations -import org.mifos.mobile.core.common.utils.getTodayFormatted import org.mifos.mobile.feature.savings.R diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferContent.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferContent.kt index dd2c545b0..0a69fe631 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferContent.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferContent.kt @@ -33,16 +33,16 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.theme.DarkGray +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.Primary import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload import org.mifos.mobile.core.model.entity.templates.account.AccountOption import org.mifos.mobile.core.ui.component.MFStepProcess import org.mifos.mobile.core.ui.component.MifosDropDownDoubleTextField -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField import org.mifos.mobile.core.ui.component.StepProcessState import org.mifos.mobile.core.ui.component.getStepState -import org.mifos.mobile.core.ui.theme.DarkGray -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.ui.theme.Primary import org.mifos.mobile.feature.savings.R @Composable diff --git a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferScreen.kt b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferScreen.kt index ff75c21d9..0a62d6afe 100644 --- a/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferScreen.kt +++ b/feature/savings/src/main/java/org/mifos/mobile/feature/savings/savings_make_transfer/SavingsMakeTransferScreen.kt @@ -11,13 +11,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosErrorComponent -import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.common.Constants import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload import org.mifos.mobile.core.model.enums.TransferType +import org.mifos.mobile.core.ui.component.MifosErrorComponent +import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.feature.savings.R @Composable @@ -49,11 +50,11 @@ fun SavingsMakeTransferScreen( ) { val context = LocalContext.current - MFScaffold( - topBarTitleResId = if(uiData.transferType == org.mifos.mobile.core.common.Constants.TRANSFER_PAY_TO) R.string.deposit + MifosScaffold( + topBarTitleResId = if(uiData.transferType == Constants.TRANSFER_PAY_TO) R.string.deposit else R.string.transfer, navigateBack = navigateBack, - scaffoldContent = { + content = { Box(modifier = Modifier.padding(it).fillMaxSize()) { SavingsMakeTransferContent( uiData = uiData, diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts index 954e6e86f..a2d85dc46 100644 --- a/feature/settings/build.gradle.kts +++ b/feature/settings/build.gradle.kts @@ -8,7 +8,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/settings/src/main/java/org/mifos/mobile/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/org/mifos/mobile/feature/settings/SettingsScreen.kt index c82dc22cd..05a903cf7 100644 --- a/feature/settings/src/main/java/org/mifos/mobile/feature/settings/SettingsScreen.kt +++ b/feature/settings/src/main/java/org/mifos/mobile/feature/settings/SettingsScreen.kt @@ -33,13 +33,13 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MFScaffold -import org.mifos.mobile.core.ui.component.MifosRadioButtonDialog -import org.mifos.mobile.core.ui.component.MifosTopBarTitle -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.model.enums.AppTheme import org.mifos.mobile.core.common.utils.LanguageHelper +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.components.MifosTopBarTitle +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.enums.AppTheme import org.mifos.mobile.core.model.enums.MifosAppLanguage +import org.mifos.mobile.core.ui.component.MifosRadioButtonDialog import java.util.Locale @Composable @@ -101,7 +101,7 @@ fun SettingsScreen( var showEndpointUpdateDialog by rememberSaveable { mutableStateOf(false) } var showThemeUpdateDialog by rememberSaveable { mutableStateOf(false) } - MFScaffold( + MifosScaffold( topBar = { MifosTopBarTitle( navigateBack = navigateBack, diff --git a/feature/settings/src/main/java/org/mifos/mobile/feature/settings/UpdateEndpointDialog.kt b/feature/settings/src/main/java/org/mifos/mobile/feature/settings/UpdateEndpointDialog.kt index ca01b712c..5df9ec200 100644 --- a/feature/settings/src/main/java/org/mifos/mobile/feature/settings/UpdateEndpointDialog.kt +++ b/feature/settings/src/main/java/org/mifos/mobile/feature/settings/UpdateEndpointDialog.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import org.mifos.mobile.core.ui.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme @Composable fun UpdateEndpointDialogScreen( diff --git a/feature/third-party-transfer/build.gradle.kts b/feature/third-party-transfer/build.gradle.kts index 4069e46c2..44f5cd706 100644 --- a/feature/third-party-transfer/build.gradle.kts +++ b/feature/third-party-transfer/build.gradle.kts @@ -10,7 +10,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferContent.kt b/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferContent.kt index 7caa62754..2981b56d7 100644 --- a/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferContent.kt +++ b/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferContent.kt @@ -32,19 +32,19 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextButton +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosTextButton +import org.mifos.mobile.core.designsystem.theme.DarkGray +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.designsystem.theme.Primary import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload import org.mifos.mobile.core.model.entity.templates.account.AccountOption import org.mifos.mobile.core.ui.component.MFStepProcess import org.mifos.mobile.core.ui.component.MifosDropDownDoubleTextField -import org.mifos.mobile.core.ui.component.MifosOutlinedTextButton -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField -import org.mifos.mobile.core.ui.component.MifosTextButton import org.mifos.mobile.core.ui.component.StepProcessState import org.mifos.mobile.core.ui.component.getStepState -import org.mifos.mobile.core.ui.theme.DarkGray -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.ui.theme.Primary import org.mifos.mobile.feature.third.party.transfer.R @Composable diff --git a/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferScreen.kt b/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferScreen.kt index 8cbe2ec3c..219bc1fc4 100644 --- a/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferScreen.kt +++ b/feature/third-party-transfer/src/main/java/org/mifos/mobile/feature/third/party/transfer/third_party_transfer/ThirdPartyTransferScreen.kt @@ -13,12 +13,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme import org.mifos.mobile.core.model.entity.payload.ReviewTransferPayload import org.mifos.mobile.core.model.enums.TransferType -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.feature.third.party.transfer.R @Composable @@ -49,10 +49,10 @@ fun ThirdPartyTransferScreen( reviewTransfer: (ReviewTransferPayload) -> Unit ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.third_party_transfer, navigateBack = navigateBack, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box(modifier = Modifier.padding(paddingValues = paddingValues)) { when(uiState) { is ThirdPartyTransferUiState.ShowUI -> { diff --git a/feature/transfer-process/build.gradle.kts b/feature/transfer-process/build.gradle.kts index d8abc9a29..04ca5a00e 100644 --- a/feature/transfer-process/build.gradle.kts +++ b/feature/transfer-process/build.gradle.kts @@ -9,7 +9,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/transfer-process/src/main/java/org/mifos/mobile/feature/transfer/process/TransferProcessScreen.kt b/feature/transfer-process/src/main/java/org/mifos/mobile/feature/transfer/process/TransferProcessScreen.kt index b22e1abe4..f079e7874 100644 --- a/feature/transfer-process/src/main/java/org/mifos/mobile/feature/transfer/process/TransferProcessScreen.kt +++ b/feature/transfer-process/src/main/java/org/mifos/mobile/feature/transfer/process/TransferProcessScreen.kt @@ -34,12 +34,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MFScaffold +import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosScaffold +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.model.entity.payload.TransferPayload import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay -import org.mifos.mobile.core.ui.theme.MifosMobileTheme -import org.mifos.mobile.core.common.Network -import org.mifos.mobile.core.model.entity.payload.TransferPayload @Composable @@ -67,10 +67,10 @@ fun TransferProcessScreen( ) { val context = LocalContext.current - MFScaffold( + MifosScaffold( topBarTitleResId = R.string.transfer, navigateBack = navigateBack, - scaffoldContent = { paddingValues -> + content = { paddingValues -> Box( modifier = Modifier .padding(paddingValues) diff --git a/feature/update-password/build.gradle.kts b/feature/update-password/build.gradle.kts index ed0d02665..f468e58ae 100644 --- a/feature/update-password/build.gradle.kts +++ b/feature/update-password/build.gradle.kts @@ -9,7 +9,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordContent.kt b/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordContent.kt index 4b7dda7d8..52f5097b5 100644 --- a/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordContent.kt +++ b/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordContent.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType @@ -31,8 +30,7 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import org.mifos.mobile.core.ui.component.MifosOutlinedTextField +import org.mifos.mobile.core.designsystem.components.MifosOutlinedTextField import org.mifos.mobile.feature.update.password.R @Composable diff --git a/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordScreen.kt b/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordScreen.kt index 84166e3ff..38ef24d09 100644 --- a/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordScreen.kt +++ b/feature/update-password/src/main/java/org/mifos/mobile/feature/update_password/UpdatePasswordScreen.kt @@ -26,10 +26,10 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import org.mifos.mobile.core.ui.component.MifosProgressIndicator -import org.mifos.mobile.core.ui.component.MifosTopBar -import org.mifos.mobile.core.ui.theme.MifosMobileTheme import org.mifos.mobile.core.common.Network +import org.mifos.mobile.core.designsystem.components.MifosTopBar +import org.mifos.mobile.core.designsystem.theme.MifosMobileTheme +import org.mifos.mobile.core.ui.component.MifosProgressIndicator import org.mifos.mobile.feature.update.password.R diff --git a/feature/user_profile/build.gradle.kts b/feature/user_profile/build.gradle.kts index e8fe962eb..02af52b27 100644 --- a/feature/user_profile/build.gradle.kts +++ b/feature/user_profile/build.gradle.kts @@ -10,7 +10,7 @@ android { } dependencies { - implementation(projects.ui) + implementation(projects.core.ui) implementation(projects.core.common) implementation(projects.core.model) implementation(projects.core.data) diff --git a/feature/user_profile/src/main/java/org/mifos/mobile/feature/user_profile/screens/UserProfileScreen.kt b/feature/user_profile/src/main/java/org/mifos/mobile/feature/user_profile/screens/UserProfileScreen.kt index 4f2664d31..66d27e8a2 100644 --- a/feature/user_profile/src/main/java/org/mifos/mobile/feature/user_profile/screens/UserProfileScreen.kt +++ b/feature/user_profile/src/main/java/org/mifos/mobile/feature/user_profile/screens/UserProfileScreen.kt @@ -34,9 +34,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.mifos.mobile.core.common.Network import org.mifos.mobile.core.common.utils.DateHelper import org.mifos.mobile.core.datastore.PreferencesHelper +import org.mifos.mobile.core.designsystem.components.MifosScaffold import org.mifos.mobile.core.model.entity.client.Client import org.mifos.mobile.core.model.entity.client.Group -import org.mifos.mobile.core.ui.component.MFScaffold import org.mifos.mobile.core.ui.component.MifosErrorComponent import org.mifos.mobile.core.ui.component.MifosProgressIndicatorOverlay import org.mifos.mobile.core.ui.component.MifosUserImage @@ -88,12 +88,12 @@ fun UserProfileScreen( SnackbarHostState() } - MFScaffold( + MifosScaffold( topBar = { UserProfileTopBar(home = navigateBack, text = R.string.user_details) }, snackbarHost = { SnackbarHost(hostState = snackBarHostState) }, - scaffoldContent = { paddingValues -> + content = { paddingValues -> when (uiState) { is UserDetailUiState.ShowError -> { diff --git a/gradle.properties b/gradle.properties index 14537dca4..f95c904a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g +org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=4g # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b64665a6a..61916c74b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,33 +1,11 @@ [versions] androidImageCropperVersion = "4.0.0" + +activityVersion = "1.5.0" annotationVersion = "1.1.0" appcompatVersion = "1.6.1" -biometricVersion = "1.1.0" -ccpVersion = "2.7.2" -compileSdk = "34" -constraintlayoutVersion = "2.1.4" -coreKtxVersion = "1.12.0" -coreTestingVersion = "2.2.0" -coreVersion = "3.5.2" -countrycodechooserVersion = "1.0" -detekt = "1.23.5" -espressoContribVersion = "3.5.1" -kotlinxCoroutinesAndroidVersion = "1.6.4" -kotlinxCoroutinesTestVersion = "1.7.3" -legacySupportV4Version = "1.0.0" -mifosPasscodeVersion = "1.0.3" -minSdk = "24" -mockitoAndroidVersion = "5.4.0" -mockitoCoreVersion = "5.4.0" -mockitoCore = "5.4.0" -multidexVersion = "2.0.1" -recyclerviewVersion = "1.2.1" -rulesVersion = "1.6.0-alpha01" -runnerVersion = "1.6.0-alpha04" -simplecropviewVersion = "1.1.8" -sweetErrorVersion = "1.0.0" -tableviewVersion = "0.8.9.4" -targetSdk = "34" +androidDesugarJdkLibs = "2.0.4" +androidx-test-ext-junit = "1.1.5" androidGradlePlugin = "8.2.2" androidTools = "31.2.1" androidxActivity = "1.7.2" @@ -36,67 +14,140 @@ androidxComposeCompiler = "1.5.14" androidxCore = "1.10.1" androidxHilt = "1.1.0-alpha01" androidxLifecycle = "2.6.1" -hilt = "2.50" -junit = "4.13.2" -kotlin = "1.9.24" -ksp = "1.9.21-1.0.16" -firebaseCrashlyticsPlugin = "2.9.2" -gmsPlugin = "4.3.14" +androidxNavigation = "2.8.0-rc01" +androidxCoreSplashscreen = "1.0.1" + +biometricVersion = "1.1.0" butterknifePlugin = "10.2.3" -secrets = "2.0.1" -lifecycleVersion = "2.6.2" -lifecycleExtensionsVersion = "2.2.0" -activityVersion = "1.5.0" -fragmentVersion = "1.5.0" -retrofitVersion = "2.9.0" -okHttp3Version = "3.14.9" butterKnifeVersion = "10.2.3" -rxandroidVersion = "2.1.1" -rxjavaVersion = "2.2.21" -junitVersion = "4.12" -firebasePerfPlugin = "1.4.2" -truth = "1.1.5" -dependencyGuard = "0.4.3" -room = "2.6.1" -roborazzi = "1.6.0" -googleOss = "17.0.1" -googleOssPlugin = "0.10.6" -firebaseBom = "32.7.1" -androidDesugarJdkLibs = "2.0.4" -androidx-test-ext-junit = "1.1.5" -espresso-core = "3.5.1" -material = "1.11.0" -dbflowVersion = "4.2.4" -preference = "1.0.0" -playServicesVersion = "17.0.1" -spotbugs = "4.8.0" -spotlessVersion = "6.23.3" -material3 = "1.2.1" -playServicesCodeScanner = "16.1.0" -googleAppCodeScanner = "17.2.0" + +ccpVersion = "2.7.2" +constraintlayoutVersion = "2.1.4" + +compileSdk = "34" + +coreKtxVersion = "1.12.0" +coreTestingVersion = "2.2.0" +coreVersion = "3.5.2" cameraxVersion = "1.3.1" compose-material = "1.6.8" + +countrycodechooserVersion = "1.0" + +detekt = "1.23.5" +dependencyGuard = "0.4.3" +dbflowVersion = "4.2.4" + +espressoContribVersion = "3.5.1" +espresso-core = "3.5.1" + +fragmentVersion = "1.5.0" +firebaseCrashlyticsPlugin = "2.9.2" +firebasePerfPlugin = "1.4.2" +firebaseBom = "32.7.1" + +gmsPlugin = "4.3.14" +googleOss = "17.0.1" +googleOssPlugin = "0.10.6" googleMaps = "4.4.1" +googleAppCodeScanner = "17.2.0" + +hilt = "2.50" + +junit = "4.13.2" +junitVersion = "4.12" + +kotlin = "1.9.24" +ksp = "1.9.21-1.0.16" +kotlinxCoroutinesAndroidVersion = "1.6.4" +kotlinxCoroutinesTestVersion = "1.7.3" +kotlinxImmutable = "0.3.7" + +legacySupportV4Version = "1.0.0" +lifecycleVersion = "2.6.2" +lifecycleExtensionsVersion = "2.2.0" +libphonenumberAndroidVersion = "8.13.35" + +minSdk = "24" +material = "1.11.0" +material3 = "1.2.1" +mifosPasscodeVersion = "1.0.3" +mockitoAndroidVersion = "5.4.0" +mockitoCoreVersion = "5.4.0" +mockitoCore = "5.4.0" +multidexVersion = "2.0.1" +spotbugs = "4.8.0" +spotlessVersion = "6.23.3" + +okHttp3Version = "3.14.9" + +preference = "1.0.0" +playServicesVersion = "17.0.1" +playServicesCodeScanner = "16.1.0" + +recyclerviewVersion = "1.2.1" +rulesVersion = "1.6.0-alpha01" +runnerVersion = "1.6.0-alpha04" +retrofitVersion = "2.9.0" +rxandroidVersion = "2.1.1" +rxjavaVersion = "2.2.21" +room = "2.6.1" +roborazzi = "1.6.0" + +simplecropviewVersion = "1.1.8" +sweetErrorVersion = "1.0.0" +secrets = "2.0.1" + +tableviewVersion = "0.8.9.4" +targetSdk = "34" + +truth = "1.1.5" turbineVersion = "1.1.0" twitter-detekt-compose = "0.0.26" + uihouseVersion = "alpha-2.1" + vectordrawableVersion = "1.1.0" + zxingVersion = "1.9.13" +[bundles] +androidx-compose-ui-test = ["androidx-compose-ui-test", "androidx-compose-ui-test-manifest"] + [libraries] android-image-cropper = { module = "com.github.CanHub:Android-Image-Cropper", version.ref = "androidImageCropperVersion" } + androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityVersion" } androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotationVersion" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompatVersion" } androidx-biometric = { module = "androidx.biometric:biometric", version.ref = "biometricVersion" } androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayoutVersion" } -androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtxVersion" } androidx-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "coreTestingVersion" } androidx-espresso-contrib = { module = "androidx.test.espresso:espresso-contrib", version.ref = "espressoContribVersion" } androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentVersion" } +androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacySupportV4Version" } +androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidexVersion" } +androidx-rules = { module = "androidx.test:rules", version.ref = "rulesVersion" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runnerVersion" } +androidx-vectordrawable = { module = "androidx.vectordrawable:vectordrawable", version.ref = "vectordrawableVersion" } +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerviewVersion" } +androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" } + +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtxVersion" } +androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidxCoreSplashscreen" } + android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" } -androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } + +androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidxHilt" } +androidx-lifecycle-runtimeCompose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidxLifecycle" } +androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" } +androidx-lifecycle-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleVersion" } +androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycleExtensionsVersion" } +androidx-lifecycle-runtimeTesting = { group = "androidx.lifecycle", name = "lifecycle-runtime-testing", version.ref = "androidxLifecycle" } + androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidxActivity" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } +androidx-compose-animation = { group = "androidx.compose.animation", name = "animation" } androidx-compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "androidxComposeCompiler" } androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" } @@ -104,72 +155,89 @@ androidx-compose-material = { group = "androidx.compose.material", name = "mater androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3"} androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui"} -androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4"} +androidx-compose-ui-util = { group = "androidx.compose.ui", name = "ui-util"} +androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4"} androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest"} androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling"} -androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } -androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacySupportV4Version" } -androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidexVersion" } -androidx-rules = { module = "androidx.test:rules", version.ref = "rulesVersion" } -androidx-runner = { module = "androidx.test:runner", version.ref = "runnerVersion" } -androidx-vectordrawable = { module = "androidx.vectordrawable:vectordrawable", version.ref = "vectordrawableVersion" } -androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerviewVersion" } -ccp = { module = "com.hbb20:ccp", version.ref = "ccpVersion" } -zxing-core = { module = "com.google.zxing:core", version.ref = "coreVersion" } -countrycodechooser = { module = "com.github.ParveshSandila:CountryCodeChooser", version.ref = "countrycodechooserVersion" } -hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } -hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview"} -androidx-compose-ui-util = { group = "androidx.compose.ui", name = "ui-util"} -androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "androidxHilt" } -androidx-lifecycle-runtimeCompose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidxLifecycle" } -androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" } -androidx-lifecycle-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleVersion" } -androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycleExtensionsVersion" } -jakewharton-butterknife = { module = "com.jakewharton:butterknife", version.ref = "butterKnifeVersion" } -jakewharton-compiler = { module = "com.jakewharton:butterknife-compiler", version.ref = "butterKnifeVersion" } +androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } + +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" } +androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "androidxNavigation" } + +kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroidVersion" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTestVersion" } -mifos-passcode = { module = "com.github.openMF.mifos-passcode:compose", version.ref = "mifosPasscodeVersion" } -mockito-android = { module = "org.mockito:mockito-android", version.ref = "mockitoAndroidVersion" } -mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCoreVersion" } -simplecropview = { module = "com.isseiaoki:simplecropview", version.ref = "simplecropviewVersion" } +kotlinx-collections-immutable = { group = "org.jetbrains.kotlinx", name = "kotlinx-collections-immutable", version.ref = "kotlinxImmutable" } + +hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } +hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } +hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" } + squareup-retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" } squareup-retrofit-adapter-rxjava = { module = "com.squareup.retrofit2:adapter-rxjava2", version.ref = "retrofitVersion" } squareup-retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" } squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp3Version" } squareup-logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okHttp3Version" } + reactivex-rxjava2-android = { module = "io.reactivex.rxjava2:rxandroid", version.ref = "rxandroidVersion" } reactivex-rxjava2 = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjavaVersion" } -sweet-error = { module = "com.github.therajanmaurya:Sweet-Error", version.ref = "sweetErrorVersion" } -tableview = { module = "com.evrencoskun.library:tableview", version.ref = "tableviewVersion" } -truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } -junit = { module = "junit:junit", version.ref = "junitVersion"} -google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" } -google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" } -jetbrains-kotlin-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" } + firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" } firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics-ktx" } firebase-cloud-messaging = { group = "com.google.firebase", name = "firebase-messaging-ktx" } firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" } firebase-performance = { group = "com.google.firebase", name = "firebase-perf-ktx" } + dbflow-processor = { group = "com.github.Raizlabs.DBFlow", name = "dbflow-processor", version.ref = "dbflowVersion" } dbflow-core = { group = "com.github.Raizlabs.DBFlow", name = "dbflow-core", version.ref = "dbflowVersion" } dbflow = { group = "com.github.Raizlabs.DBFlow", name = "dbflow", version.ref = "dbflowVersion" } -androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" } -play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesVersion" } -google-play-services-code-scanner = { group = "com.google.android.gms", name = "play-services-code-scanner", version.ref = "playServicesCodeScanner" } -google-app-code-scanner = { group = "com.google.mlkit", name = "barcode-scanning", version.ref = "googleAppCodeScanner"} + androidx-camera-camera2 = { group = "androidx.camera", name = "camera-camera2", version.ref = "cameraxVersion"} androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "cameraxVersion"} androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "cameraxVersion"} androidx-camera-core = { group = "androidx.camera", name = "camera-core", version.ref = "cameraxVersion" } + +play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesVersion" } +google-play-services-code-scanner = { group = "com.google.android.gms", name = "play-services-code-scanner", version.ref = "playServicesCodeScanner" } +google-app-code-scanner = { group = "com.google.mlkit", name = "barcode-scanning", version.ref = "googleAppCodeScanner"} google-map-compose = { group = "com.google.maps.android", name = "maps-compose", version.ref = "googleMaps" } +mockito-android = { module = "org.mockito:mockito-android", version.ref = "mockitoAndroidVersion" } +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCoreVersion" } + +truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } + +google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" } +google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" } + +junit = { module = "junit:junit", version.ref = "junitVersion"} +jetbrains-kotlin-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" } + +libphonenumber-android = { module = "io.michaelrocks:libphonenumber-android", version.ref = "libphonenumberAndroidVersion" } + +lint-api = { group = "com.android.tools.lint", name = "lint-api", version.ref = "androidTools" } +lint-checks = { group = "com.android.tools.lint", name = "lint-checks", version.ref = "androidTools" } +lint-tests = { group = "com.android.tools.lint", name = "lint-tests", version.ref = "androidTools" } + #Detekt detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" } twitter-detekt-compose = { group = "com.twitter.compose.rules", name = "detekt", version.ref = "twitter-detekt-compose" } +zxing-core = { module = "com.google.zxing:core", version.ref = "coreVersion" } + +ccp = { module = "com.hbb20:ccp", version.ref = "ccpVersion" } +countrycodechooser = { module = "com.github.ParveshSandila:CountryCodeChooser", version.ref = "countrycodechooserVersion" } +mifos-passcode = { module = "com.github.openMF.mifos-passcode:compose", version.ref = "mifosPasscodeVersion" } + +jakewharton-butterknife = { module = "com.jakewharton:butterknife", version.ref = "butterKnifeVersion" } +jakewharton-compiler = { module = "com.jakewharton:butterknife-compiler", version.ref = "butterKnifeVersion" } + +simplecropview = { module = "com.isseiaoki:simplecropview", version.ref = "simplecropviewVersion" } +sweet-error = { module = "com.github.therajanmaurya:Sweet-Error", version.ref = "sweetErrorVersion" } + +tableview = { module = "com.evrencoskun.library:tableview", version.ref = "tableviewVersion" } + # Dependencies of the included build-logic android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" } diff --git a/libs/country-code-picker/.gitignore b/libs/country-code-picker/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/libs/country-code-picker/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/libs/country-code-picker/README.md b/libs/country-code-picker/README.md new file mode 100644 index 000000000..fc7c58ad0 --- /dev/null +++ b/libs/country-code-picker/README.md @@ -0,0 +1,5 @@ +## A local fork of the country-code-picker library + +Source: https://github.com/jump-sdk/jetpack_compose_country_code_picker_emoji + +Forked so that we can make use of it while not bringing in m2 dependencies in our project unecessarily diff --git a/libs/country-code-picker/build.gradle.kts b/libs/country-code-picker/build.gradle.kts new file mode 100644 index 000000000..69740c1e1 --- /dev/null +++ b/libs/country-code-picker/build.gradle.kts @@ -0,0 +1,33 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) +} + +android { + namespace = "com.mifos.library.countrycodepicker" +} + +dependencies { + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.foundation.layout) + implementation(libs.androidx.compose.material.iconsExtended) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.compose.ui.util) + + implementation(libs.kotlinx.collections.immutable) + + implementation(libs.libphonenumber.android) + + testImplementation(libs.androidx.compose.ui.test) + androidTestImplementation(libs.androidx.compose.ui.test) +} diff --git a/libs/country-code-picker/src/main/AndroidManifest.xml b/libs/country-code-picker/src/main/AndroidManifest.xml new file mode 100644 index 000000000..3c84395b9 --- /dev/null +++ b/libs/country-code-picker/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/CountryCodePicker.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/CountryCodePicker.kt new file mode 100644 index 000000000..86da45a5d --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/CountryCodePicker.kt @@ -0,0 +1,368 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker + +import android.content.Context +import android.util.Log +import androidx.compose.foundation.focusable +import androidx.compose.foundation.interaction.InteractionSource +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsFocusedAsState +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldColors +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.autofill.AutofillType +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mifos.library.countrycodepicker.component.CountryCodeDialog +import com.mifos.library.countrycodepicker.component.autofill +import com.mifos.library.countrycodepicker.data.CountryData +import com.mifos.library.countrycodepicker.data.Iso31661alpha2 +import com.mifos.library.countrycodepicker.data.PhoneCode +import com.mifos.library.countrycodepicker.data.utils.ValidatePhoneNumber +import com.mifos.library.countrycodepicker.data.utils.extractCountryCode +import com.mifos.library.countrycodepicker.data.utils.getCountryFromPhoneCode +import com.mifos.library.countrycodepicker.data.utils.getUserIsoCode +import com.mifos.library.countrycodepicker.data.utils.numberHint +import com.mifos.library.countrycodepicker.transformation.PhoneNumberTransformation +import kotlinx.collections.immutable.ImmutableSet +import kotlinx.coroutines.launch + +private val DEFAULT_TEXT_FIELD_SHAPE = RoundedCornerShape(24.dp) +private const val TAG = "CountryCodePicker" + +/** + * @param onValueChange Called when the text in the text field changes. + * The first parameter is string pair of (country phone code, phone number) and the second parameter is + * a boolean indicating whether the phone number is valid. + * @param modifier Modifier to be applied to the inner OutlinedTextField. + * @param autoDetectCode Boolean indicating if will auto detect the code from initial phone number + * @param enabled Boolean indicating whether the field is enabled. + * @param shape Shape of the text field. + * @param showCountryCode Whether to show the country code in the text field. + * @param showCountryFlag Whether to show the country flag in the text field. + * @param colors TextFieldColors to be used for the text field. + * @param fallbackCountry The country to be used as a fallback if the user's country cannot be determined. + * Defaults to the United States. + * @param showPlaceholder Whether to show the placeholder number hint in the text field. + * @param includeOnly A set of 2 digit country codes to be included in the list of countries. + * Set to null to include all supported countries. + * @param clearIcon ImageVector to be used for the clear button. Set to null to disable the clear button. + * Defaults to Icons.Filled.Clear + * @param initialPhoneNumber an optional phone number to be initial value of the input field + * @param initialCountryIsoCode Optional ISO-3166-1 alpha-2 country code to set the initially selected country. + * Note that if a valid initialCountryPhoneCode is provided, this will be ignored. + * @param initialCountryPhoneCode Optional country phone code to set the initially selected country. + * This takes precedence over [initialCountryIsoCode]. + * @param label An optional composable to be used as a label for input field + * @param textStyle An optional [TextStyle] for customizing text style of phone number input field. + * Defaults to MaterialTheme.typography.body1 + * @param [keyboardOptions] An optional [KeyboardOptions] to customize keyboard options. + * @param [keyboardActions] An optional [KeyboardActions] to customize keyboard actions. + * @param [showError] Whether to show error on field when number is invalid, default true. + */ +@OptIn(ExperimentalComposeUiApi::class) +@Suppress("LongMethod", "LongParameterList") +@Composable +fun CountryCodePicker( + onValueChange: (Pair, Boolean) -> Unit, + modifier: Modifier = Modifier, + autoDetectCode: Boolean = false, + enabled: Boolean = true, + shape: Shape = DEFAULT_TEXT_FIELD_SHAPE, + showCountryCode: Boolean = true, + showCountryFlag: Boolean = true, + colors: TextFieldColors = OutlinedTextFieldDefaults.colors(), + fallbackCountry: CountryData = CountryData.UnitedStates, + showPlaceholder: Boolean = true, + includeOnly: ImmutableSet? = null, + clearIcon: ImageVector? = Icons.Filled.Clear, + initialPhoneNumber: String? = null, + initialCountryIsoCode: Iso31661alpha2? = null, + initialCountryPhoneCode: PhoneCode? = null, + label: @Composable (() -> Unit)? = null, + textStyle: TextStyle = LocalTextStyle.current, + keyboardOptions: KeyboardOptions? = null, + keyboardActions: KeyboardActions? = null, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + showError: Boolean = true, +) { + val context = LocalContext.current + val focusRequester = remember { FocusRequester() } + + val countryCode = autoDetectedCountryCode( + autoDetectCode = autoDetectCode, + initialPhoneNumber = initialPhoneNumber, + ) + + val phoneNumberWithoutCode = if (countryCode != null) { + initialPhoneNumber?.replace(countryCode, "") + } else { + initialPhoneNumber + } + + var phoneNumber by remember { + mutableStateOf( + TextFieldValue( + text = phoneNumberWithoutCode.orEmpty(), + selection = TextRange(phoneNumberWithoutCode?.length ?: 0), + ), + ) + } + val keyboardController = LocalSoftwareKeyboardController.current + + var country: CountryData by rememberSaveable( + context, + countryCode, + initialCountryPhoneCode, + initialCountryIsoCode, + ) { + mutableStateOf( + configureInitialCountry( + initialCountryPhoneCode = countryCode ?: initialCountryPhoneCode, + context = context, + initialCountryIsoCode = initialCountryIsoCode, + fallbackCountry = fallbackCountry, + ), + ) + } + + val phoneNumberTransformation = remember(country) { + PhoneNumberTransformation(country.countryIso, context) + } + val validatePhoneNumber = remember(context) { ValidatePhoneNumber(context) } + + var isNumberValid: Boolean by rememberSaveable(country, phoneNumber) { + mutableStateOf( + validatePhoneNumber( + fullPhoneNumber = country.countryPhoneCode + phoneNumber.text, + ), + ) + } + + val coroutineScope = rememberCoroutineScope() + + OutlinedTextField( + value = phoneNumber, + onValueChange = { enteredPhoneNumber -> + val preFilteredPhoneNumber = phoneNumberTransformation.preFilter(enteredPhoneNumber) + phoneNumber = TextFieldValue( + text = preFilteredPhoneNumber, + selection = TextRange(preFilteredPhoneNumber.length), + ) + isNumberValid = validatePhoneNumber( + fullPhoneNumber = country.countryPhoneCode + phoneNumber.text, + ) + onValueChange(country.countryPhoneCode to phoneNumber.text, isNumberValid) + }, + modifier = modifier + .fillMaxWidth() + .focusable() + .autofill( + autofillTypes = listOf(AutofillType.PhoneNumberNational), + onFill = { filledPhoneNumber -> + val preFilteredPhoneNumber = + phoneNumberTransformation.preFilter(filledPhoneNumber) + phoneNumber = TextFieldValue( + text = preFilteredPhoneNumber, + selection = TextRange(preFilteredPhoneNumber.length), + ) + isNumberValid = validatePhoneNumber( + fullPhoneNumber = country.countryPhoneCode + phoneNumber.text, + ) + onValueChange(country.countryPhoneCode to phoneNumber.text, isNumberValid) + keyboardController?.hide() + coroutineScope.launch { + focusRequester.safeFreeFocus() + } + }, + focusRequester = focusRequester, + ) + .focusRequester(focusRequester = focusRequester), + enabled = enabled, + textStyle = textStyle, + label = label, + placeholder = { + if (showPlaceholder) { + PlaceholderNumberHint(country.countryIso) + } + }, + leadingIcon = { + CountryCodeDialog( + selectedCountry = country, + includeOnly = includeOnly, + onCountryChange = { countryData -> + country = countryData + isNumberValid = validatePhoneNumber( + fullPhoneNumber = country.countryPhoneCode + phoneNumber.text, + ) + onValueChange(country.countryPhoneCode to phoneNumber.text, isNumberValid) + }, + showCountryCode = showCountryCode, + showFlag = showCountryFlag, + textStyle = textStyle, + ) + }, + trailingIcon = { + if (clearIcon != null) { + ClearIconButton( + imageVector = clearIcon, + colors = colors, + isNumberValid = !showError || isNumberValid, + ) { + phoneNumber = TextFieldValue("") + isNumberValid = false + onValueChange(country.countryPhoneCode to phoneNumber.text, isNumberValid) + } + } + }, + isError = showError && !isNumberValid, + interactionSource = interactionSource, + visualTransformation = phoneNumberTransformation, + keyboardOptions = keyboardOptions ?: KeyboardOptions.Default.copy( + keyboardType = KeyboardType.Phone, + autoCorrect = true, + imeAction = ImeAction.Done, + ), + keyboardActions = keyboardActions ?: KeyboardActions( + onDone = { + keyboardController?.hide() + coroutineScope.launch { + focusRequester.safeFreeFocus() + } + }, + ), + singleLine = true, + shape = shape, + colors = colors, + ) +} + +private fun configureInitialCountry( + initialCountryPhoneCode: PhoneCode?, + context: Context, + initialCountryIsoCode: Iso31661alpha2?, + fallbackCountry: CountryData, +): CountryData { + if (initialCountryPhoneCode?.run { !startsWith("+") } == true) { + Log.e(TAG, "initialCountryPhoneCode must start with +") + } + return initialCountryPhoneCode?.let { getCountryFromPhoneCode(it, context) } + ?: CountryData.entries.firstOrNull { it.countryIso == initialCountryIsoCode } + ?: CountryData.isoMap[getUserIsoCode(context)] + ?: fallbackCountry +} + +private fun FocusRequester.safeFreeFocus() { + try { + this.freeFocus() + } catch (exception: IllegalStateException) { + Log.e(TAG, "Unable to free focus", exception) + } +} + +@Composable +private fun PlaceholderNumberHint(countryIso: Iso31661alpha2) { + Text( + text = stringResource( + id = numberHint.getOrDefault(countryIso, R.string.unknown), + ), + ) +} + +@Composable +private fun ClearIconButton( + imageVector: ImageVector, + colors: TextFieldColors, + isNumberValid: Boolean, + onClick: () -> Unit, +) = IconButton(onClick = onClick) { + Icon( + imageVector = imageVector, + contentDescription = stringResource(id = R.string.clear), + tint = colors.trailingIconColor( + enabled = true, + isError = !isNumberValid, + interactionSource = remember { MutableInteractionSource() }, + ).value, + ) +} + +@Composable +private fun autoDetectedCountryCode(autoDetectCode: Boolean, initialPhoneNumber: String?): String? = + if (initialPhoneNumber?.startsWith("+") == true && autoDetectCode) { + extractCountryCode(initialPhoneNumber) + } else { + null + } + +@Composable +private fun TextFieldColors.trailingIconColor( + enabled: Boolean, + isError: Boolean, + interactionSource: InteractionSource, +): State { + val focused by interactionSource.collectIsFocusedAsState() + + return rememberUpdatedState( + when { + !enabled -> disabledTrailingIconColor + isError -> errorTrailingIconColor + focused -> focusedTrailingIconColor + else -> unfocusedTrailingIconColor + }, + ) +} + +@Preview +@Composable +private fun CountryCodePickerPreview() { + CountryCodePicker( + onValueChange = { _, _ -> }, + showCountryCode = true, + showCountryFlag = true, + showPlaceholder = true, + includeOnly = null, + ) +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/Autofill.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/Autofill.kt new file mode 100644 index 000000000..97b7c89ef --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/Autofill.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.component + +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.autofill.AutofillNode +import androidx.compose.ui.autofill.AutofillType +import androidx.compose.ui.composed +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.layout.boundsInWindow +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalAutofill +import androidx.compose.ui.platform.LocalAutofillTree + +@ExperimentalComposeUiApi +internal fun Modifier.autofill( + autofillTypes: List, + onFill: (String) -> Unit, + focusRequester: FocusRequester, +): Modifier = this then composed { + val autofill = LocalAutofill.current + val autofillNode = AutofillNode(onFill = onFill, autofillTypes = autofillTypes) + LocalAutofillTree.current += autofillNode + + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + + this + .onGloballyPositioned { + autofillNode.boundingBox = it.boundsInWindow() + } + .onFocusChanged { focusState -> + autofill?.run { + if (focusState.isFocused) { + requestAutofillForNode(autofillNode) + } else { + cancelAutofillForNode(autofillNode) + } + } + } +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryCodeDialog.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryCodeDialog.kt new file mode 100644 index 000000000..de99fc90c --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryCodeDialog.kt @@ -0,0 +1,162 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +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.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mifos.library.countrycodepicker.data.CountryData +import com.mifos.library.countrycodepicker.data.utils.emojiFlag +import com.mifos.library.countrycodepicker.data.utils.sortedByLocalizedName +import kotlinx.collections.immutable.ImmutableSet +import kotlinx.collections.immutable.toImmutableList + +internal val DEFAULT_PADDING = 10.dp + +@Composable +internal fun CountryCodeDialog( + selectedCountry: CountryData, + includeOnly: ImmutableSet?, + onCountryChange: (CountryData) -> Unit, + showCountryCode: Boolean, + showFlag: Boolean, + textStyle: TextStyle, + modifier: Modifier = Modifier, + backgroundColor: Color = MaterialTheme.colorScheme.surface, +) { + val context = LocalContext.current + + var country by remember { mutableStateOf(selectedCountry) } + var isOpenDialog by remember { mutableStateOf(false) } + val interactionSource = remember { MutableInteractionSource() } + val countryList by remember(context, includeOnly) { + derivedStateOf { + val allCountries = CountryData.entries.sortedByLocalizedName(context) + includeOnly?.run { + val includeUppercase = map { it.uppercase() } + allCountries.filter { it.countryIso in includeUppercase } + } ?: allCountries + } + } + + Column( + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + ) { + isOpenDialog = true + }, + ) { + CountryRow( + modifier = Modifier.padding(DEFAULT_PADDING), + showCountryCode = showCountryCode, + showFlag = showFlag, + country = country, + textStyle = textStyle, + ) + + if (isOpenDialog) { + CountryDialog( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(DEFAULT_ROUNDING)), + onDismissRequest = { isOpenDialog = false }, + onSelect = { countryItem -> + onCountryChange(countryItem) + country = countryItem + isOpenDialog = false + }, + countryList = countryList.toImmutableList(), + textStyle = if (textStyle.color != Color.Unspecified) { + textStyle + } else { + textStyle.copy(color = MaterialTheme.colorScheme.onSurface) + }, + backgroundColor = backgroundColor, + ) + } + } +} + +@Composable +private fun CountryRow( + showCountryCode: Boolean, + showFlag: Boolean, + country: CountryData, + textStyle: TextStyle, + modifier: Modifier = Modifier, +) = Row( + modifier = modifier, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, +) { + Text( + text = emojiCodeText( + showFlag = showFlag, + isPickCountry = country, + showCountryCode = showCountryCode, + ), + modifier = Modifier.padding(start = DEFAULT_PADDING), + style = textStyle.copy(color = textStyle.color.copy(alpha = 1f)), + ) + Icon( + imageVector = Icons.Default.ArrowDropDown, + contentDescription = null, + tint = textStyle.color, + ) +} + +@Composable +private fun emojiCodeText( + showFlag: Boolean, + isPickCountry: CountryData, + showCountryCode: Boolean, +) = (if (showFlag) isPickCountry.emojiFlag else "") + + (if (showCountryCode && showFlag) " " else "") + + (if (showCountryCode) isPickCountry.countryPhoneCode else "") + +@Preview +@Composable +private fun CountryCodeDialogPreview() { + CountryCodeDialog( + selectedCountry = CountryData.UnitedStates, + includeOnly = null, + onCountryChange = {}, + showCountryCode = true, + showFlag = true, + textStyle = TextStyle(), + backgroundColor = Color.White, + ) +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryDialog.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryDialog.kt new file mode 100644 index 000000000..2b2d2a328 --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/component/CountryDialog.kt @@ -0,0 +1,291 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import com.mifos.library.countrycodepicker.R +import com.mifos.library.countrycodepicker.data.CountryData +import com.mifos.library.countrycodepicker.data.utils.countryNames +import com.mifos.library.countrycodepicker.data.utils.emojiFlag +import com.mifos.library.countrycodepicker.data.utils.searchCountry +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList + +internal val DEFAULT_ROUNDING = 10.dp +private val DEFAULT_ROW_PADDING = 16.dp +private const val ROW_PADDING_VERTICAL_SCALING = 1.1f +private val SEARCH_ICON_PADDING = 5.dp +private const val HEADER_TEXT_SIZE_MULTIPLE = 1.5 +private val MIN_TAP_DIMENSION = 48.dp +private const val DIVIDER_ALPHA = 0.12f + +/** + * @param onDismissRequest Executes when the user tries to dismiss the dialog. + * @param onSelect Executes when the user selects a country from the list. + * @param textStyle A [TextStyle] for customizing text style of search input field and country rows. + * @param modifier The modifier to be applied to the dialog surface. + * @param countryList The list of countries to display in the dialog. + * @param rowPadding The padding to be applied to each row. + * @param backgroundColor The [Color] of the dialog background. + * @param dividerColor The [Color] of the country row dividers. + */ +@Composable +fun CountryDialog( + onDismissRequest: () -> Unit, + onSelect: (item: CountryData) -> Unit, + textStyle: TextStyle, + modifier: Modifier = Modifier, + countryList: ImmutableList = persistentListOf(), + rowPadding: Dp = DEFAULT_ROW_PADDING, + backgroundColor: Color = MaterialTheme.colorScheme.surface, + dividerColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = DIVIDER_ALPHA), +) { + val context = LocalContext.current + var searchValue by rememberSaveable { mutableStateOf("") } + val filteredCountries by remember(context, searchValue) { + derivedStateOf { + if (searchValue.isEmpty()) { + countryList + } else { + countryList.searchCountry( + searchValue, + context, + ) + } + } + } + + Dialog( + onDismissRequest = onDismissRequest, + content = { + @Suppress("ReusedModifierInstance") + Surface( + color = backgroundColor, + modifier = modifier, + ) { + Column(modifier = Modifier.fillMaxSize()) { + HeaderRow(textStyle, onDismissRequest) + + SearchTextField( + value = searchValue, + onValueChange = { searchValue = it }, + textStyle = textStyle, + leadingIcon = { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = stringResource(id = R.string.search), + tint = textStyle.color, + modifier = Modifier.padding(horizontal = SEARCH_ICON_PADDING), + ) + }, + ) + + Spacer(modifier = Modifier.height(DEFAULT_ROW_PADDING)) + + LazyColumn { + items( + filteredCountries, + key = { it.countryIso }, + ) { countryItem -> + HorizontalDivider(color = dividerColor) + CountryRowItem( + rowPadding = rowPadding, + onSelect = { onSelect(countryItem) }, + countryItem = countryItem, + textStyle = textStyle, + ) + } + } + } + } + }, + ) +} + +@Composable +private fun HeaderRow( + textStyle: TextStyle, + onDismissRequest: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + ) { + Spacer(modifier = Modifier.width(DEFAULT_ROW_PADDING)) + Text( + text = stringResource(id = R.string.select_country), + style = textStyle.copy( + fontSize = textStyle + .fontSize + .takeIf { it != TextUnit.Unspecified } + ?.let { it * HEADER_TEXT_SIZE_MULTIPLE } + ?: MaterialTheme.typography.labelSmall.fontSize, + ), + ) + Spacer(modifier = Modifier.weight(1f)) + IconButton( + onClick = { onDismissRequest() }, + ) { + Icon( + imageVector = Icons.Filled.Clear, + contentDescription = "Close", + tint = textStyle.color, + ) + } + } +} + +@Composable +private fun CountryRowItem( + rowPadding: Dp, + onSelect: () -> Unit, + countryItem: CountryData, + textStyle: TextStyle, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .clickable(onClick = { onSelect() }) + .padding( + horizontal = rowPadding, + vertical = rowPadding * ROW_PADDING_VERTICAL_SCALING, + ), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = countryItem.emojiFlag + " " + + stringResource( + id = countryNames.getOrDefault( + countryItem.countryIso, + R.string.unknown, + ), + ), + style = textStyle, + overflow = TextOverflow.Ellipsis, + ) + } +} + +@Composable +private fun SearchTextField( + value: String, + onValueChange: (String) -> Unit, + textStyle: TextStyle, + modifier: Modifier = Modifier, + leadingIcon: (@Composable () -> Unit)? = null, + hint: String = stringResource(id = R.string.search), +) { + val requester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + requester.requestFocus() + } + + BasicTextField( + modifier = modifier + .fillMaxWidth() + .height(MIN_TAP_DIMENSION) + .padding(horizontal = DEFAULT_ROW_PADDING) + .focusRequester(requester), + value = value, + onValueChange = onValueChange, + singleLine = true, + cursorBrush = SolidColor(textStyle.color), + textStyle = textStyle, + decorationBox = { innerTextField -> + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + leadingIcon?.invoke() + Box( + modifier = Modifier + .padding(start = DEFAULT_ROUNDING) + .weight(1f), + contentAlignment = Alignment.CenterStart, + ) { + if (value.isEmpty()) { + Text( + text = hint, + maxLines = 1, + style = textStyle.copy(color = textStyle.color.copy(alpha = 0.5f)), + ) + } + innerTextField() + } + } + }, + ) +} + +@Preview +@Composable +private fun CountryDialogPreview() { + CountryDialog( + onDismissRequest = {}, + onSelect = {}, + countryList = CountryData.entries.toImmutableList(), + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(DEFAULT_ROUNDING)), + textStyle = TextStyle(), + ) +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/CountryData.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/CountryData.kt new file mode 100644 index 000000000..f7264d5d7 --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/CountryData.kt @@ -0,0 +1,263 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data + +typealias Iso31661alpha2 = String +typealias PhoneCode = String + +enum class CountryData(val countryIso: Iso31661alpha2, val countryPhoneCode: PhoneCode) { + Andorra("AD", "+376"), + UnitedArabEmirates("AE", "+971"), + Afghanistan("AF", "+93"), + AntiguaAndBarbuda("AG", "+1"), + Anguilla("AI", "+1"), + Albania("AL", "+355"), + Armenia("AM", "+374"), + Angola("AO", "+244"), + Antarctica("AQ", "+672"), + Argentina("AR", "+54"), + AmericanSamoa("AS", "+1"), + Austria("AT", "+43"), + Australia("AU", "+61"), + Aruba("AW", "+297"), + AlandIslands("AX", "+358"), + Azerbaijan("AZ", "+994"), + BosniaAndHerzegovina("BA", "+387"), + Barbados("BB", "+1"), + Bangladesh("BD", "+880"), + Belgium("BE", "+32"), + BurkinaFaso("BF", "+226"), + Bulgaria("BG", "+359"), + Bahrain("BH", "+973"), + Burundi("BI", "+257"), + Benin("BJ", "+229"), + SaintBarthelemy("BL", "+590"), + Bermuda("BM", "+1"), + BruneiDarussalam("BN", "+673"), + Bolivia("BO", "+591"), + Brazil("BR", "+55"), + Bahamas("BS", "+1"), + Bhutan("BT", "+975"), + Botswana("BW", "+267"), + Belarus("BY", "+375"), + Belize("BZ", "+501"), + Canada("CA", "+1"), + CocosKeelingIslands("CC", "+61"), + CongoKinshasaDRC("CD", "+243"), + CentralAfricanRepublic("CF", "+236"), + CongoBrazzavilleRepublic("CG", "+242"), + Switzerland("CH", "+41"), + CoteDivoire("CI", "+225"), + CookIslands("CK", "+682"), + Chile("CL", "+56"), + Cameroon("CM", "+237"), + China("CN", "+86"), + Colombia("CO", "+57"), + CostaRica("CR", "+506"), + Cuba("CU", "+53"), + CapeVerde("CV", "+238"), + Curacao("CW", "+599"), + Christmas("CX", "+61"), + CyprusIsland("CY", "+357"), + CzechRepublic("CZ", "+420"), + Germany("DE", "+49"), + Djibouti("DJ", "+253"), + Denmark("DK", "+45"), + Dominica("DM", "+1"), + DominicanRepublic("DO", "+1"), + Algeria("DZ", "+213"), + Ecuador("EC", "+593"), + Estonia("EE", "+372"), + Egypt("EG", "+20"), + Eritrea("ER", "+291"), + Spain("ES", "+34"), + Ethiopia("ET", "+251"), + Finland("FI", "+358"), + Fiji("FJ", "+679"), + FalklandIslands("FK", "+500"), + Micronesia("FM", "+691"), + FaroeIslands("FO", "+298"), + France("FR", "+33"), + Gabon("GA", "+241"), + UnitedKingdom("GB", "+44"), + Grenada("GD", "+1"), + Georgia("GE", "+995"), + FrenchGuyana("GF", "+594"), + Ghana("GH", "+233"), + Gibraltar("GI", "+350"), + Greenland("GL", "+299"), + Gambia("GM", "+220"), + Guinea("GN", "+224"), + Guadeloupe("GP", "+590"), + EquatorialGuinea("GQ", "+240"), + Greece("GR", "+30"), + Guatemala("GT", "+502"), + Guam("GU", "+1"), + GuineaBissau("GW", "+245"), + Guyana("GY", "+592"), + HongKong("HK", "+852"), + Honduras("HN", "+504"), + Croatia("HR", "+385"), + Haiti("HT", "+509"), + Hungary("HU", "+36"), + Indonesia("ID", "+62"), + Ireland("IE", "+353"), + Israel("IL", "+972"), + IsleOfMan("IM", "+44"), + India("IN", "+91"), + BritishIndianOceanTerritory("IO", "+246"), + Iraq("IQ", "+964"), + Iran("IR", "+98"), + Iceland("IS", "+354"), + Italy("IT", "+39"), + Jersey("JE", "+44"), + Jamaica("JM", "+1"), + Jordan("JO", "+962"), + Japan("JP", "+81"), + Kenya("KE", "+254"), + Kyrgyzstan("KG", "+996"), + Cambodia("KH", "+855"), + Kiribati("KI", "+686"), + Comoros("KM", "+269"), + SaintKittsAndNevis("KN", "+1"), + NorthKorea("KP", "+850"), + SouthKorea("KR", "+82"), + Kuwait("KW", "+965"), + CaymanIslands("KY", "+1"), + Kazakhstan("KZ", "+7"), + Lao("LA", "+856"), + Lebanon("LB", "+961"), + SaintLucia("LC", "+1"), + Liechtenstein("LI", "+423"), + SriLanka("LK", "+94"), + Liberia("LR", "+231"), + Lesotho("LS", "+266"), + Lithuania("LT", "+370"), + Luxembourg("LU", "+352"), + Latvia("LV", "+371"), + Libya("LY", "+218"), + Morocco("MA", "+212"), + Monaco("MC", "+377"), + Moldova("MD", "+373"), + Montenegro("ME", "+382"), + SaintMartin("MF", "+590"), + Madagascar("MG", "+261"), + MarshallIslands("MH", "+692"), + NorthMacedonia("MK", "+389"), + Mali("ML", "+223"), + Myanmar("MM", "+95"), + Mongolia("MN", "+976"), + Macau("MO", "+853"), + NorthernMarianaIslands("MP", "+1"), + Martinique("MQ", "+596"), + Mauritania("MR", "+222"), + Montserrat("MS", "+1"), + Malta("MT", "+356"), + Mauritius("MU", "+230"), + Maldives("MV", "+960"), + Malawi("MW", "+265"), + Mexico("MX", "+52"), + Malaysia("MY", "+60"), + Mozambique("MZ", "+258"), + Namibia("NA", "+264"), + NewCaledonia("NC", "+687"), + Niger("NE", "+227"), + NorfolkIslands("NF", "+672"), + Nigeria("NG", "+234"), + Nicaragua("NI", "+505"), + Netherlands("NL", "+31"), + Norway("NO", "+47"), + Nepal("NP", "+977"), + Nauru("NR", "+674"), + Niue("NU", "+683"), + NewZealand("NZ", "+64"), + Oman("OM", "+968"), + Panama("PA", "+507"), + Peru("PE", "+51"), + FrenchPolynesia("PF", "+689"), + PapuaNewGuinea("PG", "+675"), + Philippines("PH", "+63"), + Pakistan("PK", "+92"), + Poland("PL", "+48"), + SaintPierreAndMiquelon("PM", "+508"), + PitcairnIslands("PN", "+870"), + PuertoRico("PR", "+1"), + Palestine("PS", "+970"), + Portugal("PT", "+351"), + Palau("PW", "+680"), + Paraguay("PY", "+595"), + Qatar("QA", "+974"), + Reunion("RE", "+262"), + Romania("RO", "+40"), + Serbia("RS", "+381"), + RussianFederation("RU", "+7"), + Rwanda("RW", "+250"), + SaudiArabia("SA", "+966"), + SolomonIslands("SB", "+677"), + Seychelles("SC", "+248"), + Sudan("SD", "+249"), + Sweden("SE", "+46"), + Singapore("SG", "+65"), + SaintHelena("SH", "+290"), + Slovenia("SI", "+386"), + Slovakia("SK", "+421"), + SierraLeone("SL", "+232"), + SanMarino("SM", "+378"), + Senegal("SN", "+221"), + Somalia("SO", "+252"), + Suriname("SR", "+597"), + SouthSudan("SS", "+211"), + SaoTomeAndPrincipe("ST", "+239"), + ElSalvador("SV", "+503"), + SintMaarten("SX", "+1"), + Syria("SY", "+963"), + Swaziland("SZ", "+268"), + TurksAndCaicosIslands("TC", "+1"), + Chad("TD", "+235"), + Togo("TG", "+228"), + Thailand("TH", "+66"), + Tajikistan("TJ", "+992"), + Tokelau("TK", "+690"), + TimorLeste("TL", "+670"), + Turkmenistan("TM", "+993"), + Tunisia("TN", "+216"), + Tonga("TO", "+676"), + Turkey("TR", "+90"), + TrinidadAndTobago("TT", "+1"), + Tuvalu("TV", "+688"), + Taiwan("TW", "+886"), + Tanzania("TZ", "+255"), + Ukraine("UA", "+380"), + Uganda("UG", "+256"), + UnitedStates("US", "+1"), + Uruguay("UY", "+598"), + Uzbekistan("UZ", "+998"), + HolySee("VA", "+379"), + SaintVincentAndTheGrenadines("VC", "+1"), + Venezuela("VE", "+58"), + BritishVirginIslands("VG", "+1"), + USVirginIslands("VI", "+1"), + Vietnam("VN", "+84"), + Vanuatu("VU", "+678"), + WallisAndFutuna("WF", "+681"), + Samoa("WS", "+685"), + Kosovo("XK", "+383"), + Yemen("YE", "+967"), + Mayotte("YT", "+262"), + SouthAfrica("ZA", "+27"), + Zambia("ZM", "+260"), + Zimbabwe("ZW", "+263"), + ; + + companion object { + val isoMap: Map = entries.associateBy { it.countryIso } + internal val phoneCodeMap: Map = entries.associateBy { it.countryPhoneCode } + } +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryCodeUtils.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryCodeUtils.kt new file mode 100644 index 000000000..77c1ac361 --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryCodeUtils.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data.utils + +import android.content.Context +import android.telephony.TelephonyManager +import com.mifos.library.countrycodepicker.data.CountryData +import com.mifos.library.countrycodepicker.data.Iso31661alpha2 +import com.mifos.library.countrycodepicker.data.PhoneCode +import kotlin.math.min + +private const val EMOJI_UNICODE = 0x1F1A5 +private const val MAX_LENGTH_COUNTRY_CODE = 3 + +internal fun getCountryFromPhoneCode(code: PhoneCode, context: Context): CountryData? { + val countries = CountryData.entries.filter { it.countryPhoneCode == code } + return when (countries.size) { + 0 -> null + 1 -> countries.firstOrNull() + else -> { + val userIso = getUserIsoCode(context) + countries.firstOrNull { it.countryIso == userIso } + ?: if (code == "+1") CountryData.UnitedStates else countries.firstOrNull() + } + } +} + +@Suppress("SwallowedException", "TooGenericExceptionCaught", "Deprecation") +internal fun getUserIsoCode(context: Context): Iso31661alpha2 = try { + val telephonyManager = context.telephonyManager + telephonyManager?.networkCountryIso ?: telephonyManager?.simCountryIso +} catch (ex: Exception) { + null +}.takeIf { !it.isNullOrBlank() } ?: context.resources.configuration.locale.country + +val CountryData.emojiFlag: String get() = countryCodeToEmojiFlag(countryIso) + +fun countryCodeToEmojiFlag(countryCode: Iso31661alpha2): String = + countryCode + .uppercase() + .map { char -> Character.codePointAt("$char", 0) + EMOJI_UNICODE } + .joinToString("") { String(Character.toChars(it)) } + +private val Context.telephonyManager: TelephonyManager? + get() = getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager + +internal fun extractCountryCode(fullNumber: String): String? { + val numberLength = fullNumber.length + val minLength = min(a = numberLength, b = MAX_LENGTH_COUNTRY_CODE) + for (i in 1..minLength) { + val potentialCountryCode = fullNumber.substring(0, i) + if (CountryData.phoneCodeMap.containsKey(potentialCountryCode)) { + return potentialCountryCode + } + } + return null +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryNameMap.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryNameMap.kt new file mode 100644 index 000000000..89caad9ce --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/CountryNameMap.kt @@ -0,0 +1,258 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data.utils + +import com.mifos.library.countrycodepicker.R +import com.mifos.library.countrycodepicker.data.Iso31661alpha2 + +internal val countryNames: Map = mapOf( + "AD" to R.string.andorra, + "AE" to R.string.united_arab_emirates, + "AF" to R.string.afghanistan, + "AG" to R.string.antigua_and_barbuda, + "AI" to R.string.anguilla, + "AL" to R.string.albania, + "AM" to R.string.armenia, + "AO" to R.string.angola, + "AQ" to R.string.antarctica, + "AR" to R.string.argentina, + "AS" to R.string.american_samoa, + "AT" to R.string.austria, + "AU" to R.string.australia, + "AW" to R.string.aruba, + "AX" to R.string.aland_islands, + "AZ" to R.string.azerbaijan, + "BA" to R.string.bosnia, + "BB" to R.string.barbados, + "BD" to R.string.bangladesh, + "BE" to R.string.belgium, + "BF" to R.string.burkina_faso, + "BG" to R.string.bulgaria, + "BH" to R.string.bahrain, + "BI" to R.string.burundi, + "BJ" to R.string.benin, + "BL" to R.string.saint_barhelemy, + "BM" to R.string.bermuda, + "BN" to R.string.brunei_darussalam, + "BO" to R.string.bolivia, + "BR" to R.string.brazil, + "BS" to R.string.bahamas, + "BT" to R.string.bhutan, + "BW" to R.string.botswana, + "BY" to R.string.belarus, + "BZ" to R.string.belize, + "CA" to R.string.canada, + "CC" to R.string.cocos, + "CD" to R.string.congo_democratic, + "CF" to R.string.central_african, + "CG" to R.string.congo, + "CH" to R.string.switzerland, + "CI" to R.string.cote_dlvoire, + "CK" to R.string.cook_islands, + "CL" to R.string.chile, + "CM" to R.string.cameroon, + "CN" to R.string.china, + "CO" to R.string.colombia, + "CR" to R.string.costa_rica, + "CU" to R.string.cuba, + "CV" to R.string.cape_verde, + "CW" to R.string.curacao, + "CX" to R.string.christmas_island, + "CY" to R.string.cyprus, + "CZ" to R.string.czech_republic, + "DE" to R.string.germany, + "DJ" to R.string.djibouti, + "DK" to R.string.denmark, + "DM" to R.string.dominica, + "DO" to R.string.dominican_republic, + "DZ" to R.string.algeria, + "EC" to R.string.ecuador, + "EE" to R.string.estonia, + "EG" to R.string.egypt, + "ER" to R.string.eritrea, + "ES" to R.string.spain, + "ET" to R.string.ethiopia, + "FI" to R.string.finland, + "FJ" to R.string.fiji, + "FK" to R.string.falkland_islands, + "FM" to R.string.micronesia, + "FO" to R.string.faroe_islands, + "FR" to R.string.france, + "GA" to R.string.gabon, + "GB" to R.string.united_kingdom, + "GD" to R.string.grenada, + "GE" to R.string.georgia, + "GF" to R.string.french_guiana, + "GG" to R.string.guernsey, + "GH" to R.string.ghana, + "GI" to R.string.gibraltar, + "GL" to R.string.greenland, + "GM" to R.string.gambia, + "GN" to R.string.guinea, + "GP" to R.string.guadeloupe, + "GQ" to R.string.equatorial_guinea, + "GR" to R.string.greece, + "GT" to R.string.guatemala, + "GU" to R.string.guam, + "GW" to R.string.guinea_bissau, + "GY" to R.string.guyana, + "HK" to R.string.hong_kong, + "HN" to R.string.honduras, + "HR" to R.string.croatia, + "HT" to R.string.haiti, + "HU" to R.string.hungary, + "ID" to R.string.indonesia, + "IE" to R.string.ireland, + "IL" to R.string.israil, + "IM" to R.string.isle_of_man, + "IN" to R.string.india, + "IO" to R.string.british_indian_ocean, + "IQ" to R.string.iraq, + "IR" to R.string.iran, + "IS" to R.string.iceland, + "IT" to R.string.italia, + "JE" to R.string.jersey, + "JM" to R.string.jamaica, + "JO" to R.string.jordan, + "JP" to R.string.japan, + "KE" to R.string.kenya, + "KG" to R.string.kyrgyzstan, + "KH" to R.string.cambodia, + "KI" to R.string.kiribati, + "KM" to R.string.comoros, + "KN" to R.string.saint_kitts, + "KP" to R.string.north_korea, + "KR" to R.string.south_korea, + "KW" to R.string.kuwait, + "KY" to R.string.cayman_islands, + "KZ" to R.string.kazakhstan, + "LA" to R.string.laos, + "LB" to R.string.lebanon, + "LC" to R.string.saint_lucia, + "LI" to R.string.liechtenstein, + "LK" to R.string.siri_lanka, + "LR" to R.string.liberia, + "LS" to R.string.lesotho, + "LT" to R.string.lithuania, + "LU" to R.string.luxembourg, + "LV" to R.string.latvia, + "LY" to R.string.libya, + "MA" to R.string.morocco, + "MC" to R.string.monaco, + "MD" to R.string.moldova, + "ME" to R.string.montenegro, + "MF" to R.string.saint_martin, + "MG" to R.string.madagascar, + "MH" to R.string.marshall_islands, + "MK" to R.string.north_macedonia, + "ML" to R.string.mali, + "MM" to R.string.myanmar, + "MN" to R.string.mongolia, + "MO" to R.string.macau, + "MP" to R.string.northern_mariana, + "MQ" to R.string.martinique, + "MR" to R.string.mauritania, + "MS" to R.string.montserrat, + "MT" to R.string.malta, + "MU" to R.string.mauritius, + "MV" to R.string.maldives, + "MW" to R.string.malawi, + "MX" to R.string.mexico, + "MY" to R.string.malaysia, + "MZ" to R.string.mozambique, + "NA" to R.string.namibia, + "NC" to R.string.new_caledonia, + "NE" to R.string.niger, + "NF" to R.string.norfolk, + "NG" to R.string.nigeria, + "NI" to R.string.nicaragua, + "NL" to R.string.netherlands, + "NO" to R.string.norway, + "NP" to R.string.nepal, + "NR" to R.string.nauru, + "NU" to R.string.niue, + "NZ" to R.string.new_zealand, + "OM" to R.string.oman, + "PA" to R.string.panama, + "PE" to R.string.peru, + "PF" to R.string.french_polynesia, + "PG" to R.string.papua_new_guinea, + "PH" to R.string.philippines, + "PK" to R.string.pakistan, + "PL" to R.string.poland, + "PM" to R.string.saint_pierre, + "PN" to R.string.pitcairn, + "PR" to R.string.puerto_rico, + "PS" to R.string.state_of_palestine, + "PT" to R.string.portugal, + "PW" to R.string.palau, + "PY" to R.string.paraguay, + "QA" to R.string.qatar, + "RE" to R.string.reunion, + "RO" to R.string.romania, + "RS" to R.string.serbia, + "RU" to R.string.russia, + "RW" to R.string.rwanda, + "SA" to R.string.saudi_arabia, + "SB" to R.string.solomon_islands, + "SC" to R.string.seychelles, + "SD" to R.string.sudan, + "SE" to R.string.sweden, + "SG" to R.string.singapore, + "SH" to R.string.saint_helena, + "SI" to R.string.slovenia, + "SK" to R.string.slovakia, + "SL" to R.string.sierra_leone, + "SM" to R.string.san_marino, + "SN" to R.string.senegal, + "SO" to R.string.somalia, + "SR" to R.string.suriname, + "SS" to R.string.south_sudan, + "ST" to R.string.sao_tome, + "SV" to R.string.el_salvador, + "SX" to R.string.sint_maarten, + "SY" to R.string.syria, + "SZ" to R.string.swaziland, + "TC" to R.string.turks_and_caicos, + "TD" to R.string.chad, + "TG" to R.string.togo, + "TH" to R.string.thailand, + "TJ" to R.string.taijikistan, + "TK" to R.string.tokelau, + "TL" to R.string.timor_leste, + "TM" to R.string.turkmenistan, + "TN" to R.string.tunisia, + "TO" to R.string.tonga, + "TR" to R.string.turkey, + "TT" to R.string.trinidad_and_tobago, + "TV" to R.string.tuvalu, + "TW" to R.string.taiwan, + "TZ" to R.string.tazmania, + "UA" to R.string.ukraine, + "UG" to R.string.uganda, + "US" to R.string.united_states_america, + "UY" to R.string.uruguay, + "UZ" to R.string.uzbekistan, + "VA" to R.string.holy_see, + "VC" to R.string.saint_vincent, + "VE" to R.string.venezuela, + "VG" to R.string.virgin_islands, + "VI" to R.string.virgin_islands_us, + "VN" to R.string.vietnam, + "VU" to R.string.vanuatu, + "WF" to R.string.wallis_and_futuna, + "WS" to R.string.samoa, + "XK" to R.string.kosovo, + "YE" to R.string.yemen, + "YT" to R.string.mayotte, + "ZA" to R.string.south_africa, + "ZM" to R.string.zambia, + "ZW" to R.string.zimbabwe, +) diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/NumberHintMap.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/NumberHintMap.kt new file mode 100644 index 000000000..1bcfa425a --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/NumberHintMap.kt @@ -0,0 +1,259 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data.utils + +import com.mifos.library.countrycodepicker.R +import com.mifos.library.countrycodepicker.data.Iso31661alpha2 + +@Suppress("LongMethod", "CyclomaticComplexMethod") +internal val numberHint: Map = mapOf( + "AD" to R.string.andorra_hint, + "AE" to R.string.united_arab_emirates_hint, + "AF" to R.string.afganistan_hint, + "AG" to R.string.antigua_and_barbuda_hint, + "AI" to R.string.anguilla_hint, + "AL" to R.string.albania_hint, + "AM" to R.string.armenia_hint, + "AO" to R.string.angola_hint, + "AQ" to R.string.antarctica_hint, + "AR" to R.string.argentina_hint, + "AS" to R.string.american_samoa_hint, + "AT" to R.string.austria_hint, + "AU" to R.string.australia_hint, + "AW" to R.string.aruba_hint, + "AX" to R.string.aland_islands_hint, + "AZ" to R.string.azerbaijan_hint, + "BA" to R.string.bosnia_hint, + "BB" to R.string.barbados_hint, + "BD" to R.string.bangladesh_hint, + "BE" to R.string.belgium_hint, + "BF" to R.string.burkina_faso_hint, + "BG" to R.string.bulgaria_hint, + "BH" to R.string.bahrain_hint, + "BI" to R.string.burundi_hint, + "BJ" to R.string.benin_hint, + "BL" to R.string.saint_barhelemy_hint, + "BM" to R.string.bermuda_hint, + "BN" to R.string.brunei_darussalam_hint, + "BO" to R.string.bolivia_hint, + "BR" to R.string.brazil_hint, + "BS" to R.string.bahamas_hint, + "BT" to R.string.bhutan_hint, + "BW" to R.string.botswana_hint, + "BY" to R.string.belarus_hint, + "BZ" to R.string.belize_hint, + "CA" to R.string.canada_hint, + "CC" to R.string.cocos_hint, + "CD" to R.string.congo_democratic_hint, + "CF" to R.string.central_african_hint, + "CG" to R.string.congo_hint, + "CH" to R.string.switzerland_hint, + "CI" to R.string.cote_dlvoire_hint, + "CK" to R.string.cook_islands_hint, + "CL" to R.string.chile_hint, + "CM" to R.string.cameroon_hint, + "CN" to R.string.china_hint, + "CO" to R.string.colombia_hint, + "CR" to R.string.costa_rica_hint, + "CU" to R.string.cuba_hint, + "CV" to R.string.cape_verde_hint, + "CW" to R.string.curacao_hint, + "CX" to R.string.christmas_island_hint, + "CY" to R.string.cyprus_hint, + "CZ" to R.string.czech_republic_hint, + "DE" to R.string.germany_hint, + "DJ" to R.string.djibouti_hint, + "DK" to R.string.denmark_hint, + "DM" to R.string.dominica_hint, + "DO" to R.string.dominician_republic_hint, + "DZ" to R.string.algeria_hint, + "EC" to R.string.ecuador_hint, + "EE" to R.string.estonia_hint, + "EG" to R.string.egypt_hint, + "ER" to R.string.eritrea_hint, + "ES" to R.string.spain_hint, + "ET" to R.string.ethiopia_hint, + "FI" to R.string.finland_hint, + "FJ" to R.string.fiji_hint, + "FK" to R.string.falkland_islands_hint, + "FM" to R.string.micro_hint, + "FO" to R.string.faroe_islands_hint, + "FR" to R.string.france_hint, + "GA" to R.string.gabon_hint, + "GB" to R.string.united_kingdom_hint, + "GD" to R.string.grenada_hint, + "GE" to R.string.georgia_hint, + "GF" to R.string.french_guyana_hint, + "GG" to R.string.guernsey_hint, + "GH" to R.string.ghana_hint, + "GI" to R.string.gibraltar_hint, + "GL" to R.string.greenland_hint, + "GM" to R.string.gambia_hint, + "GN" to R.string.guinea_hint, + "GP" to R.string.guadeloupe_hint, + "GQ" to R.string.equatorial_guinea_hint, + "GR" to R.string.greece_hint, + "GT" to R.string.guatemala_hint, + "GU" to R.string.guam_hint, + "GW" to R.string.guinea_bissau_hint, + "GY" to R.string.guyana_hint, + "HK" to R.string.hong_kong_hint, + "HN" to R.string.honduras_hint, + "HR" to R.string.croatia_hint, + "HT" to R.string.haiti_hint, + "HU" to R.string.hungary_hint, + "ID" to R.string.indonesia_hint, + "IE" to R.string.ireland_hint, + "IL" to R.string.israil_hint, + "IM" to R.string.isle_of_man_hint, + "IS" to R.string.iceland_hint, + "IN" to R.string.india_hint, + "IO" to R.string.british_indian_ocean_hint, + "IQ" to R.string.iraq_hint, + "IR" to R.string.iran_hint, + "IT" to R.string.italia_hint, + "JE" to R.string.jersey_hint, + "JM" to R.string.jamaica_hint, + "JO" to R.string.jordan_hint, + "JP" to R.string.japan_hint, + "KE" to R.string.kenya_hint, + "KG" to R.string.kyrgyzstan_hint, + "KH" to R.string.cambodia_hint, + "KI" to R.string.kiribati_hint, + "KM" to R.string.comoros_hint, + "KN" to R.string.saint_kitts_hint, + "KP" to R.string.north_korea_hint, + "KR" to R.string.south_korea_hint, + "KW" to R.string.kuwait_hint, + "KY" to R.string.cayman_islands_hint, + "KZ" to R.string.kazakhstan_hint, + "LA" to R.string.laos_hint, + "LB" to R.string.lebanon_hint, + "LC" to R.string.saint_lucia_hint, + "LI" to R.string.liechtenstein_hint, + "LK" to R.string.siri_lanka_hint, + "LR" to R.string.liberia_hint, + "LS" to R.string.lesotho_hint, + "LT" to R.string.lithuania_hint, + "LU" to R.string.luxembourg_hint, + "LV" to R.string.latvia_hint, + "LY" to R.string.libya_hint, + "MA" to R.string.marocco_hint, + "MC" to R.string.monaco_hint, + "MD" to R.string.moldova_hint, + "ME" to R.string.montenegro_hint, + "MF" to R.string.saint_martin_hint, + "MG" to R.string.madagascar_hint, + "MH" to R.string.marshall_islands_hint, + "MK" to R.string.north_macedonia_hint, + "ML" to R.string.mali_hint, + "MM" to R.string.myanmar_hint, + "MN" to R.string.mongolia_hint, + "MO" to R.string.macau_hint, + "MP" to R.string.northern_mariana_hint, + "MQ" to R.string.martinique_hint, + "MR" to R.string.mauriatana_hint, + "MS" to R.string.montserrat_hint, + "MT" to R.string.malta_hint, + "MU" to R.string.mauritius_hint, + "MV" to R.string.maldives_hint, + "MW" to R.string.malawi_hint, + "MX" to R.string.mexico_hint, + "MY" to R.string.malaysia_hint, + "MZ" to R.string.mozambique_hint, + "NA" to R.string.namibia_hint, + "NC" to R.string.new_caledonia_hint, + "NE" to R.string.niger_hint, + "NF" to R.string.norfolk_hint, + "NG" to R.string.nigeria_hint, + "NI" to R.string.nicaragua_hint, + "NL" to R.string.netherlands_hint, + "NO" to R.string.norway_hint, + "NP" to R.string.nepal_hint, + "NR" to R.string.nauru_hint, + "NU" to R.string.niue_hint, + "NZ" to R.string.new_zealand_hint, + "OM" to R.string.oman_hint, + "PA" to R.string.panama_hint, + "PE" to R.string.peru_hint, + "PF" to R.string.french_polynesia_hint, + "PG" to R.string.papua_new_guinea_hint, + "PH" to R.string.philippinies_hint, + "PK" to R.string.pakistan_hint, + "PL" to R.string.poland_hint, + "PM" to R.string.saint_pierre_hint, + "PN" to R.string.pitcairn_hint, + "PR" to R.string.puerto_rico_hint, + "PS" to R.string.state_of_palestine_hint, + "PT" to R.string.portugal_hint, + "PW" to R.string.palau_hint, + "PY" to R.string.paraguay_hint, + "QA" to R.string.qatar_hint, + "RE" to R.string.reunion_hint, + "RO" to R.string.romania_hint, + "RS" to R.string.serbia_hint, + "RU" to R.string.russia_hint, + "RW" to R.string.rwanda_hint, + "SA" to R.string.saudi_arabia_hint, + "SB" to R.string.solomon_islands_hint, + "SC" to R.string.seychelles_hint, + "SD" to R.string.sudan_hint, + "SE" to R.string.sweden_hint, + "SG" to R.string.singapore_hint, + "SH" to R.string.saint_helena_hint, + "SI" to R.string.slovenia_hint, + "SK" to R.string.slovakia_hint, + "SL" to R.string.sierra_leone_hint, + "SM" to R.string.san_marino_hint, + "SN" to R.string.senegal_hint, + "SO" to R.string.somali_hint, + "SR" to R.string.suriname_hint, + "SS" to R.string.south_sudan_hint, + "ST" to R.string.sao_tome_hint, + "SV" to R.string.el_salvador_hint, + "SX" to R.string.sint_maarten_hint, + "SY" to R.string.syrian_hint, + "SZ" to R.string.swaziland_hint, + "TC" to R.string.turks_and_caicos_hint, + "TD" to R.string.chad_hint, + "TG" to R.string.togo_hint, + "TH" to R.string.thailand_hint, + "TJ" to R.string.taijikistan_hint, + "TK" to R.string.tokelau_hint, + "TL" to R.string.timor_leste_hint, + "TM" to R.string.turkmenistan_hint, + "TN" to R.string.tunisia_hint, + "TO" to R.string.tonga_hint, + "TR" to R.string.turkey_hint, + "TT" to R.string.trinidad_and_tobago_hint, + "TV" to R.string.tuvalu_hint, + "TW" to R.string.taiwan_hint, + "TZ" to R.string.tazmania_hint, + "UA" to R.string.ukraina_hint, + "UG" to R.string.uganda_hint, + "US" to R.string.united_states_america_hint, + "UY" to R.string.uruguay_hint, + "UZ" to R.string.uzbekistan_hint, + "VA" to R.string.holy_see_hint, + "VC" to R.string.saint_vincent_hint, + "VE" to R.string.venezuela_hint, + "VG" to R.string.virgin_islands_hint, + "VI" to R.string.virgin_islands_us_hint, + "VN" to R.string.vietnam_hint, + "VU" to R.string.vanuatu_hint, + "WF" to R.string.walli_and_fatuna_hint, + "WS" to R.string.samoa_hint, + "XK" to R.string.kosovo_hint, + "YE" to R.string.yemen_hint, + "YT" to R.string.mayotte_hint, + "ZA" to R.string.south_africa_hint, + "ZM" to R.string.zambia_hint, + "ZW" to R.string.zimbabwe_hint, +) diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/SearchCountryList.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/SearchCountryList.kt new file mode 100644 index 000000000..347e2d1bc --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/SearchCountryList.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data.utils + +import android.content.Context +import com.mifos.library.countrycodepicker.R +import com.mifos.library.countrycodepicker.data.CountryData + +internal fun List.searchCountry(key: String, context: Context): List = + this.mapNotNull { countryData -> + countryNames[countryData.countryIso]?.let { countryName -> + val localizedCountryName = context.resources.getString(countryName).lowercase() + if (localizedCountryName.contains(key.lowercase())) { + countryData to localizedCountryName + } else { + null + } + } + } + .partition { it.second.startsWith(key.lowercase()) } + .let { (startWith, contains) -> + startWith.map { it.first } + contains.map { it.first } + } + +internal fun List.sortedByLocalizedName(context: Context): List = + this.sortedBy { + context.resources.getString( + countryNames.getOrDefault(it.countryIso, R.string.unknown), + ) + } diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/ValidatePhoneNumber.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/ValidatePhoneNumber.kt new file mode 100644 index 000000000..8070000c5 --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/data/utils/ValidatePhoneNumber.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.data.utils + +import android.content.Context +import io.michaelrocks.libphonenumber.android.NumberParseException +import io.michaelrocks.libphonenumber.android.PhoneNumberUtil + +private const val MIN_PHONE_LENGTH = 6 + +internal class ValidatePhoneNumber(private val context: Context) { + private val phoneUtil: PhoneNumberUtil by lazy { PhoneNumberUtil.createInstance(context) } + + operator fun invoke(fullPhoneNumber: String): Boolean = + if (fullPhoneNumber.length > MIN_PHONE_LENGTH) { + try { + phoneUtil.isValidNumber(phoneUtil.parse(fullPhoneNumber, null)) + } catch (ex: NumberParseException) { + false + } + } else { + false + } +} diff --git a/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/transformation/PhoneNumberTransformation.kt b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/transformation/PhoneNumberTransformation.kt new file mode 100644 index 000000000..9af61b140 --- /dev/null +++ b/libs/country-code-picker/src/main/kotlin/com/mifos/library/countrycodepicker/transformation/PhoneNumberTransformation.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.countrycodepicker.transformation + +import android.content.Context +import android.telephony.PhoneNumberUtils +import android.text.Selection +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.input.OffsetMapping +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.TransformedText +import androidx.compose.ui.text.input.VisualTransformation +import io.michaelrocks.libphonenumber.android.PhoneNumberUtil + +// https://medium.com/google-developer-experts/hands-on-jetpack-compose-visualtransformation-to-create-a-phone-number-formatter-99b0347fc4f6 + +class PhoneNumberTransformation(countryCode: String, context: Context) : VisualTransformation { + private val phoneNumberFormatter by lazy { + PhoneNumberUtil.createInstance(context).getAsYouTypeFormatter(countryCode) + } + + fun preFilter(text: String): String = text.filter { PhoneNumberUtils.isReallyDialable(it) } + + fun preFilter(textValue: TextFieldValue): String = preFilter(textValue.text) + + override fun filter(text: AnnotatedString): TransformedText { + val transformation = reformat(text, Selection.getSelectionEnd(text)) + + return TransformedText( + AnnotatedString(transformation.formatted.orEmpty()), + object : OffsetMapping { + @Suppress("TooGenericExceptionCaught", "SwallowedException") + override fun originalToTransformed(offset: Int): Int { + return try { + transformation.originalToTransformed[offset] + } catch (ex: IndexOutOfBoundsException) { + transformation.transformedToOriginal.lastIndex + } + } + + override fun transformedToOriginal(offset: Int): Int = + transformation.transformedToOriginal[offset] + }, + ) + } + + @Suppress("AvoidMutableCollections", "AvoidVarsExceptWithDelegate") + private fun reformat(s: CharSequence, cursor: Int): Transformation { + phoneNumberFormatter.clear() + + val curIndex = cursor - 1 + var formatted: String? = null + var lastNonSeparator = 0.toChar() + var hasCursor = false + + s.forEachIndexed { index, char -> + if (PhoneNumberUtils.isNonSeparator(char)) { + if (lastNonSeparator.code != 0) { + formatted = getFormattedNumber(lastNonSeparator, hasCursor) + hasCursor = false + } + lastNonSeparator = char + } + if (index == curIndex) { + hasCursor = true + } + } + + if (lastNonSeparator.code != 0) { + formatted = getFormattedNumber(lastNonSeparator, hasCursor) + } + val originalToTransformed = mutableListOf() + val transformedToOriginal = mutableListOf() + var specialCharsCount = 0 + formatted?.forEachIndexed { index, char -> + if (!PhoneNumberUtils.isNonSeparator(char)) { + specialCharsCount++ + } else { + originalToTransformed.add(index) + } + transformedToOriginal.add(index - specialCharsCount) + } + originalToTransformed.add(originalToTransformed.maxOrNull()?.plus(1) ?: 0) + transformedToOriginal.add(transformedToOriginal.maxOrNull()?.plus(1) ?: 0) + + return Transformation(formatted, originalToTransformed, transformedToOriginal) + } + + private fun getFormattedNumber(lastNonSeparator: Char, hasCursor: Boolean): String? { + return if (hasCursor) { + phoneNumberFormatter.inputDigitAndRememberPosition(lastNonSeparator) + } else { + phoneNumberFormatter.inputDigit(lastNonSeparator) + } + } + + private data class Transformation( + val formatted: String?, + val originalToTransformed: List, + val transformedToOriginal: List, + ) +} diff --git a/libs/country-code-picker/src/main/res/values-ar/strings.xml b/libs/country-code-picker/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..e6296394d --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-ar/strings.xml @@ -0,0 +1,260 @@ + + + + أفغانستان + جزر أولند + ألبانيا + الجزائر + ساموا-الأمريكي + أندورا + أندورا + أنجولا + أنجويلا + المنطقة القطبية الجنوبية + أنتيغوا وباربودا + الأرجنتين + أرمينيا + أروبا + أستراليا + النمسا + أذربيجان + باهاماس + البحرين + بنجلاديش + باربادوس + بيلاروس + بلجيكا + بيليز + بنين + برمودا + بوتان + بوليفيا + البوسنة والهرسك + بوتسوانا + البرازيل + إقليم المحيط البريطاني الهندي + بروناي + بلغاريا + بوركينا فاسو + بوروندي + كمبوديا + كاميرون + كندا + الرأس الأخضر + جزر كايمان + جمهورية أفريقيا الوسطى + تشاد + تشيلي + الصين + جزيرة كريسماس + جزر كوكس(كيلينغ) + كولومبيا + جزر القمر + جمهورية الكونغو + جمهورية الكونغو الديمقراطية + جزر كوك + كوستاريكا + ساحل العاج + كرواتيا + كوبا + Curaçao + قبرص + التشيك + الدنمارك + جيبوتي + دومينيكا + جمهورية الدومينيكان + الإكوادور + مصر + السلفادور + غينيا الاستوائية + إريتريا + إستونيا + إثيوبيا + جزر فوكلاند + جزر فارو + فيجي + فنلندا + فرنسا + غينيا الفرنسية + بولينيزيا الفرنسية + الغابون + غامبيا + جورجيا + ألمانيا + غانا + جبل طارق + اليونان + جرينلاند + غرينادا + غوادلوب + غوام + غواتيمال + غيرنزي + غينيا + غينيا بيساو + غيانا + هايتي + الفاتيكان + هندوراس + هونغ كونغ + المجر + أيسلندا + الهند + إندونيسيا + إيران + العراق + جمهورية أيرلندا + جزيرة مان + إسرائيل + إيطاليا + جامايكا + اليابان + جيرسي + الأردن + كازاخستان + كينيا + كيريباتي + كوسوفو + الكويت + قيرغيزستان + لاوس + لاتفيا + لبنان + ليسوتو + ليبيريا + ليبيا + ليختنشتاين + ليتوانيا + لوكسمبورغ + ماكاو + مدغشقر + مالاوي + ماليزيا + المالديف + مالي + مالطا + جزر مارشال + مارتينيك + موريتانيا + موريشيوس + مايوت + المكسيك + ميكرونيسيا + مولدوفا + موناكو + منغوليا + الجبل الأسو + مونتسرات + المغرب + موزمبيق + (بورما) ميانمار + ناميبيا + ناورو + نيبال + هولندا + كاليدونيا الجديدة + نيوزيلندا + نيكاراجوا + النيجر + نيجيريا + نيوي + جزيرة نورفولك + كوريا الشمالية + مقدونيا الشمالية + جزر ماريانا الشمالية + النرويج + عُمان + باكستان + بالاو + بنما + بابوا غينيا الجديدة + باراغواي + بيرو + الفلبين + بيتكيرن + بولندا + البرتغال + بورتوريكو + قطر + ريونيون + رومانيا + روسيا + رواندا + سانت بارتليمي + سانت هيلانة + سانت كيتس ونيفيس + سانت لوسيا + سانت مارتن + سانت بيير/ميكلون + سانت فينسنت والغرينادين + ساموا + سان مارينو + Sساو تومي وبرينسيب + السعودية + السنغال + صربيا + سيشل + سيراليون + سنغافورة + سانت مارتن + سريلانكا + سلوفاكيا + سلوفينيا + جزر سليمان + الصومال + جنوب أفريقيا + كوريا الجنوبية + جنوب السودان + إسبانيا + دولة فلسطين + السودان + سورينام + سوازيلند (إسواتيني) + السويد + سويسرا + سوريا + طاجيكستان + تايوان + تنزانيا + تايلاند + تيمور الشرقية + توغو + توكيلاو + تونغا + ترينيداد وتوباغو + تونس + تركيا + تركمانستان + جزر توركس/كايكوس + توفالو + أوغندا + أوكرانيا + الإمارات العربية المتحدة + المملكة المتحدة + الولايات المتحدة + أوروغواي + أوزبكستان + فانواتو + فنزويلا + فيتنام + جزر العذراء البريطانية + جزر العذراء الأمريكية + واليس وفوتونا + اليمن + زامبيا + زيمبابوي + غير معروف + بحث + أختر دولة + رقم الهاتف غير صحيح + محو + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-es/strings.xml b/libs/country-code-picker/src/main/res/values-es/strings.xml new file mode 100644 index 000000000..1ee645316 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-es/strings.xml @@ -0,0 +1,260 @@ + + + + Afganistán + Islas Åland + Albania + Argelia + Samoa Americana + Andorra + Andorra + Angola + Anguila + Antártida + Antigua y Barbuda + Argentina + Armenia + Aruba + Australia + Austria + Azerbaiyán + Bahamas + Baréin + Bangladesh + Barbados + Bielorrusia + Bélgica + Belice + Benín + Bermudas + Bután + Bolivia + Bosnia y Herzegovina + Botsuana + Brasil + Territorio Británico del Océano Índico + Brunei Darussalam + Bulgaria + Burkina Faso + Burundi + Camboya + Camerún + Canadá + Cabo Verde + Islas Caimán + República Centroafricana + Chad + Chile + China + Isla de Navidad + Islas Cocos (Keeling) + Colombia + Comoras + Congo + República Democrática del Congo + Islas Cook + Costa Rica + Costa de Marfil + Croacia + Cuba + Curaçao + Chipre + República Checa + Dinamarca + Yibuti + Dominica + República Dominicana + Ecuador + Egipto + El Salvador + Guinea Ecuatorial + Eritrea + Estonia + Etiopía + Islas Malvinas + Islas Faroe + Fiyi + Finlandia + Francia + Guayana Francesa + Polinesia Francesa + Gabón + Gambia + Georgia + Alemania + Ghana + Gibraltar + Grecia + Groenlandia + Granada + Guadalupe + Guam + Guatemala + Guernsey + Guinea + Guinea-Bissau + Guyana + Haití + Santa Sede (Ciudad del Vaticano) + Honduras + Hong Kong + Hungría + Islandia + India + Indonesia + Irán, República Islámica de + Irak + Irlanda + Isla de Man + Israel + Italia + Jamaica + Japón + Jersey + Jordania + Kazajstán + Kenia + Kiribati + Kosovo + Kuwait + Kirguistán + República Democrática Popular Lao + Letonia + Líbano + Lesoto + Liberia + Libia + Liechtenstein + Lituania + Luxemburgo + Macao + Madagascar + Malaui + Malasia + Maldivas + Malí + Malta + Islas Marshall + Martinica + Mauritania + Mauricio + Mayotte + México + Micronesia, Estados Federados de + Moldavia, República de + Mónaco + Mongolia + Montenegro + Montserrat + Marruecos + Mozambique + Birmania + Namibia + Nauru + Nepal + Países Bajos + Nueva Caledonia + Nueva Zelanda + Nicaragua + Níger + Nigeria + Niue + Islas Norfolk + Corea del Norte + Macedonia del Norte + Islas Marianas del Norte + Noruega + Omán + Pakistán + Palau + Panamá + Papúa Nueva Guinea + Paraguay + Perú + Filipinas + Islas Pitcairn + Polonia + Portugal + Puerto Rico + Qatar + Reunión + Rumania + Federación Rusa + Ruanda + San Bartolomé + Santa Elena, Ascensión y Tristán de Acuña + San Cristóbal y Nieves + Santa Lucía + San Martín + San Pedro y Miquelón + + Samoa + San Marino + Santo Tomé y Príncipe + Arabia Saudita + Senegal + Serbia + Seychelles + Sierra Leona + Singapur + Sint Maarten + Sri Lanka + Eslovaquia + Eslovenia + Islas Salomón + Somalia + Sudáfrica + Corea del Sur + Sudán del Sur + España + Palestina + Sudán + Surinam + Suazilandia + Suecia + Suiza + República Árabe Siria + Tayikistán + Taiwán + Tanzania, República Unida de + Tailandia + Timor Oriental + Togo + Tokelau + Tonga + + Túnez + Turquía + Turkmenistán + Islas Turcas y Caicos + Tuvalu + Uganda + Ucrania + Emiratos Árabes Unidos (EAU) + Reino Unido + Estados Unidos de América + Uruguay + Uzbekistán + Vanuatu + Venezuela, República Bolivariana de + Vietnam + Islas Vírgenes Británicas + Islas Vírgenes de los Estados Unidos + Wallis y Futuna + Yemen + Zambia + Zimbabue + Desconocido + Buscar\u2026 + Seleccionar país + Numero de telefono invalido + Borrar + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-fr/strings.xml b/libs/country-code-picker/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..26e4169cc --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-fr/strings.xml @@ -0,0 +1,260 @@ + + + + Afghanistan + Îles Åland + Albanie + Algérie + Samoa américaines + Andorre + Andorre + Angola + Anguilla + Antarctique + Antigua-et-Barbuda + Argentine + Arménie + Aruba + Australie + Autriche + Azerbaïdjan + Bahamas + Bahreïn + Bangladesh + Barbade + Biélorussie + Belgique + Belize + Bénin + Bermudes + Bhoutan + Bolivie + Bosnie-Herzégovine + Botswana + Brésil + Territoire britannique de l\'océan Indien + Brunei Darussalam + Bulgarie + Burkina Faso + Burundi + Cambodge + Cameroun + Canada + Cap-Vert + Îles Caïmans + République centrafricaine + Tchad + Chili + Chine + Île Christmas + Îles Cocos (Keeling) + Colombie + Comores + Congo + Congo, la République démocratique du + Îles Cook + Costa Rica + Côte d\'Ivoire + Croatie + Cuba + Curaçao + Chypre + Tchéquie (République tchèque) + Danemark + Djibouti + Dominique + République dominicaine + Équateur + Égypte + Salvador + Guinée équatoriale + Érythrée + Estonie + Éthiopie + Îles Falkland (Malouines) + Îles Féroé + Fidji + Finlande + France + Guyane française + Polynésie française + Gabon + Gambie + Géorgie + Allemagne + Ghana + Gibraltar + Grèce + Groenland + Grenade + Guadeloupe + Guam + Guatemala + Guernesey + Guinée + Guinée-Bissau + Guyana + Haïti + Saint-Siège (État de la Cité du Vatican) + Honduras + Hong Kong + Hongrie + Islande + Inde + Indonésie + Iran, République islamique d\' + Irak + Irlande + Île de Man + Israël + Italie + Jamaïque + Japon + Jersey + Jordanie + Kazakhstan + Kenya + Kiribati + Kosovo + Koweït + Kirghizistan + République démocratique populaire lao + Lettonie + Liban + Lesotho + Libéria + Libye + Liechtenstein + Lituanie + Luxembourg + Macao + Madagascar + Malawi + Malaisie + Maldives + Mali + Malte + Îles Marshall + Martinique + Mauritanie + Maurice + Mayotte + Mexique + Micronésie, États fédérés de + Moldova, République de + Monaco + Mongolie + Monténégro + Montserrat + Maroc + Mozambique + Myanmar + Namibie + Nauru + Népal + Pays-Bas + Nouvelle-Calédonie + Nouvelle-Zélande + Nicaragua + Niger + Nigéria + Niué + Île Norfolk + Corée du Nord + Macédoine du Nord + Îles Mariannes du Nord + Norvège + Oman + Pakistan + Palaos + Panama + Papouasie-Nouvelle-Guinée + Paraguay + Pérou + Philippines + Pitcairn + Pologne + Portugal + Porto Rico + Qatar + Réunion + Roumanie + Fédération de Russie + Rwanda + Saint-Barthélemy + Sainte-Hélène, Ascension et Tristan da Cunha + Saint-Kitts-et-Nevis + Sainte-Lucie + Saint-Martin (partie française) + Saint-Pierre-et-Miquelon + Saint-Vincent-et-les-Grenadines + Samoa + Saint-Marin + Sao Tomé-et-Principe + Arabie saoudite + Sénégal + Serbie + Seychelles + Sierra Leone + Singapour + Saint-Martin (partie néerlandaise) + Sri Lanka + Slovaquie + Slovénie + Îles Salomon + Somalie + Afrique du Sud + Corée du Sud + Soudan du Sud + Espagne + Palestine + Soudan + Suriname + Eswatini + Suède + Suisse + République arabe syrienne + Tadjikistan + Taïwan + Tanzanie, République unie de + Thaïlande + Timor oriental + Togo + Tokelau + Tonga + + Tunisie + Turquie + Turkménistan + Îles Turks et Caïques + Tuvalu + Ouganda + Ukraine + Émirats Arabes Unis (EAU) + Royaume-Uni + États-Unis + Uruguay + Ouzbékistan + Vanuatu + Venezuela + Viet Nam + Îles Vierges britanniques + Îles Vierges des États-Unis + Wallis-et-Futuna + Yémen + Zambie + Zimbabwe + Inconnu + Recherche\u2026 + Sélectionnez votre pays + Numéro de téléphone invalide + Effacer + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-hi/strings.xml b/libs/country-code-picker/src/main/res/values-hi/strings.xml new file mode 100644 index 000000000..6314ab908 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-hi/strings.xml @@ -0,0 +1,260 @@ + + + + अफ़ग़ानिस्तान + ऑलैण्ड द्वीपसमूह + अल्बानिया + अल्जीरिया + अमेरिकी समोआ + अण्डोरा + अण्डोरा + अंगोला + एंगुइला + अंटार्कटिका + अण्टीगुआ और बारबूडा + अर्जेंटीना + आर्मीनिया + अरूबा + ऑस्ट्रेलिया + ऑस्ट्रिया + आज़रबाइजान + बहामस + बहरीन + बांग्लादेश + बारबाडोस + बेलारूस + बेल्जियम + बेलीज़ + बेनिन + बरमूडा + भूटान + बोलीविया + बोस्निया और हर्जेगोविना + बोत्सवाना + ब्राज़िल + ब्रिटिश हिंद महासागर क्षेत्र + ब्रुनेई + बुल्गारिया + बुर्किना फासो + बुरुन्डी + कंबोडिया + कैमरुन + कनाडा + केप वर्दे + केमन द्वीपसमूह + मध्य अफ़्रीकी गणराज्य + चाड + चिली + चीन + क्रिसमस द्वीप + कोकोस द्वीपसमूह + कोलंबिया + कोमोरोस + कांगो + कांगो लोकतान्त्रिक गणराज्य + कुक द्वीपसमूह + कोस्टा रिका + कोत दिव्वार + क्रोएशिया + क्यूबा + क्युरासाओ + साइप्रस + चेक गणराज्य + डेनमार्क + जिबूती + डोमिनिका + डोमिनिकन गणराज्य + इक्वेडोर + मिस्र + एल साल्वाडोर + भूमध्यरेखीय गिनी + इरिट्रिया + एस्तोनिया + इथियोपिया + फ़ॉकलैंड द्वीपसमूह + फरो द्वीपसमूह + फ़िजी + फिनलैंड + फ्रांस + फ्रेंच गुयाना + फ़्रेंच पोलिनेशिया + Gabon + जाम्बिया + जॉर्जिया + जर्मनी + घाना + जिब्राल्टर + यूनान + ग्रीनलैंड + ग्रेनेडा + ग्वाडलूप + Guam + ग्वाटेमाला + ग्वेर्नसे + गिनी + गिनी-बिसाऊ + गुयाना + हाइती + वैटिकन शहर + हौन्डुरस + हांगकांग + हंगरी + आइसलैंड + भारत + इंडोनेशिया + ईरान + इराक + आयरलैंड + आइल ऑफ मैन + इजराइल + इटली + जमैका + जापान + जर्सी + जॉर्डन + कज़ाख़िस्तान + कीनिया + किरिबाती + कोसोवो + कुवैत + किर्ग़िज़स्तान + लाओस + लातविया + लेबनान + लिसूतू / लेसोथो + लाइबेरिया + लीबिया + लिकटेंस्टाइन + लिथुआनिया + लक्समबर्ग + मकाउ + मेडागास्कर + मलावी + मलेशिया + मालदीव + माली + माल्टा + मार्शल द्वीपसमूह + मार्टीनिक + मॉरीतानिया + मॉरीशस + मायोत + मेक्सिको + माइक्रोनेशियाf + मॉल्डोवा + मोनैको + मंगोलिया + मॉन्टेनीग्रो + मोंटेसेराट + मोरक्को + मोज़ाम्बीक + म्यांमार + नाम्बिया + नाउरु + नेपाल + नीदरलैंड + नया केलडोनिया + न्यूज़ीलैंड + निकारागुआ + नाइजर + नाईजीरिया + निउए + नॉर्फ़ोक द्वीपसमूह + उत्तर कोरिया + उत्तरी मैसेडोनिया + उत्तरी मरीयाना द्वीपसमूह + नॉर्वे + ओमान + पाकिस्तान + पलाउ + पनामा + पापुआ न्यू गिनी + पैराग्वे + पेरू + फिलिपींस + पिटकेर्न द्वीपसमूह + पोलैंड + पुर्तगाल + पोर्टो रिको + क़तर + रेयूनियों + रोमानिया + रूस + रवांडा + सेंट बार्थेलेमी + सेंट हेलेना + सेंट किट्स और नेविस + सेंट लूसिया + सेंट मार्टिन + संत पियर एवं मिकलान + सेंट विंसेंट एंड ग्रेनाडाइन्स + समोआ + सान मारिनो + साओ तोमे और प्रिन्सिपी + सउदी अरब + सेनेगल + सर्बिया + सेशेल्स + सिएरा लियोन + सिंगापुर + सिंट मार्टेन + श्रीलंका + स्लोवाकिया + स्लोवेनिया + सोलोमन द्वीपसमूह + सोमालिया + दक्षिण अफ्रीका + दक्षिण कोरिया + दक्षिण सूडान + स्पेन + फ़िलिस्तीन + सूडान + सूरीनाम + स्वाज़ीलैण्ड/एस्वातीनी + स्वीडन + स्विट्ज़रलैंड + सीरिया + तजाकिस्तान + ताइवान + तंजानिया + थाईलैंड + तिमोर-लेस्ते + टोगो + टोकेलाऊ + टोंगा + त्रिनिदाद और टोबैगो + ट्यूनीशिया + तुर्की + तुर्कमेनिस्तान + तुर्क एंड कैकोस द्वीपसमूह + तुवालू + युगांडा + यूक्रेन + संयुक्त अरब अमीरात + संयुक्त ब्रिटेन + संयुक्त राज्य अमेरिका + उरुग्वे + उज़्बेकिस्तान + वानूआतू + वेनेज़ुएला + वियतनाम + ब्रिटिश वर्जिन द्वीपसमूह + यूएस वर्जिन द्वीपसमूह + वालिस और फ़्यूचूना + यमन + जाम्बिया + ज़िम्बाब्वे + अज्ञात + खोजें\u2026 + देश चुनें + अवैध फोन नंबर + स्पष्ट + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-it-rIT/strings.xml b/libs/country-code-picker/src/main/res/values-it-rIT/strings.xml new file mode 100644 index 000000000..32f4a8364 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-it-rIT/strings.xml @@ -0,0 +1,260 @@ + + + + "Afghanistan " + "Isole Aland " + "Albania " + "Algeria " + "Samoa americane " + Andorra + "Andorra " + "Angola " + Anguilla + "Antartide " + "Antigua e Barbuda " + "Argentina " + "Armenia " + Aruba + "Australia " + "Austria " + "Azerbaigian " + "Bahamas " + "Bahrein " + "Bangladesh " + "Barbados " + "Bielorussia " + "Belgio " + "Belize " + Benin + Bermuda + Bhutan + "Bolivia " + "Bosnia Erzegovina " + "Botswana " + "Brasile " + "Territorio britannico dell'Oceano Indiano " + Brunei Darussalam + "Bulgaria " + "Burkina Faso " + Burundi + "Cambogia " + "Camerun " + "Canada " + "Isole di Capo Verde " + "Isole Cayman " + "Repubblica Centrafricana " + "Chad " + "Chile " + "Cinese " + "Isola di Natale " + "Isole Cocos (a chiglia). " + "Colombia " + "Comore " + "Congo " + "Repubblica Democratica del Congo " + "Isole Cook " + "Costa Rica " + "Costa d'Avorio " + "Croazia " + "Cuba " + Curacao + "Cipro " + "Repubblica Ceca " + "Danimarca " + "Gibuti " + "Domenicano " + "Repubblica Dominicana " + "Ecuador " + " Egitto" + El Salvador + "Guinea Equatoriale " + Eritrea + "Estonia " + "Etiopia " + "Isole Falkland (malvine) " + "Isole Faroe " + "Figi " + "Finlandia " + "Francia " + "Guiana francese " + "Polinesia francese " + Gabon + "Gambia " + "Georgia " + "Germania " + "Ghana " + "Gibilterra " + "Grecia " + "Groenlandia " + "Granata " + "Guadalupa " + Guam + Guatemala + Guernsey + "Guinea " + Gine-bissau + Guyana + Haiti + Santa Sede (Stato Città del Vaticano) + Honduras + Hong Kong + "Ungheria " + "Islanda " + "India " + Indonesia + "Repubblica Islamica dell'Iran " + "Iraq " + Irlanda + "Isola di Man " + "Israele " + "Italia " + "Giamaica " + "Giappone " + Jersey + "Giordania " + "Kazakistan " + "Kenia " + Kiribati + Kosovo + "Kuwait " + "Kirghizistan " + "Repubblica Democratica Popolare del Laos " + "Lettonia " + "Libano " + Lesotho + "Liberia " + "Libia " + "Liechtenstein " + "Lituania " + "Lussemburgo " + "Macao " + "Madagascar " + Malawi + "Malaysia " + "Maldive " + Mali + "Malta " + "Isole Marshall " + "Martinica " + "Mauritania " + "Maurizio " + Mayotte + "Messicano " + "Micronesia, Stati Federati " + "Repubblica di Moldova " + "Monaco " + "Mongolia " + "Montenegro " + Montserrat + "Marocco " + "Mozambico " + "Birmania " + "Namibia " + Nauru + Nepal + "Olanda " + "Nuova Caledonia " + "Nuova Zelanda " + "Nicaragua " + "Niger " + "Nigeria " + "Niue " + "Isole Norfolk " + "Corea del nord " + "Macedonia " + "Isole Marianne settentrionali " + "Norvegia " + "Oman " + "Pakistan " + Palau + "Panama " + "Papua Nuova Guinea " + "Paraguay " + "Perù " + Filippine + "Isole Pitcairn " + Polonia + "Portogallo " + "Porto Rico " + Qatar + "Riunione " + Romania + "Federazione Russa " + Ruanda + "San Bartolomeo " + "Sant'Elena, Ascensione e Tristano Da Cunha " + "Saint Kitts e Nevis " + "Santa Lucia " + "San Martino " + "Santi Pietro e Miquelon " + St. Vincent e Grenadine + Samoa + San Marino + "Sao Tomé e Principe " + "Arabia Saudita " + "Senegal " + "Serbia " + "Seychelles " + Sierra Leone + "Singapore " + "Sint Maarten " + Sri Lanka + "Slovacchia " + "Slovenia " + "Isole Salomone " + Somali + Sud Africa + "Corea del Sud " + "Sudan del Sud " + "Spagna " + "Palestina " + "Sudan " + "Suriname " + "Swaziland " + "Svezia " + "Svizzera " + "Repubblica Araba Siriana " + "Tagikistan " + "Taiwan " + "Tanzania, Repubblica Unita " + "Tailandia " + "Timor Est " + "Andare " + Tokelau + "Tongano " + "Trinidad e Tobago " + "Tunisia " + Turchia + "Turkmenistan " + "Isole Turks e Caicos " + "Tuvalù " + "Uganda " + "Ucraina " + "Unità degli Emirati Arabi " + "Regno Unito " + "Stati Uniti d'America " + "Uruguay " + "Uzbekistan " + Vanuatu + Venezuela, Repubblica Bolivariana + Vietnam + Isole Vergini Britanniche + Isole Vergini americane + Wallis ve Futuna + Yemen + Zambia + Zimbabwe + Sconosciuto + Ricerca\u2026 + Seleziona il paese + Numero di telefono sbagliato + Pulisci + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-nl/strings.xml b/libs/country-code-picker/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..2655b61bf --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-nl/strings.xml @@ -0,0 +1,260 @@ + + + + Afghanistan + Åland + Albanië + Algerije + Amerikaans-Samoa + Andorra + Andorra + Angola + Anguilla + Antarctica + Antigua en Barbuda + Argentinië + Armenië + Aruba + Australië + Oostenrijk + Azerbeidzjan + Bahamas + Bahrein + Bangladesh + Barbados + Wit-Rusland + België + Belize + Benin + Bermuda + Bhutan + Bolivia + Bosnië en Herzegovina + Botswana + Brazilië + Brits Indische Oceaanterritorium + Brunei Darussalam + Bulgarije + Burkina Faso + Burundi + Cambodja + Kameroen + Canada + Kaapverdië + Kaaimaneilanden + Centraal-Afrikaanse Republiek + Tsjaad + Chili + China + Christmaseiland + Cocoseilanden (Keeling) + Colombia + Comoren + Republiek Congo + Democratische Republiek Congo + Cookeilanden + Costa Rica + Ivoorkust + Kroatië + Cuba + Curaçao + Cyprus + Tsjechische Republiek + Denemarken + Djibouti + Dominica + Dominicaanse Republiek + Ecuador + Egypte + El Salvador + Equatoriaal-Guinea + Eritrea + Estland + Ethiopië + Falklandeilanden + Faeröer Eilanden + Fiji + Finland + Frankrijk + Frans-Guyana + Frans-Polynesië + Gabon + Gambia + Georgië + Duitsland + Ghana + Gibraltar + Griekenland + Groenland + Grenada + Guadeloupe + Guam + Guatemala + Guernsey + Guinee + Guinee-Bissau + Guyana + Haïti + Vaticaanstad (Heilige Stoel) + Honduras + Hongkong + Hongarije + IJsland + India + Indonesië + Iran, Islamitische Republiek + Irak + Ierland + Eiland Man + Israël + Italië + Jamaica + Japan + Jersey + Jordanië + Kazachstan + Kenia + Kiribati + Kosovo + Koeweit + Kirgizië + Laos, Democratische Volksrepubliek + Letland + Libanon + Lesotho + Liberia + Libië + Liechtenstein + Litouwen + Luxemburg + Macau + Madagaskar + Malawi + Maleisië + Maldiven + Mali + Malta + Marshalleilanden + Martinique + Mauritanië + Mauritius + Mayotte + Mexico + Micronesië, Federale Staten van + Moldavië, Republiek + Monaco + Mongolië + Montenegro + Montserrat + Marokko + Mozambique + Myanmar (Birma) + Namibië + Nauru + Nepal + Nederland + Nieuw-Caledonië + Nieuw-Zeeland + Nicaragua + Niger + Nigeria + Niue + Norfolkeilanden + Noord-Korea + Noord-Macedonië + Noordelijke Marianen + Noorwegen + Oman + Pakistan + Palau + Panama + Papoea-Nieuw-Guinea + Paraguay + Peru + Filipijnen + Pitcairneilanden + Polen + Portugal + Puerto Rico + Qatar + Réunion + Roemenië + Russische Federatie + Rwanda + Sint-Bartholomeus + Sint-Helena, Ascension en Tristan da Cunha + Saint Kitts en Nevis + Saint Lucia + Collectiviteit van Sint-Maarten + Saint-Pierre en Miquelon + + Samoa + San Marino + Sao Tomé en Principe + Saoedi-Arabië + Senegal + Servië + Seychellen + Sierra Leone + Singapore + Sint Maarten + Sri Lanka + Slowakije + Slovenië + Salomonseilanden + Somalië + Zuid-Afrika + Zuid-Korea + Zuid-Soedan + Spanje + Palestina + Soedan + Suriname + Swaziland + Zweden + Zwitserland + Syrische Arabische Republiek + Tadzjikistan + Taiwan + Tanzania, Verenigde Republiek + Thailand + Oost-Timor + Togolese Republiek + Tokelau + Tonga + + Tunesië + Turkije + Turkmenistan + Turks- en Caicoseilanden + Tuvalu + Oeganda + Oekraïne + Verenigde Arabische Emiraten (UAE) + Verenigd Koninkrijk + Verenigde Staten van Amerika + Uruguay + Oezbekistan + Vanuatu + Venezuela, Bolivariaanse Republiek + Vietnam + Britse Maagdeneilanden + Amerikaanse Maagdeneilanden + Wallis en Futuna + Jemen + Zambia + Zimbabwe + Onbekend + Zoeken\u2026 + Selecteer land + Ongeldig telefoonnummer + Wissen + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-ru-rRU/strings.xml b/libs/country-code-picker/src/main/res/values-ru-rRU/strings.xml new file mode 100644 index 000000000..5b56af0f6 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-ru-rRU/strings.xml @@ -0,0 +1,260 @@ + + + + Афганистан + Аландские острова + Албания + Алжир + Американское Самоа + Андорра + Андорра + Ангола + Ангилья + Антарктика + Антигуа и Барбуда + Аргентина + Армения + Аруба + Австралия + Австрия + Азербайджан + Багамы + Бахрейн + Бангладеш + Барбадос + Беларусь + Бельгия + Белиз + Бенин + Бермуды + Бутан + Боливия + Босния и Герцеговина + Ботсвана + Бразилия + Британская территория Индийского океана + Бруней-Даруссалам + Болгария + Буркина-Фасо + Бурунди + Камбоджа + Камерун + Канада + Кабо-Верде + Кайманы + Центральноафриканская республика + Чад + Чили + Китай + Остров Рождества + Кокосовые острова (острова Килинг) + Колумбия + Коморские острова + Конго + Демократическая республика Конго + Острова Кука + Коста-Рика + Кот-д-Ивуар + Хорватия + Куба + Курасао + Кипр + Чехия + Дания + Джибути + Доминика + Доминиканская республика + Эквадор + Египет + Сальвадор + Экваториальная Гвинея + Эритрея + Эстония + Эфиопия + Фолклендские острова (Мальвинские острова) + Фарерские острова + Фиджи + Финляндия + Франция + Французская Гвиана + Французская Полинезия + Габон + Гамбия + Грузия + Германия + Гана + Гибралтар + Греция + Гренландия + Гренада + Гваделупа + Гуам + Гватемала + Гернси + Гвинея + Гвинея-Бисау + Гайана + Гаити + город-государство Ватикан + Гондурас + Гонконг + Венгрия + Исландия + Индия + Индонезия + Исламская Республика Иран + Ирак + Ирландия + Остров Мэн + Израиль + Италия + Ямайка + Япония + Джерси + Иордания + Казахстан + Кения + Кирибати + Косово + Кувейт + Кыргызстан + Лаосская Народно-Демократическая Республика + Латвия + Ливан + Лесото + Либерия + Ливия + Лихтенштейн + Литва + Люксембург + Макао + Мадагаскар + Малави + Малайзия + Мальдивы + Мали + Мальта + Маршалловы острова + Мартиника + Мавритания + Маврикий + Майотта + Мексика + Федеративные Штаты Микронезии + Молдова + Монако + Монголия + Черногория + Монтсеррат + Марокко + Мозамбик + Мьянма + Намибия + Науру + Непал + Нидерланды + Новая Каледония + Новая Зеландия + Никарагуа + Нигер + Нигерия + Ниуэ + Норфолкские острова + Корейская Народно-Демократическая Республика + Северная Македония + Северные Марианские острова + Норвегия + Оман + Пакистан + Палау + Панама + Папуа-Новая Гвинея + Парагвай + Перу + Филиппины + Острова Питкэрн + Польша + Португалия + Пуэрто-Рико + Катар + Реюньон + Румыния + Российская Федерация + Руанда + Сен-Бартельми + Святая Елена, Вознесение и Тристан да Кунья + Сент-Китс и Невис + Сент-Люсия + Сент-Мартин + Сен-Пьер и Микелон + Сент-Винсент и Гренадины + Самоа + Сан-Марино + Сан-Томе и Принсипи + Саудовская Аравия + Сенегал + Сербия + Сейшелы + Сьерра-Леоне + Сингапур + Синт-Мартен + Шри-Ланка + Словакия + Словения + Соломоновы острова + Сомали + Южноафриканская республика + Республика Корея + Южный Судан + Испания + Палестина + Судан + Суринам + Свазиленд + Швеция + Швейцария + Сирийская Арабская Республика + Таджикистан + Тайвань + Танзания + Тайланд + Тимор-Лешти + Того + Токелау + Тонга + Тринидад и Тобаго + Тунис + Турция + Туркменистан + острова Теркс и Кайкос + Тувалу + Уганда + Украина + Объединённые Арабские Эмираты (ОАЭ) + Великобритания + Соединённые Штаты Америки + Уругвай + Узбекистан + Вануату + Боливарианская Республика Венесуэла + Вьетнам + Британские Виргинские Острова + Виргинские острова США + Уоллис и Футуна + Йемен + Замбия + Зимбабве + Неизвестный + Поиск\u2026 + Выберите страну + Неверный номер телефона + Очистить + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-so/strings.xml b/libs/country-code-picker/src/main/res/values-so/strings.xml new file mode 100644 index 000000000..098a763b9 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-so/strings.xml @@ -0,0 +1,260 @@ + + + + Afgaanistaan + Jasiiradaha Aaland + Albaaniya + Aljeeriya + Samowada Ameerika + Andora + Andora + Angoola + Anguilla + Antarctica + Antigua iyo Barbuda + Arjentiina + Armeeniya + Aruba + Awstaraaliya + Awsteriya + Axerbayjaan + Bahaamas + Baareen + Bangladesh + Barbados + Belaarus + Biljam + Beliis + Biniin + Bermuuda + Buutan + Boliiviya + Bosniya iyo Hargaysa + Botswana + Baraasiil + Xeebta Hindiya ee Biritishka + Brunayi Darussalam + Bulgaariya + Burkiina Faaso + Burundi + Kamboja + Kameruun + Kanada + Cape Verde + Cayman Islands + Jamhuuriyadda Afrikada Dhexe + Chad + Jiili + Shiinaha + Jasiirada Kiristmas + Jasiiradaha Cocos (Keeling) + Kolombiya + Komoros + Congo + Jamhuuriyadda Dimuqraadiga Congo + Jasiiradaha Cook + Costa Rica + Koot Divuaar + Koratia + Kuba + Curaçao + Qubrus + Jamhuuriyadda Jek + Denmark + Jabuuti + Dominica + Jamhuuriyadda Dimuqraadiga Dominika + Ikwadoor + Masar + El Salvador + Giniiga Guine + Eritrea + Estooniya + Itoobiya + Jasiiradaha Falkland (Malvinas) + Jasiiradaha Faroe + Fiji + Finland + Faransiiska + Guyana Faransiiska + French Polynesia + Gaboon + Gambia + Joorjiya + Jarmal + Ghana + Gibraltar + Giriigga + Greenland + Grenada + Guadeloupe + Guam + Guatemala + Guernsey + Gini + Gini-Bisaawu + Guyana + Haiti + Maka Mokha (Madaxweyne) Mar Vatican City + Honduras + Hong Kong + Hungari + Aisland + Hindiya + Indoneesiya + Iiraan + Ciraaq + Ayrlaand + Jasiirada Man + Israa\'iil + Talyaani + Jamaaika + Jabbaan + Jersey + Jordan + Kazakhstan + Kenya + Kiribati + Kosovo + Kuwait + Kyrgyzstan + Jamhuuriyadda Dimuqraadiga Lac + Latvia + Lebanon + Lesotho + Liberia + Libya + Liechtenstein + Lithuania + Luxembourg + Macau + Madagascar + Malawi + Malaysia + Maldives + Mali + Malta + Marshall Islands + Martinique + Mauritania + Mauritius + Mayotte + Meksiko + Mikroneesiya, Qoomiyadda Federaalka + Moldova, Jamhuuriyadda + Monaco + Mongolia + Montenegro + Montserrat + Morocco + Mozambique + Myanmar + Namibiya + Nauru + Nepal + Netherlands + New Caledonia + New Zealand + Nikaraguwa + Niger + Nayjeriya + Niue + Jasiiradaha Norfolk + Korega Waqooyi + Macedonia Waqooyi + Northern Mariana Islands + Norway + Cumaan + Pakistan + Belaw + Panama + Papua New Guinea + Baragway + Piru + Filibiin + Jasiiradaha Pitcairn + Booland + Bortuqaal + Puerto Rico + Qadar + Riyuuniyon + Rumaaniya + Ruushka + Ruwanda + Saint Barthélemy + St. Helena, Ascension iyo Tristan da Cunha + Saint Kitts iyo Nevis + Saint Lucia + Saint Martin + Saint Pierre iyo Miquelon + + Samoa + San Marino + Sao Tome iyo Principe + Sacuudi Carabiya + Sinigaal + Sarbijiya + Seyshelis + Siyara Liyoon + Singabuur + Sint Maarten + Sri Lanka + Slovakia + Sloveniya + Jasiiradaha Solomon + Soomaaliya + Koonfur Afrika + Korega Koonfurta + Sudan Koonfurta + Isbaaniya + Falastiin + Suudaan + Surinaam + Swaasilaan + Iswidhan + Switzerland + Jamhuuriyadda Kuuriya Ee Shiinaha + Tajikistan + Taiwan + Tanzaniya, Jamhuuriyadda Muuminadaha + Taylaand + Timor-Leste + Togo + Tokelau + Tonga + + Tunisiya + Turki + Turkmenistan + Turks iyo Caicos Islands + Tuvalu + Ugaanda + Ukrayn + Imaaraadka Carabta (UAE) + "Boqortooyada Midowday " + Maraykanka + Uruguay + Uzbekistan + Vanuatu + Fenisuweela, Jamhuuriyadda Bolivarian + Fiyetnaam + Jasiiradaha Biritishka ee Fadhiyaan + Jasiiradaha Mareykanka ee Fadhiyaan + Wallis iyo Futuna + Yaman + Zambiya + Simbabwe + Aan la garanayn + Raadi\u2026 + Xulo waddanka + Lambarka Taleefanka aan sax ahayn + Nadiifi + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-tr-rTR/strings.xml b/libs/country-code-picker/src/main/res/values-tr-rTR/strings.xml new file mode 100644 index 000000000..972b0f93a --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-tr-rTR/strings.xml @@ -0,0 +1,260 @@ + + + + Afganistan + Åland Adaları + Arnavutluk + Cezayir + Amerikan Samoası + Andorra + Andorra + Angola + Anguilla + Antartika + Antigua and Barbuda + Arjantin + Ermenistan + Aruba + Avustralya + Avusturya + Azerbaycan + Bahamalar + Bahreyn + Bangladeş + Barbados + Beyaz Rusya + Belçika + Belize + Benin + Bermuda + Bhutan + Bolivya + Bosna Hersek + Botsvana + Brezilya + Britanya Hint Okyanusu Toprakları + Brunei Darussalam + Bulgaristan + Burkina Faso + Burundi + Kamboçya + Kamerun + Kanada + Yeşil Burun Adaları + Cayman Adaları + Orta Afrika Cumhuriyeti + Çad + Şili + Çin + Noel Adası + Cocos (keeling) Adaları + Kolombiya + Comoros + Kongo + Kongo Demoktratik Cumhuriyeti + Cook Adaları + Kosta Rika + Fildişi Sahili + Hırvatistan + Küba + Curacao + Kıbrıs + Çek Cumhuriyeti + Danimarka + Cibuti + Dominik + Dominik Cumhuriyeti + Ekvador + Mısır + El Salvador + Ekvator Ginesi + Eritre + Estonya + Etiyopya + Falkland Adaları (malvinas) + Faroe Adaları + Fiji + Finlandiya + Fransa + Fransız Guyanası + Fransız Polinezyası + Gabon + Gambiya + Gürcistan + Almanya + Gana + Cebelitarık + Yunanistan + Grönland + Grenada + Guadelup + Guam + Guatemala + Guernsey + Gine + Gine-bissau + Guyana + Haiti + Holy See (vatikan Şehir Devleti) + Honduras + Hong Kong + Macaristan + İzlanda + Hindistan + Endonezya + İran İslam Cumhuriyeti + Irak + İrlanda + Man Adası + İsrail + İtalya + Jamaika + Japonya + Jersey + Ürdün + Kazakistan + Kenya + Kiribati + Kosova + Kuveyt + Kırgızistan + Lao Demokratik Halk Cumhuriyeti + Letonya + Lübnan + Lesoto + Liberya + Libya + Lihtenştayn + Litvanya + Lüksemburg + Makao + Madagaskar + Malawi + Malezya + Maldivler + Mali + Malta + Marşal Adaları + Martinik + Moritanya + Mauritius + Mayotte + Meksika + Mikronezya, Federal Devletler + Moldova Cumhuriyeti + Monako + Mongolistan + Karadağ + Montserrat + Fas + Mozambik + Myanmar + Namibya + Nauru + Nepal + Hollanda + Yeni Kaledonya + Yeni Zelanda + Nikaragua + Nijer + Nijerya + Niue + Norfolk Adaları + Kuzey Kore + Makedonya + Kuzey Mariana Adaları + Norveç + Umman + Pakistan + Palau + Panama + Papua Yeni Gine + Paraguay + Peru + Filipinler + Pitcairn Adaları + Polonya + Portekiz + Porto Riko + Katar + Réunion + Romanya + Rusya Federasyonu + Ruanda + Saint Barthélemy + Saint Helena, Yükseliş ve Tristan Da Cunha + Saint Kitts ve Nevis + Aziz Lucia + Aziz Martin + Aziz Pierre ve Miquelon + + Samoa + San Marino + Sao Tome ve Principe + Suudi Arabistan + Senegal + Sırbistan + Seyşeller + Sierra Leone + Singapur + Sint Maarten + Sri Lanka + Slovakya + Slovenya + Solomon Adaları + Somali + Güney Afrika + Güney Kore + Güney Sudan + İspanya + Filistin + Sudan + Surinam + Svaziland + İsveç + İsviçre + Suriye Arap Cumhuriyeti + Tacikistan + Tayvan + Tanzanya, Birleşik Cumhuriyeti + Tayland + Timor-leste + Togo + Tokelau + Tonga + + Tunus + Türkiye + Türkmenistan + Turks ve Caicos Adaları + Tuvalu + Uganda + Ukrayna + Birleşik Arap Emirlikleri + Birleşik Krallık + Amerika Birleşik Devletleri + Uruguay + Özbekistan + Vanuatu + Venezuela, Bolivarcı Cumhuriyeti + Vietnam + Britanya Virjin Adaları + Amerika Birleşik Devletleri Virgin Adaları + Wallis ve Futuna + Yemen + Zambiya + Zimbabve + Bilinmiyor + Ara\u2026 + Ülke Seçiniz + Hatalı Telefon Numarası + Temizle + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values-zh/strings.xml b/libs/country-code-picker/src/main/res/values-zh/strings.xml new file mode 100644 index 000000000..210bac47f --- /dev/null +++ b/libs/country-code-picker/src/main/res/values-zh/strings.xml @@ -0,0 +1,260 @@ + + + + 阿富汗 + 奥兰群岛 + 阿尔巴尼亚 + 阿尔及利亚 + 美属萨摩亚 + 安道尔 + 安道尔 + 安哥拉 + 安圭拉 + 南极洲 + 安提瓜和巴布达 + 阿根廷 + 亚美尼亚 + 阿鲁巴 + 澳大利亚 + 奥地利 + 阿塞拜疆 + 巴哈马 + 巴林 + 孟加拉国 + 巴巴多斯 + 白俄罗斯 + 比利时 + 伯利兹 + 贝宁 + 百慕大 + 不丹 + 玻利维亚 + 波斯尼亚和黑塞哥维那 + 博茨瓦纳 + 巴西 + 英属印度洋领地 + 文莱达鲁萨兰国 + 保加利亚 + 布基纳法索 + 布隆迪 + 柬埔寨 + 喀麦隆 + 加拿大 + 佛得角 + 开曼群岛 + 中非共和国 + 乍得 + 智利 + 中国 + 圣诞岛 + 科科斯(基林)群岛 + 哥伦比亚 + 科摩罗 + 刚果 + 刚果民主共和国 + 库克群岛 + 哥斯达黎加 + 科特迪瓦 + 克罗地亚 + 古巴 + 库拉索 + 塞浦路斯 + 捷克共和国 + 丹麦 + 吉布提 + 多米尼加 + 多米尼加共和国 + 厄瓜多尔 + 埃及 + 萨尔瓦多 + 赤道几内亚 + 厄立特里亚 + 爱沙尼亚 + 埃塞俄比亚 + 福克兰群岛 + 法罗群岛 + 斐济 + 芬兰 + 法国 + 法属圭亚那 + 法属波利尼西亚 + 加蓬 + 冈比亚 + 格鲁吉亚 + 德国 + 加纳 + 直布罗陀 + 希腊 + 格陵兰 + 格林纳达 + 瓜德罗普 + 关岛 + 危地马拉 + 根西岛 + 几内亚 + 几内亚比绍 + 圭亚那 + 海地 + 梵蒂冈 + 洪都拉斯 + 香港 + 匈牙利 + 冰岛 + 印度 + 印度尼西亚 + 伊朗伊斯兰共和国 + 伊拉克 + 爱尔兰 + 曼岛 + 以色列 + 意大利 + 牙买加 + 日本 + 澤西 + 约旦 + 哈萨克斯坦 + 肯尼亚 + 基里巴斯 + 科索沃 + 科威特 + 吉尔吉斯斯坦 + 老挝人民民主共和国 + 拉脱维亚 + 黎巴嫩 + 莱索托 + 利比里亚 + 利比亚 + 列支敦士登 + 立陶宛 + 卢森堡 + 澳门 + 马达加斯加 + 马拉维 + 马来西亚 + 马尔代夫 + 马里 + 马耳他 + 马绍尔群岛 + 马提尼克 + 毛里塔尼亚 + 毛里求斯 + 马约特 + 墨西哥 + 密克罗尼西亚 + 摩尔多瓦 + 摩纳哥 + 蒙古 + 黑山 + 蒙特塞拉特 + 摩洛哥 + 莫桑比克 + 缅甸 + 纳米比亚 + 瑙鲁 + 尼泊尔 + 荷兰 + 新喀里多尼亚 + 新西兰 + 尼加拉瓜 + 尼日尔 + 尼日利亚 + 纽埃 + 诺福克岛 + 朝鲜 + 北馬其頓 + 北马里亚纳群岛 + 挪威 + 阿曼 + 巴基斯坦 + 帕劳 + 巴拿马 + 巴布亚新几内亚 + 巴拉圭 + 秘鲁 + 菲律宾 + 皮特凯恩 + 波兰 + 葡萄牙 + 波多黎各 + 卡塔尔 + 留尼汪 + 罗马尼亚 + 俄罗斯 + 卢旺达 + 圣巴泰勒米 + 圣赫勒拿、阿森松岛和特里斯坦达库尼亚群岛 + 圣基茨和尼维斯 + 圣卢西亚 + 圣马丁 + 圣皮埃尔和密克隆 + + 萨摩亚 + 圣马力诺 + 圣多美和普林西比 + 沙特阿拉伯 + 塞内加尔 + 塞尔维亚 + 塞舌尔 + 塞拉利昂 + 新加坡 + 荷属圣马丁 + 斯里兰卡 + 斯洛伐克 + 斯洛文尼亚 + 所罗门群岛 + 索马里 + 南非 + 韩国 + 南苏丹 + 西班牙 + 巴勒斯坦 + 苏丹 + 苏里南 + 斯威士兰 + 瑞典 + 瑞士 + 叙利亚 + 塔吉克斯坦 + 台湾 + 坦桑尼亚联合共和国 + 泰国 + 东帝汶 + 多哥 + 托克劳 + 汤加 + + 突尼斯 + 土耳其 + 土库曼斯坦 + 特克斯和凯科斯群岛 + 图瓦卢 + 乌干达 + 乌克兰 + 阿拉伯联合酋长国 + 英国 + 美国 + 乌拉圭 + 乌兹别克斯坦 + 瓦努阿图 + 委内瑞拉 + 越南 + 英属维京群岛 + 美属维京群岛 + 瓦利斯和富图纳 + 也门 + 赞比亚 + 津巴布韦 + 未知 + 搜索 + 选择国家 + 无效的电话号码 + 清空 + \ No newline at end of file diff --git a/libs/country-code-picker/src/main/res/values/strings.xml b/libs/country-code-picker/src/main/res/values/strings.xml new file mode 100644 index 000000000..c92eef4f6 --- /dev/null +++ b/libs/country-code-picker/src/main/res/values/strings.xml @@ -0,0 +1,502 @@ + + + + Afghanistan + Åland Islands + Albania + Algeria + American Samoa + Andorra + Andorra + Angola + Anguilla + Antarctica + Antigua and Barbuda + Argentina + Armenia + Aruba + Australia + Austria + Azerbaijan + Bahamas + Bahrain + Bangladesh + Barbados + Belarus + Belgium + Belize + Benin + Bermuda + Bhutan + Bolivia + Bosnia And Herzegovina + Botswana + Brazil + British Indian Ocean Territory + Brunei Darussalam + Bulgaria + Burkina Faso + Burundi + Cambodia + Cameroon + Canada + Cape Verde + Cayman Islands + Central African Republic + Chad + Chile + China + Christmas Island + Cocos (Keeling) Islands + Colombia + Comoros + Congo Republic + Congo, The Democratic Republic Of The + Cook Islands + Costa Rica + Côte D\'ivoire + Croatia + Cuba + Curaçao + Cyprus + Czech Republic + Denmark + Djibouti + Dominica + Dominican Republic + Ecuador + Egypt + El Salvador + Equatorial Guinea + Eritrea + Estonia + Ethiopia + Falkland Islands (malvinas) + Faroe Islands + Fiji + Finland + France + French Guyana + French Polynesia + Gabon + Gambia + Georgia + Germany + Ghana + Gibraltar + Greece + Greenland + Grenada + Guadeloupe + Guam + Guatemala + Guernsey + Guinea + Guinea-bissau + Guyana + Haiti + Holy See (vatican City State) + Honduras + Hong Kong + Hungary + Iceland + India + Indonesia + Iran, Islamic Republic Of + Iraq + Ireland + Isle Of Man + Israel + Italy + Jamaica + Japan + Jersey + Jordan + Kazakhstan + Kenya + Kiribati + Kosovo + Kuwait + Kyrgyzstan + Lao People\'s Democratic Republic + Latvia + Lebanon + Lesotho + Liberia + Libya + Liechtenstein + Lithuania + Luxembourg + Macau + Madagascar + Malawi + Malaysia + Maldives + Mali + Malta + Marshall Islands + Martinique + Mauritania + Mauritius + Mayotte + Mexico + Micronesia, Federated States Of + Moldova, Republic Of + Monaco + Mongolia + Montenegro + Montserrat + Morocco + Mozambique + Myanmar + Namibia + Nauru + Nepal + Netherlands + New Caledonia + New Zealand + Nicaragua + Niger + Nigeria + Niue + Norfolk Islands + North Korea + Macedonia (FYROM) + Northern Mariana Islands + Norway + Oman + Pakistan + Palau + Panama + Papua New Guinea + Paraguay + Peru + Philippines + Pitcairn Islands + Poland + Portugal + Puerto Rico + Qatar + Réunion + Romania + Russian Federation + Rwanda + Saint Barthélemy + Saint Helena, Ascension And Tristan Da Cunha + Saint Kitts and Nevis + Saint Lucia + Saint Martin + Saint Pierre And Miquelon + + Samoa + San Marino + Sao Tome And Principe + Saudi Arabia + Senegal + Serbia + Seychelles + Sierra Leone + Singapore + Sint Maarten + Sri Lanka + Slovakia + Slovenia + Solomon Islands + Somalia + South Africa + South Korea + South Sudan + Spain + Palestine + Sudan + Suriname + Swaziland + Sweden + Switzerland + Syrian Arab Republic + Tajikistan + Taiwan + Tanzania, United Republic Of + Thailand + Timor-leste + Togo + Tokelau + Tonga + + Tunisia + Türkiye + Turkmenistan + Turks and Caicos Islands + Tuvalu + Uganda + Ukraine + United Arab Emirates (UAE) + United Kingdom + United States Of America + Uruguay + Uzbekistan + Vanuatu + Venezuela, Bolivarian Republic Of + Vietnam + British Virgin Islands + US Virgin Islands + Wallis And Futuna + Yemen + Zambia + Zimbabwe + Unknown + Search\u2026 + Select Country + Invalid Phone Number + Clear + 70 123 4567 + 551 23 45 67 + 684-733-1234 + 50 123 4567 + 41 2345678 + (xxx) xxx-xxxx + 312 345 + 923 123 456 + 268-464-1234 + 9 11 2345-6789 + 67 212 3456 + 560 1234 + 412 345 678 + 664 123456 + 40 123 45 67 + 690 00 12 34 + 242-359-1234 + 3600 1234 + 1812-345678 + 246-250-1234 + 29 491-19-11 + 470 12 34 56 + 622-1234 + 90 01 12 34 + 441-370-1234 + 17 12 34 56 + 7400 123456 + 71234567 + 61 123 456 + 71 123 456 + 11 96123-4567 + 712 3456 + 48 123 456 + 70 12 34 56 + 991 12 34 + 345-323-1234 + 77 83 10 01 + 412 345 678 + 71 234 + 9 518 1234 + 63 01 23 45 + 601 123 456 + 131 2345 6789 + 32 12 34 56 + 809-234-5678 + 767-225-1234 + 99 123 4567 + 222 123 456 + 7012 3456 + 7 123 456 + 77 123456 + 5123 4567 + 91 123 4567 + 51234 + 211234 + 650-123456 + 501 234 56 78 + 905 123 4567 + 599 123 456 + 6 12 34 56 78 + 694 20 12 34 + 87 12 34 56 + 6 03 12 34 + 301 2345 + 23 123 4567 + 601 12 34 56 + 955 012 345 + 473-403-1234 + 22 12 34 + 690 00 12 34 + 671-300-1234 + 5123 4567 + 7781 123456 + 609 1234 + 71 123 4567 + -2000-0000 + 977 123 456 + 555 12 34 56 + 34 10 1234 + 92 123 4567 + 6 12345678 + 9123-4567 + 5123 4567 + 284-300-1234 + 612 34 56 78 + 70 123 45 67 + 78 123 45 67 + -1234-5678 + 7797 712345 + 91 234 567 + 6 71 23 45 67 + (xxx) xxx-xxxx + 67 622 901 + 3312 3456 + 771 000 9998 + 712 123456 + 96 123456 + 700 123 456 + 321 1234567 + 321 23 45 + 61234567 + 991 234 567 + 43 201 234 + 8312 3456 + 500 12345 + 192 123 4567 + 72 345 678 + 670-234-5678 + 5 1234567 + 20 23 123 456 + 5012 3456 + 21 234 567 + 77 012 3456 + 91-2345678 + 612 34567 + 71 123 456 + 628 123 456 + 20 123 4567 + 6612 3456 + 32 12 345 67 + 991 23 45 67 + 771-2345 + 12-345 6789 + 65 01 23 45 + 9696 1234 + 235-1234 + 696 20 12 34 + 5251 2345 + 639 01 23 45 + 222 123 4567 + 100 123 4567 + 350 1234 + 8812 3456 + 621 12 345 + 6 12 34 56 78 + 664-492-3456 + 22 12 34 56 + 82 123 4567 + 9 712 345 678 + 81 123 4567 + 555 1234 + 984-1234567 + 93 12 34 56 + 802 123 4567 + 888 4012 + 412 345 678 + 3 81234 + 406 12 345 + 70 01 23 45 + 91 234 56 78 + 301 2345678 + 620 1234 + 6123-4567 + 7012 3456 + 961 456789 + 912 345 678 + 512 345 678 + 912 345 678 + 787-234-5678 + 692 12 34 56 + 712 034 567 + 720 123 456 + 912 345-67-89 + 690 00 12 34 + 51234 + 869-765-2917 + 758-284-5678 + 55 12 34 + 784-430-1234 + 72 12345 + 66 66 12 12 + 981 2345 + 70 123 45 67 + 2 510 123 + 60 1234567 + 25 123456 + 8123 4567 + 721-520-5678 + 912 123 456 + 74 21234 + 7 1123456 + 71 234 5678 + 91 123 1234 + 741-2345 + 944 567 890 + 51 234 5678 + 7612 3456 + 2 2123 4567 + 917 12 3456 + 621 234 567 + 81 234 5678 + 912 345 678 + 7721 2345 + 90 11 23 45 + 7290 + 771 5123 + 868-291-1234 + 20 123 456 + 649-231-1234 + 901234 + 66 123456 + 712 345678 + 50 123 4567 + 9212 3456 + 94 231 234 + 7 9012 3456 + 591 2345 + 412-1234567 + 91 234 56 78 + 82 12 34 + 712 345 678 + 75.12.34 + 21 123 4567 + 691 234 5678 + 95 5123456 + 71 234 5678 + (264) 123-1234 + xxx xxx + 29 12 34 56 + 02 12 34 56 + 0171 123456 + 200 52200 + 042 123456 + 665 1234 + 03-123-4567 + 087 123 4567 + 21 8379 6236 + xxxxx xxxxx + 021 1234 5678 + 388 123 4567 + (876) 123-4567 + 0777 123 4567 + 070 123 456 + 06 698xxxxx + (340) xxx-xxxx + 3xx xxxx + xxxx xxxxxx + xxx xxxx + xxxxxxxx + xxx xxxx + xxxx xxxx + xxxxxxxx(x) + \ No newline at end of file diff --git a/libs/material3-navigation/.gitignore b/libs/material3-navigation/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/libs/material3-navigation/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/libs/material3-navigation/README.md b/libs/material3-navigation/README.md new file mode 100644 index 000000000..832103582 --- /dev/null +++ b/libs/material3-navigation/README.md @@ -0,0 +1,7 @@ +## A local fork of the material-navigation functionality from androidx.material + +This library provides a navigation solution for Compose projects using Material3 BottomSheets. +It allows you to define your BottomSheet as navigation routes, +eliminating the need for the androidx.compose.material.navigation and androidx.compose.material:material ! libraries. +This simplifies your app's dependencies and ensures a consistent Material3 experience. +This library also leverages the new functionality from androidx.navigation:navigation-compose:2.8.0-beta0X to allow you to define routes with serialized classes. \ No newline at end of file diff --git a/libs/material3-navigation/build.gradle.kts b/libs/material3-navigation/build.gradle.kts new file mode 100644 index 000000000..16f46693a --- /dev/null +++ b/libs/material3-navigation/build.gradle.kts @@ -0,0 +1,24 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) +} + +android { + namespace = "com.mifos.library.material3.navigation" +} + +dependencies { + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.compose.ui.util) +} diff --git a/libs/material3-navigation/src/main/AndroidManifest.xml b/libs/material3-navigation/src/main/AndroidManifest.xml new file mode 100644 index 000000000..367affcc3 --- /dev/null +++ b/libs/material3-navigation/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheet.kt b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheet.kt new file mode 100644 index 000000000..27389dac3 --- /dev/null +++ b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheet.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.material3.navigation + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.BottomSheetDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp + +/** + * Helper function to create a [ModalBottomSheetLayout] from a [BottomSheetNavigator]. + * + * @see [ModalBottomSheetLayout] + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +public fun ModalBottomSheetLayout( + bottomSheetNavigator: BottomSheetNavigator, + modifier: Modifier = Modifier, + sheetMaxWidth: Dp = BottomSheetDefaults.SheetMaxWidth, + shape: Shape = BottomSheetDefaults.ExpandedShape, + containerColor: Color = BottomSheetDefaults.ContainerColor, + contentColor: Color = contentColorFor(containerColor), + tonalElevation: Dp = BottomSheetDefaults.Elevation, + scrimColor: Color = BottomSheetDefaults.ScrimColor, + dragHandle: @Composable (() -> Unit)? = { BottomSheetDefaults.DragHandle() }, + content: @Composable () -> Unit, +) { + Column(modifier = modifier) { + bottomSheetNavigator.sheetInitializer() + content() + } + + if (bottomSheetNavigator.sheetEnabled) { + ModalBottomSheet( + onDismissRequest = bottomSheetNavigator.onDismissRequest, + sheetState = bottomSheetNavigator.sheetState, + content = bottomSheetNavigator.sheetContent, + sheetMaxWidth = sheetMaxWidth, + shape = shape, + containerColor = containerColor, + contentColor = contentColor, + tonalElevation = tonalElevation, + scrimColor = scrimColor, + dragHandle = dragHandle, + ) + } +} diff --git a/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigator.kt b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigator.kt new file mode 100644 index 000000000..6bd0d056f --- /dev/null +++ b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigator.kt @@ -0,0 +1,286 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +@file:OptIn(ExperimentalMaterial3Api::class) +@file:Suppress("ktlint:standard:discouraged-comment-location") + +package com.mifos.library.material3.navigation + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.SheetState +import androidx.compose.material3.SheetValue +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.util.fastForEach +import androidx.navigation.FloatingWindow +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavDestination +import androidx.navigation.NavOptions +import androidx.navigation.Navigator +import androidx.navigation.NavigatorState +import androidx.navigation.compose.LocalOwnersProvider +import com.mifos.library.material3.navigation.BottomSheetNavigator.Destination +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.transform +import kotlinx.coroutines.launch + +/** + * The state of a [ModalBottomSheetLayout] that the [BottomSheetNavigator] drives + * + * @param sheetState The sheet state that is driven by the [BottomSheetNavigator] + */ +public class BottomSheetNavigatorSheetState(private val sheetState: SheetState) { + /** + * @see SheetState.isVisible + */ + public val isVisible: Boolean + get() = sheetState.isVisible + + /** + * @see SheetState.currentValue + */ + public val currentValue: SheetValue + get() = sheetState.currentValue + + /** + * @see SheetState.targetValue + */ + public val targetValue: SheetValue + get() = sheetState.targetValue +} + +/** + * Create and remember a [BottomSheetNavigator] + */ +@Composable +public fun rememberBottomSheetNavigator( + skipPartiallyExpanded: Boolean = false, +): BottomSheetNavigator { + val sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = skipPartiallyExpanded, + ) + + return remember(sheetState) { BottomSheetNavigator(sheetState) } +} + +/** + * Navigator that drives a [ModalBottomSheetState] for use of [ModalBottomSheetLayout]s + * with the navigation library. Every destination using this Navigator must set a valid + * [Composable] by setting it directly on an instantiated [Destination] or calling + * [navigation.bottomSheet]. + * + * The [sheetInitializer] [Composable] will always host the latest entry of the back stack. When + * navigating from a [BottomSheetNavigator.Destination] to another + * [BottomSheetNavigator.Destination], the content of the sheet will be replaced instead of a + * new bottom sheet being shown. + * + * When the sheet is dismissed by the user, the [state]'s [NavigatorState.backStack] will be popped. + * + * The primary constructor is not intended for public use. Please refer to + * [rememberBottomSheetNavigator] instead. + * + * @param sheetState The [ModalBottomSheetState] that the [BottomSheetNavigator] will use to + * drive the sheet state + */ +@Navigator.Name("bottomSheet") +public class BottomSheetNavigator( + internal val sheetState: SheetState, +) : Navigator() { + + internal var sheetEnabled by mutableStateOf(false) + private set + + private var attached by mutableStateOf(false) + + /** + * Get the back stack from the [state]. In some cases, the [sheetInitializer] might be composed + * before the Navigator is attached, so we specifically return an empty flow if we aren't + * attached yet. + */ + private val backStack: StateFlow> + get() = if (attached) { + state.backStack + } else { + MutableStateFlow(emptyList()) + } + + /** + * Get the transitionsInProgress from the [state]. In some cases, the [sheetInitializer] might be + * composed before the Navigator is attached, so we specifically return an empty flow if we + * aren't attached yet. + */ + private val transitionsInProgress: StateFlow> + get() = if (attached) { + state.transitionsInProgress + } else { + MutableStateFlow(emptySet()) + } + + /** + * Access properties of the [ModalBottomSheetLayout]'s [ModalBottomSheetState] + */ + public val navigatorSheetState: BottomSheetNavigatorSheetState = + BottomSheetNavigatorSheetState(sheetState) + + /** + * A [Composable] function that hosts the current sheet content. This should be set as + * sheetContent of your [ModalBottomSheetLayout]. + */ + + internal var sheetContent: @Composable ColumnScope.() -> Unit = {} + internal var onDismissRequest: () -> Unit = {} + + private var animateToDismiss: () -> Unit = {} + + /** + * The [Composable] that initializes the sheet. This should be composed in the same + * [Composable] that hosts the [ModalBottomSheetLayout]. + */ + internal val sheetInitializer: @Composable () -> Unit = { + val saveableStateHolder = rememberSaveableStateHolder() + val transitionsInProgressEntries by transitionsInProgress.collectAsState() + + // The latest back stack entry, retained until the sheet is completely hidden + // While the back stack is updated immediately, we might still be hiding the sheet, so + // we keep the entry around until the sheet is hidden + val retainedEntry by produceState( + initialValue = null, + key1 = backStack, + ) { + backStack + .transform { backStackEntries -> + // Always hide the sheet when the back stack is updated + // Regardless of whether we're popping or pushing, we always want to hide + // the sheet first before deciding whether to re-show it or keep it hidden + try { + sheetEnabled = false + } catch (_: CancellationException) { + // We catch but ignore possible cancellation exceptions as we don't want + // them to bubble up and cancel the whole produceState coroutine + } finally { + emit(backStackEntries.lastOrNull()) + } + } + .collect { + value = it + } + } + + if (retainedEntry != null) { + val currentOnSheetShown by rememberUpdatedState { + transitionsInProgressEntries.forEach(state::markTransitionComplete) + } + LaunchedEffect(sheetState, retainedEntry) { + snapshotFlow { sheetState.isVisible } + // We are only interested in changes in the sheet's visibility + .distinctUntilChanged() + // distinctUntilChanged emits the initial value which we don't need + .drop(1) + .collect { visible -> + if (visible) { + currentOnSheetShown() + } + } + } + + val scope = rememberCoroutineScope() + + LaunchedEffect(key1 = retainedEntry) { + sheetEnabled = true + + sheetContent = { + retainedEntry!!.LocalOwnersProvider(saveableStateHolder) { + val content = + (retainedEntry!!.destination as Destination).content + content(retainedEntry!!) + } + } + onDismissRequest = { + sheetEnabled = false + + // Sheet dismissal can be started through popBackStack in which case we have a + // transition that we'll want to complete + if (transitionsInProgressEntries.contains(retainedEntry)) { + state.markTransitionComplete(retainedEntry!!) + } + // If there is no transition in progress, the sheet has been dimissed by the + // user (for example by tapping on the scrim or through an accessibility action) + // In this case, we will immediately pop without a transition as the sheet has + // already been hidden + else { + state.pop(popUpTo = retainedEntry!!, saveState = false) + } + } + + animateToDismiss = { + scope + .launch { sheetState.hide() } + .invokeOnCompletion { + onDismissRequest() + } + } + } + } else { + LaunchedEffect(key1 = Unit) { + sheetContent = {} + onDismissRequest = {} + animateToDismiss = {} + } + } + } + + override fun onAttach(state: NavigatorState) { + super.onAttach(state) + attached = true + } + + override fun createDestination(): Destination = Destination( + navigator = this, + content = {}, + ) + + override fun navigate( + entries: List, + navOptions: NavOptions?, + navigatorExtras: Extras?, + ) { + entries.fastForEach { entry -> + state.push(entry) + } + } + + override fun popBackStack(popUpTo: NavBackStackEntry, savedState: Boolean) { + animateToDismiss() + } + + /** + * [NavDestination] specific to [BottomSheetNavigator] + */ + @NavDestination.ClassType(Composable::class) + public class Destination( + navigator: BottomSheetNavigator, + internal val content: @Composable ColumnScope.(NavBackStackEntry) -> Unit, + ) : NavDestination(navigator), FloatingWindow +} diff --git a/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigatorDestinationBuilder.kt b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigatorDestinationBuilder.kt new file mode 100644 index 000000000..33b3e74ee --- /dev/null +++ b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/BottomSheetNavigatorDestinationBuilder.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.material3.navigation + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.runtime.Composable +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavDestinationBuilder +import androidx.navigation.NavDestinationDsl +import androidx.navigation.NavType +import androidx.navigation.compose.ComposeNavigator +import kotlin.reflect.KClass +import kotlin.reflect.KType + +/** DSL for constructing a new [ComposeNavigator.Destination] */ +@NavDestinationDsl +class BottomSheetNavigatorDestinationBuilder : + NavDestinationBuilder { + + private val composeNavigator: BottomSheetNavigator + private val content: @Composable ColumnScope.(NavBackStackEntry) -> Unit + + constructor( + navigator: BottomSheetNavigator, + route: String, + content: @Composable ColumnScope.(NavBackStackEntry) -> Unit, + ) : super(navigator, route) { + this.composeNavigator = navigator + this.content = content + } + + constructor( + navigator: BottomSheetNavigator, + route: KClass<*>, + typeMap: Map>, + content: @Composable ColumnScope.(NavBackStackEntry) -> Unit, + ) : super(navigator, route, typeMap) { + this.composeNavigator = navigator + this.content = content + } + + override fun instantiateDestination(): BottomSheetNavigator.Destination { + return BottomSheetNavigator.Destination(composeNavigator, content) + } + + override fun build(): BottomSheetNavigator.Destination { + return super.build() + } +} diff --git a/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/NavGraphBuilder.kt b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/NavGraphBuilder.kt new file mode 100644 index 000000000..5793a19dd --- /dev/null +++ b/libs/material3-navigation/src/main/kotlin/com/mifos/library/material3/navigation/NavGraphBuilder.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package com.mifos.library.material3.navigation + +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.runtime.Composable +import androidx.compose.ui.util.fastForEach +import androidx.navigation.NamedNavArgument +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavDeepLink +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavType +import androidx.navigation.get +import kotlin.reflect.KType + +/** + * Add the [content] [Composable] as bottom sheet content to the [NavGraphBuilder] + * + * @param route route for the destination + * @param arguments list of arguments to associate with destination + * @param deepLinks list of deep links to associate with the destinations + * @param content the sheet content at the given destination + */ +fun NavGraphBuilder.bottomSheet( + route: String, + arguments: List = emptyList(), + deepLinks: List = emptyList(), + content: @Composable ColumnScope.(backstackEntry: NavBackStackEntry) -> Unit, +) { + addDestination( + BottomSheetNavigator.Destination( + provider[BottomSheetNavigator::class], + content, + ).apply { + this.route = route + arguments.fastForEach { (argumentName, argument) -> + addArgument(argumentName, argument) + } + deepLinks.fastForEach { deepLink -> + addDeepLink(deepLink) + } + }, + ) +} + +inline fun NavGraphBuilder.bottomSheet( + deepLinks: List = emptyList(), + typeMap: Map> = emptyMap(), + noinline content: @Composable ColumnScope.(backstackEntry: NavBackStackEntry) -> Unit, +) { + destination( + BottomSheetNavigatorDestinationBuilder( + provider[BottomSheetNavigator::class], + T::class, + typeMap, + content, + ) + .apply { + deepLinks.forEach { deepLink -> deepLink(deepLink) } + }, + ) +} diff --git a/libs/mifos-passcode/.gitignore b/libs/mifos-passcode/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/libs/mifos-passcode/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/libs/mifos-passcode/README.md b/libs/mifos-passcode/README.md new file mode 100644 index 000000000..2a35a94b0 --- /dev/null +++ b/libs/mifos-passcode/README.md @@ -0,0 +1,3 @@ +# :feature:passcode module +## Dependency graph +![Dependency graph](../../docs/images/graphs/dep_graph_feature_passcode.svg) diff --git a/libs/mifos-passcode/build.gradle.kts b/libs/mifos-passcode/build.gradle.kts new file mode 100644 index 000000000..324c50300 --- /dev/null +++ b/libs/mifos-passcode/build.gradle.kts @@ -0,0 +1,35 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) + alias(libs.plugins.mifos.android.hilt) +} + +android { + namespace = "com.mifos.library.passcode" +} + +dependencies { + implementation(libs.androidx.core.ktx) + + implementation(libs.androidx.compose.foundation) + implementation(libs.androidx.compose.foundation.layout) + implementation(libs.androidx.compose.material.iconsExtended) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.compose.ui.util) + + implementation(libs.androidx.lifecycle.runtimeCompose) + implementation(libs.androidx.lifecycle.viewModelCompose) + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.hilt.navigation.compose) + +} diff --git a/libs/mifos-passcode/src/main/AndroidManifest.xml b/libs/mifos-passcode/src/main/AndroidManifest.xml new file mode 100644 index 000000000..b9b046d65 --- /dev/null +++ b/libs/mifos-passcode/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PassCodeScreen.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PassCodeScreen.kt new file mode 100644 index 000000000..c20e54ad4 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PassCodeScreen.kt @@ -0,0 +1,242 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.Animatable +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifos.library.passcode.component.MifosIcon +import org.mifos.library.passcode.component.PasscodeForgotButton +import org.mifos.library.passcode.component.PasscodeHeader +import org.mifos.library.passcode.component.PasscodeKeys +import org.mifos.library.passcode.component.PasscodeMismatchedDialog +import org.mifos.library.passcode.component.PasscodeSkipButton +import org.mifos.library.passcode.component.PasscodeToolbar +import org.mifos.library.passcode.theme.blueTint +import org.mifos.library.passcode.utility.Constants.PASSCODE_LENGTH +import org.mifos.library.passcode.utility.PreferenceManager +import org.mifos.library.passcode.utility.ShakeAnimation.performShakeAnimation +import org.mifos.library.passcode.utility.VibrationFeedback.vibrateFeedback +import org.mifos.library.passcode.viewmodels.PasscodeViewModel + +@Composable +internal fun PasscodeScreen( + onForgotButton: () -> Unit, + onSkipButton: () -> Unit, + onPasscodeConfirm: (String) -> Unit, + onPasscodeRejected: () -> Unit, + modifier: Modifier = Modifier, + viewModel: PasscodeViewModel = hiltViewModel(), +) { + val context = LocalContext.current + val preferenceManager = remember { PreferenceManager(context) } + + val activeStep by viewModel.activeStep.collectAsStateWithLifecycle() + val filledDots by viewModel.filledDots.collectAsStateWithLifecycle() + val passcodeVisible by viewModel.passcodeVisible.collectAsStateWithLifecycle() + val currentPasscode by viewModel.currentPasscodeInput.collectAsStateWithLifecycle() + + val xShake = remember { Animatable(initialValue = 0.0F) } + var passcodeRejectedDialogVisible by remember { mutableStateOf(false) } + + LaunchedEffect(key1 = viewModel.onPasscodeConfirmed) { + viewModel.onPasscodeConfirmed.collect { + onPasscodeConfirm(it) + } + } + + LaunchedEffect(key1 = viewModel.onPasscodeRejected) { + viewModel.onPasscodeRejected.collect { + passcodeRejectedDialogVisible = true + vibrateFeedback(context) + performShakeAnimation(xShake) + onPasscodeRejected() + } + } + + Scaffold( + modifier = modifier + .fillMaxSize(), + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(paddingValues), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + PasscodeToolbar(activeStep = activeStep, preferenceManager.hasPasscode) + + PasscodeSkipButton( + hasPassCode = preferenceManager.hasPasscode, + onSkipButton = onSkipButton, + ) + + MifosIcon(modifier = Modifier.fillMaxWidth()) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp, bottom = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + PasscodeHeader( + activeStep = activeStep, + isPasscodeAlreadySet = preferenceManager.hasPasscode, + ) + PasscodeView( + restart = { viewModel.restart() }, + togglePasscodeVisibility = { viewModel.togglePasscodeVisibility() }, + filledDots = filledDots, + passcodeVisible = passcodeVisible, + currentPasscode = currentPasscode, + passcodeRejectedDialogVisible = passcodeRejectedDialogVisible, + onDismissDialog = { passcodeRejectedDialogVisible = false }, + xShake = xShake, + ) + } + + Spacer(modifier = Modifier.height(6.dp)) + + PasscodeKeys( + enterKey = viewModel::enterKey, + deleteKey = viewModel::deleteKey, + deleteAllKeys = viewModel::deleteAllKeys, + modifier = Modifier.padding(horizontal = 12.dp), + ) + + Spacer(modifier = Modifier.height(8.dp)) + + PasscodeForgotButton( + hasPassCode = preferenceManager.hasPasscode, + onForgotButton = onForgotButton, + ) + } + } +} + +@Composable +private fun PasscodeView( + restart: () -> Unit, + togglePasscodeVisibility: () -> Unit, + filledDots: Int, + passcodeVisible: Boolean, + currentPasscode: String, + passcodeRejectedDialogVisible: Boolean, + onDismissDialog: () -> Unit, + xShake: Animatable, + modifier: Modifier = Modifier, +) { + PasscodeMismatchedDialog( + visible = passcodeRejectedDialogVisible, + onDismiss = { + onDismissDialog.invoke() + restart() + }, + ) + + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + modifier = Modifier.offset { IntOffset(xShake.value.toInt(), 0) }, + horizontalArrangement = Arrangement.spacedBy( + space = 26.dp, + alignment = Alignment.CenterHorizontally, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + repeat(PASSCODE_LENGTH) { dotIndex -> + if (passcodeVisible && dotIndex < currentPasscode.length) { + Text( + text = currentPasscode[dotIndex].toString(), + color = blueTint, + ) + } else { + val isFilledDot = dotIndex + 1 <= filledDots + val dotColor = animateColorAsState( + if (isFilledDot) blueTint else Color.Gray, + label = "", + ) + + Box( + modifier = Modifier + .size(14.dp) + .background( + color = dotColor.value, + shape = CircleShape, + ), + ) + } + } + } + + IconButton( + onClick = togglePasscodeVisibility, + modifier = Modifier.padding(start = 10.dp), + ) { + Icon( + imageVector = if (passcodeVisible) { + Icons.Filled.Visibility + } else { + Icons.Filled.VisibilityOff + }, + contentDescription = null, + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun PasscodeScreenPreview() { + PasscodeScreen( + onForgotButton = {}, + onSkipButton = {}, + onPasscodeConfirm = {}, + onPasscodeRejected = {}, + ) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PasscodeNavigation.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PasscodeNavigation.kt new file mode 100644 index 000000000..eab00eefd --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/PasscodeNavigation.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable + +const val PASSCODE_SCREEN = "passcode_screen" + +fun NavGraphBuilder.passcodeRoute( + onForgotButton: () -> Unit, + onSkipButton: () -> Unit, + onPasscodeConfirm: (String) -> Unit, + onPasscodeRejected: () -> Unit, +) { + composable( + route = PASSCODE_SCREEN, + ) { + PasscodeScreen( + onForgotButton = onForgotButton, + onSkipButton = onSkipButton, + onPasscodeConfirm = onPasscodeConfirm, + onPasscodeRejected = onPasscodeRejected, + ) + } +} + +fun NavController.navigateToPasscodeScreen(options: NavOptions? = null) { + navigate(PASSCODE_SCREEN, options) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/MifosIcon.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/MifosIcon.kt new file mode 100644 index 000000000..5b5e8b778 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/MifosIcon.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.mifos.library.passcode.R + +@Composable +internal fun MifosIcon(modifier: Modifier = Modifier) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.Center, + ) { + Image( + modifier = Modifier.size(180.dp), + painter = painterResource(id = R.drawable.lib_mifos_passcode_mifos_logo), + contentDescription = null, + ) + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeButton.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeButton.kt new file mode 100644 index 000000000..f1b4d31ac --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeButton.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.mifos.library.passcode.R +import org.mifos.library.passcode.theme.forgotButtonStyle +import org.mifos.library.passcode.theme.skipButtonStyle + +@Composable +internal fun PasscodeSkipButton( + hasPassCode: Boolean, + onSkipButton: () -> Unit, + modifier: Modifier = Modifier, +) { + if (!hasPassCode) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.End, + ) { + TextButton( + onClick = { onSkipButton.invoke() }, + ) { + Text(text = stringResource(R.string.library_mifos_passcode_skip), style = skipButtonStyle) + } + } + } +} + +@Composable +internal fun PasscodeForgotButton( + hasPassCode: Boolean, + onForgotButton: () -> Unit, + modifier: Modifier = Modifier, +) { + if (hasPassCode) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.Center, + ) { + TextButton( + onClick = { onForgotButton.invoke() }, + ) { + Text( + text = stringResource(R.string.library_mifos_passcode_login_manually), + style = forgotButtonStyle, + ) + } + } + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeHeader.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeHeader.kt new file mode 100644 index 000000000..1a08a37a9 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeHeader.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.Transition +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.animateOffset +import androidx.compose.animation.core.rememberTransition +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.scale +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.mifos.library.passcode.R +import org.mifos.library.passcode.utility.Step + +@Composable +internal fun PasscodeHeader( + activeStep: Step, + isPasscodeAlreadySet: Boolean, + modifier: Modifier = Modifier, +) { + val transitionState = remember { MutableTransitionState(activeStep) } + transitionState.targetState = activeStep + + val transition: Transition = rememberTransition( + transitionState = transitionState, + label = "Headers Transition", + ) + + val offset = 200.0F + val zeroOffset = Offset(x = 0.0F, y = 0.0F) + val negativeOffset = Offset(x = -offset, y = 0.0F) + val positiveOffset = Offset(x = offset, y = 0.0F) + + val xTransitionHeader1 by transition.animateOffset(label = "Transition Offset Header 1") { + if (it == Step.Create) zeroOffset else negativeOffset + } + val xTransitionHeader2 by transition.animateOffset(label = "Transition Offset Header 2") { + if (it == Step.Confirm) zeroOffset else positiveOffset + } + val alphaHeader1 by transition.animateFloat(label = "Transition Alpha Header 1") { + if (it == Step.Create) 1.0F else 0.0F + } + val alphaHeader2 by transition.animateFloat(label = "Transition Alpha Header 2") { + if (it == Step.Confirm) 1.0F else 0.0F + } + val scaleHeader1 by transition.animateFloat(label = "Transition Alpha Header 1") { + if (it == Step.Create) 1.0F else 0.5F + } + val scaleHeader2 by transition.animateFloat(label = "Transition Alpha Header 2") { + if (it == Step.Confirm) 1.0F else 0.5F + } + + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + if (isPasscodeAlreadySet) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader1.x.dp) + .alpha(alpha = alphaHeader1) + .scale(scale = scaleHeader1), + text = stringResource(id = R.string.library_mifos_passcode_enter_your_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } else { + if (activeStep == Step.Create) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader1.x.dp) + .alpha(alpha = alphaHeader1) + .scale(scale = scaleHeader1), + text = stringResource(id = R.string.library_mifos_passcode_create_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } else if (activeStep == Step.Confirm) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader2.x.dp) + .alpha(alpha = alphaHeader2) + .scale(scale = scaleHeader2), + text = stringResource(id = R.string.library_mifos_passcode_confirm_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } + } + } + } +} + +@Preview +@Composable +private fun PasscodeHeaderPreview() { + PasscodeHeader(activeStep = Step.Create, isPasscodeAlreadySet = true) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeKeys.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeKeys.kt new file mode 100644 index 000000000..abaf8c3e3 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeKeys.kt @@ -0,0 +1,198 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +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.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.Backspace +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.mifos.library.passcode.R +import org.mifos.library.passcode.theme.PasscodeKeyButtonStyle +import org.mifos.library.passcode.theme.blueTint + +@Composable +internal fun PasscodeKeys( + enterKey: (String) -> Unit, + deleteKey: () -> Unit, + deleteAllKeys: () -> Unit, + modifier: Modifier = Modifier, +) { + val onEnterKeyClick = { keyTitle: String -> + enterKey(keyTitle) + } + Column( + modifier = modifier + .fillMaxWidth() + .padding(16.dp), + ) { + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "1", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "2", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "3", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "4", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "5", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "6", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "7", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "8", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "9", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey(modifier = Modifier.weight(weight = 1.0F)) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "0", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyIcon = ImageVector.vectorResource(id = R.drawable.lib_mifos_passcode_ic_delete), + keyIconContentDescription = "Delete Passcode Key Button", + onClick = { + deleteKey() + }, + onLongClick = { + deleteAllKeys() + }, + ) + } + } +} + +@Composable +internal fun PasscodeKey( + modifier: Modifier = Modifier, + keyTitle: String = "", + keyIcon: ImageVector? = null, + keyIconContentDescription: String = "", + onClick: ((String) -> Unit)? = null, + onLongClick: (() -> Unit)? = null, +) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.Center, + ) { + CombinedClickableIconButton( + onClick = { + onClick?.invoke(keyTitle) + }, + onLongClick = { + onLongClick?.invoke() + }, + modifier = Modifier + .padding(all = 4.dp), + ) { + if (keyIcon == null) { + Text( + text = keyTitle, + style = PasscodeKeyButtonStyle.copy(color = blueTint), + ) + } else { + Icon( + imageVector = Icons.AutoMirrored.Filled.Backspace, + contentDescription = keyIconContentDescription, + tint = blueTint, + ) + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +internal fun CombinedClickableIconButton( + onClick: () -> Unit, + onLongClick: () -> Unit, + modifier: Modifier = Modifier, + size: Dp = 48.dp, + enabled: Boolean = true, + content: @Composable () -> Unit, +) { + Column( + modifier = modifier + .size(size = size) + .combinedClickable( + onClick = onClick, + onLongClick = onLongClick, + enabled = enabled, + role = Role.Button, + ), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val contentAlpha = + if (enabled) LocalContentColor.current else LocalContentColor.current.copy(alpha = 0f) + CompositionLocalProvider(LocalContentColor provides contentAlpha, content = content) + } +} + +@Preview +@Composable +private fun PasscodeKeysPreview() { + PasscodeKeys({}, {}, {}) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeMismatchedDialog.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeMismatchedDialog.kt new file mode 100644 index 000000000..228221117 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeMismatchedDialog.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import com.mifos.library.passcode.R + +@Composable +internal fun PasscodeMismatchedDialog( + visible: Boolean, + onDismiss: () -> Unit, +) { + if (visible) { + AlertDialog( + shape = MaterialTheme.shapes.large, + containerColor = Color.White, + title = { + Text( + text = stringResource(R.string.library_mifos_passcode_do_not_match), + color = Color.Black, + ) + }, + confirmButton = { + TextButton(onClick = onDismiss) { + Text( + text = stringResource(R.string.library_mifos_passcode_try_again), + color = Color.Black, + ) + } + }, + onDismissRequest = onDismiss, + ) + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeStepIndicator.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeStepIndicator.kt new file mode 100644 index 000000000..43d582a7f --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeStepIndicator.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import org.mifos.library.passcode.theme.blueTint +import org.mifos.library.passcode.utility.Constants.STEPS_COUNT +import org.mifos.library.passcode.utility.Step + +@Composable +internal fun PasscodeStepIndicator( + activeStep: Step, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy( + space = 6.dp, + alignment = Alignment.CenterHorizontally, + ), + ) { + repeat(STEPS_COUNT) { step -> + val isActiveStep = step <= activeStep.index + val stepColor = + animateColorAsState(if (isActiveStep) blueTint else Color.Gray, label = "") + + Box( + modifier = Modifier + .size( + width = 72.dp, + height = 4.dp, + ) + .background( + color = stepColor.value, + shape = MaterialTheme.shapes.medium, + ), + ) + } + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeToolbar.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeToolbar.kt new file mode 100644 index 000000000..fc5bda091 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/component/PasscodeToolbar.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.component + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.mifos.library.passcode.R +import org.mifos.library.passcode.utility.Step + +@Composable +internal fun PasscodeToolbar( + activeStep: Step, + hasPasscode: Boolean, + modifier: Modifier = Modifier, +) { + var exitWarningDialogVisible by remember { mutableStateOf(false) } + + AnimatedVisibility(exitWarningDialogVisible) { + ExitWarningDialog( + visible = exitWarningDialogVisible, + onConfirm = {}, + onDismiss = { + exitWarningDialogVisible = false + }, + ) + } + + Row( + modifier = modifier + .fillMaxWidth() + .padding(top = 8.dp), + horizontalArrangement = Arrangement.Center, + ) { + if (!hasPasscode) { + PasscodeStepIndicator( + activeStep = activeStep, + ) + } + } +} + +@Composable +private fun ExitWarningDialog( + visible: Boolean, + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + if (visible) { + AlertDialog( + shape = MaterialTheme.shapes.large, + containerColor = Color.White, + title = { + Text( + text = stringResource(R.string.library_mifos_passcode_exit_message), + color = Color.Black, + ) + }, + confirmButton = { + TextButton(onClick = onConfirm) { + Text(text = stringResource(R.string.library_mifos_passcode_exit)) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(text = stringResource(R.string.lib_mifos_passcode_cancel)) + } + }, + onDismissRequest = onDismiss, + ) + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeManager.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeManager.kt new file mode 100644 index 000000000..f2436f02d --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeManager.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.data + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import org.mifos.library.passcode.utility.PreferenceManager +import javax.inject.Inject + +class PasscodeManager @Inject constructor( + @ApplicationContext + private val context: Context, +) { + private val passcodePreferencesHelper = PreferenceManager(context) + + val getPasscode = passcodePreferencesHelper.getSavedPasscode() + + val hasPasscode = passcodePreferencesHelper.hasPasscode + + fun savePasscode(passcode: String) { + passcodePreferencesHelper.savePasscode(passcode) + } + + fun clearPasscode() { + passcodePreferencesHelper.clearPasscode() + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepository.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepository.kt new file mode 100644 index 000000000..4311e6ade --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepository.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.data + +interface PasscodeRepository { + val hasPasscode: Boolean + + fun getSavedPasscode(): String + + fun savePasscode(passcode: String) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepositoryImpl.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepositoryImpl.kt new file mode 100644 index 000000000..8f4cbd863 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/data/PasscodeRepositoryImpl.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.data + +import org.mifos.library.passcode.utility.PreferenceManager +import javax.inject.Inject + +class PasscodeRepositoryImpl @Inject constructor( + private val preferenceManager: PreferenceManager, +) : PasscodeRepository { + + override val hasPasscode: Boolean + get() = preferenceManager.hasPasscode + + override fun getSavedPasscode(): String { + return preferenceManager.getSavedPasscode() + } + + override fun savePasscode(passcode: String) { + preferenceManager.savePasscode(passcode) + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/di/ApplicationModule.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/di/ApplicationModule.kt new file mode 100644 index 000000000..c5a5e821d --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/di/ApplicationModule.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.di + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import org.mifos.library.passcode.data.PasscodeRepository +import org.mifos.library.passcode.data.PasscodeRepositoryImpl +import org.mifos.library.passcode.utility.PreferenceManager +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object ApplicationModule { + @Provides + @Singleton + fun providePrefManager(@ApplicationContext context: Context): PreferenceManager { + return PreferenceManager(context) + } + + @Provides + @Singleton + fun providesPasscodeRepository(preferenceManager: PreferenceManager): PasscodeRepository { + return PasscodeRepositoryImpl(preferenceManager) + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Color.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Color.kt new file mode 100644 index 000000000..87e379858 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Color.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.theme + +import androidx.compose.ui.graphics.Color + +internal val blueTint = Color(0xFF03A9F4) diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Font.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Font.kt new file mode 100644 index 000000000..e948eca0a --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Font.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.theme + +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import com.mifos.library.passcode.R + +internal val LatoFonts = FontFamily( + Font( + resId = R.font.lib_mifos_passcode_lato_regular, + weight = FontWeight.Normal, + style = FontStyle.Normal, + ), + Font( + resId = R.font.lib_mifos_passcode_lato_bold, + weight = FontWeight.Bold, + style = FontStyle.Normal, + ), + Font( + resId = R.font.lib_mifos_passcode_lato_black, + weight = FontWeight.Black, + style = FontStyle.Normal, + ), +) diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Theme.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Theme.kt new file mode 100644 index 000000000..121bfcbd3 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Theme.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Color.Companion.Blue + +private val DarkColorPalette = darkColorScheme( + primary = Color.Cyan, + onPrimary = Color.Cyan, + secondary = Color.Black.copy(alpha = 0.2f), + background = Color.Black, +) +private val LightColorPalette = lightColorScheme( + primary = Blue, + onPrimary = Blue, + secondary = Color.Blue.copy(alpha = 0.4f), + background = Color.White, +) + +@Composable +internal fun MifosPasscodeTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit, +) { + val colors = if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } + + MaterialTheme( + colorScheme = colors, + typography = Typography, + content = content, + ) +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Type.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Type.kt new file mode 100644 index 000000000..b1bdb5ecb --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/theme/Type.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +internal val Typography = Typography( + displayLarge = TextStyle( + fontFamily = LatoFonts, + fontWeight = FontWeight.Black, + fontSize = 34.sp, + ), +) + +internal val PasscodeKeyButtonStyle = TextStyle( + fontFamily = LatoFonts, + fontWeight = FontWeight.Bold, + fontSize = 24.sp, +) + +internal val skipButtonStyle = TextStyle( + color = blueTint, + fontSize = 20.sp, + fontFamily = LatoFonts, +) + +internal val forgotButtonStyle = TextStyle( + color = blueTint, + fontSize = 14.sp, + fontFamily = LatoFonts, +) diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Constants.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Constants.kt new file mode 100644 index 000000000..4cb95a4e5 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Constants.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.utility + +internal object Constants { + const val STEPS_COUNT = 2 + const val PASSCODE_LENGTH = 4 + const val VIBRATE_FEEDBACK_DURATION = 300L +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/PreferenceManager.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/PreferenceManager.kt new file mode 100644 index 000000000..89d729d92 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/PreferenceManager.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.utility + +import android.content.Context +import com.mifos.library.passcode.R + +class PreferenceManager(context: Context) { + private val sharedPreference = context.getSharedPreferences( + R.string.lib_mifos_passcode_pref_name.toString(), + Context.MODE_PRIVATE, + ) + + var hasPasscode: Boolean + get() = sharedPreference.getBoolean(R.string.lib_mifos_passcode_has_passcode.toString(), false) + set(value) = sharedPreference.edit().putBoolean(R.string.lib_mifos_passcode_has_passcode.toString(), value) + .apply() + + fun savePasscode(passcode: String) { + sharedPreference.edit().putString(R.string.lib_mifos_passcode.toString(), passcode).apply() + hasPasscode = true + } + + fun getSavedPasscode(): String { + return sharedPreference.getString(R.string.lib_mifos_passcode.toString(), "").toString() + } + + fun clearPasscode() { + sharedPreference.edit().clear().apply() + hasPasscode = false + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/ShakeAnimation.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/ShakeAnimation.kt new file mode 100644 index 000000000..88e75cf82 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/ShakeAnimation.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.utility + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.LinearOutSlowInEasing +import androidx.compose.animation.core.keyframes +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +internal object ShakeAnimation { + + fun CoroutineScope.performShakeAnimation(xShake: Animatable) { + launch { + xShake.animateTo( + targetValue = 0f, + animationSpec = keyframes { + durationMillis = 280 + 0f at 0 using LinearOutSlowInEasing + 20f at 80 using LinearOutSlowInEasing + 20f at 120 using LinearOutSlowInEasing + 10f at 160 using LinearOutSlowInEasing + 10f at 200 using LinearOutSlowInEasing + 5f at 240 using LinearOutSlowInEasing + 0f at 280 + }, + ) + } + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Step.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Step.kt new file mode 100644 index 000000000..e5782451a --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/Step.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.utility + +internal enum class Step(var index: Int) { + Create(0), + Confirm(1), +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/VibrationFeedback.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/VibrationFeedback.kt new file mode 100644 index 000000000..62ca18df1 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/utility/VibrationFeedback.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.utility + +import android.content.Context +import android.os.Build +import android.os.CombinedVibration +import android.os.VibrationEffect +import android.os.Vibrator +import android.os.VibratorManager +import org.mifos.library.passcode.utility.Constants.VIBRATE_FEEDBACK_DURATION + +internal object VibrationFeedback { + + @Suppress("DEPRECATION") + internal fun vibrateFeedback(context: Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + (context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager).vibrate( + CombinedVibration.createParallel( + VibrationEffect.createOneShot( + VIBRATE_FEEDBACK_DURATION, + VibrationEffect.DEFAULT_AMPLITUDE, + ), + ), + ) + } else { + (context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).let { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + it.vibrate( + VibrationEffect.createOneShot( + VIBRATE_FEEDBACK_DURATION, + VibrationEffect.DEFAULT_AMPLITUDE, + ), + ) + } else { + it.vibrate(VIBRATE_FEEDBACK_DURATION) + } + } + } + } +} diff --git a/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/viewmodels/PasscodeViewModel.kt b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/viewmodels/PasscodeViewModel.kt new file mode 100644 index 000000000..4842a5800 --- /dev/null +++ b/libs/mifos-passcode/src/main/kotlin/org/mifos/library/passcode/viewmodels/PasscodeViewModel.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.library.passcode.viewmodels + +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import org.mifos.library.passcode.data.PasscodeRepository +import org.mifos.library.passcode.utility.Constants.PASSCODE_LENGTH +import org.mifos.library.passcode.utility.Step +import javax.inject.Inject + +@HiltViewModel +internal class PasscodeViewModel @Inject constructor( + private val passcodeRepository: PasscodeRepository, +) : ViewModel() { + + private val mOnPasscodeConfirmed = MutableSharedFlow() + val onPasscodeConfirmed = mOnPasscodeConfirmed.asSharedFlow() + + private val mOnPasscodeRejected = MutableSharedFlow() + val onPasscodeRejected = mOnPasscodeRejected.asSharedFlow() + + private val mActiveStep = MutableStateFlow(Step.Create) + val activeStep = mActiveStep.asStateFlow() + + private val mFilledDots = MutableStateFlow(0) + val filledDots = mFilledDots.asStateFlow() + + private var createPasscode: StringBuilder = StringBuilder() + private var confirmPasscode: StringBuilder = StringBuilder() + + private val mPasscodeVisible = MutableStateFlow(false) + val passcodeVisible = mPasscodeVisible.asStateFlow() + + private val mCurrentPasscodeInput = MutableStateFlow("") + val currentPasscodeInput = mCurrentPasscodeInput.asStateFlow() + + private var mIsPasscodeAlreadySet = mutableStateOf(passcodeRepository.hasPasscode) + + init { + resetData() + } + + private fun emitActiveStep(activeStep: Step) = viewModelScope.launch { + mActiveStep.emit(activeStep) + } + + private fun emitFilledDots(filledDots: Int) = viewModelScope.launch { + mFilledDots.emit(filledDots) + } + + private fun emitOnPasscodeConfirmed(confirmPassword: String) = viewModelScope.launch { + mOnPasscodeConfirmed.emit(confirmPassword) + } + + private fun emitOnPasscodeRejected() = viewModelScope.launch { + mOnPasscodeRejected.emit(Unit) + } + + fun togglePasscodeVisibility() { + mPasscodeVisible.value = !mPasscodeVisible.value + } + + private fun resetData() { + emitActiveStep(Step.Create) + emitFilledDots(0) + + createPasscode.clear() + confirmPasscode.clear() + } + + fun enterKey(key: String) { + if (mFilledDots.value >= PASSCODE_LENGTH) { + return + } + + val currentPasscode = + if (mActiveStep.value == Step.Create) createPasscode else confirmPasscode + currentPasscode.append(key) + mCurrentPasscodeInput.value = currentPasscode.toString() + emitFilledDots(currentPasscode.length) + + if (mFilledDots.value == PASSCODE_LENGTH) { + if (mIsPasscodeAlreadySet.value) { + if (passcodeRepository.getSavedPasscode() == createPasscode.toString()) { + emitOnPasscodeConfirmed(createPasscode.toString()) + createPasscode.clear() + } else { + emitOnPasscodeRejected() + // logic for retires can be written here + } + mCurrentPasscodeInput.value = "" + } else if (mActiveStep.value == Step.Create) { + emitActiveStep(Step.Confirm) + emitFilledDots(0) + mCurrentPasscodeInput.value = "" + } else { + if (createPasscode.toString() == confirmPasscode.toString()) { + emitOnPasscodeConfirmed(confirmPasscode.toString()) + passcodeRepository.savePasscode(confirmPasscode.toString()) + mIsPasscodeAlreadySet.value = true + resetData() + } else { + emitOnPasscodeRejected() + resetData() + } + mCurrentPasscodeInput.value = "" + } + } + } + + fun deleteKey() { + val currentPasscode = + if (mActiveStep.value == Step.Create) createPasscode else confirmPasscode + + if (currentPasscode.isNotEmpty()) { + currentPasscode.deleteAt(currentPasscode.length - 1) + mCurrentPasscodeInput.value = currentPasscode.toString() + emitFilledDots(currentPasscode.length) + } + } + + fun deleteAllKeys() { + if (mActiveStep.value == Step.Create) { + createPasscode.clear() + } else { + confirmPasscode.clear() + } + mCurrentPasscodeInput.value = "" + emitFilledDots(0) + } + + fun restart() { + resetData() + mPasscodeVisible.value = false + } +} diff --git a/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_delete_forever.xml b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_delete_forever.xml new file mode 100644 index 000000000..cc0810db2 --- /dev/null +++ b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_delete_forever.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_ic_delete.xml b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_ic_delete.xml new file mode 100644 index 000000000..a10936ea0 --- /dev/null +++ b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_ic_delete.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_mifos_logo.jpg b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_mifos_logo.jpg new file mode 100644 index 000000000..a067a3c8e Binary files /dev/null and b/libs/mifos-passcode/src/main/res/drawable/lib_mifos_passcode_mifos_logo.jpg differ diff --git a/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_black.ttf b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_black.ttf new file mode 100644 index 000000000..4340502d9 Binary files /dev/null and b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_black.ttf differ diff --git a/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_bold.ttf b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_bold.ttf new file mode 100644 index 000000000..016068b48 Binary files /dev/null and b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_bold.ttf differ diff --git a/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_regular.ttf b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_regular.ttf new file mode 100644 index 000000000..bb2e8875a Binary files /dev/null and b/libs/mifos-passcode/src/main/res/font/lib_mifos_passcode_lato_regular.ttf differ diff --git a/libs/mifos-passcode/src/main/res/values/strings.xml b/libs/mifos-passcode/src/main/res/values/strings.xml new file mode 100644 index 000000000..439874801 --- /dev/null +++ b/libs/mifos-passcode/src/main/res/values/strings.xml @@ -0,0 +1,34 @@ + + + + Passcode will be reset, are you sure? + Cancel + Yes + Passcode + hasPasscode + hasDragPasscode + passcode + drag_passcode + + Create Passcode + Confirm Passcode + Enter your Passcode + Forgot Passcode + Delete Passcode Key Button + Drag your finger here only in one direction. + Drag your Pattern + Exit + Skip + Forgot Passcode, Login Manually + Try again + Passcode do not match! + Are you sure you want to exit? + \ No newline at end of file diff --git a/libs/pullrefresh/.gitignore b/libs/pullrefresh/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/libs/pullrefresh/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/libs/pullrefresh/README.md b/libs/pullrefresh/README.md new file mode 100644 index 000000000..62b86909d --- /dev/null +++ b/libs/pullrefresh/README.md @@ -0,0 +1,5 @@ +## A local fork of the pullrefresh functionality from androidx.material + +Source: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/src/commonMain/kotlin/androidx/compose/material/pullrefresh/ + +Forked so that we can make use of it while not bringing in m2 dependencies in our project unecessarily diff --git a/libs/pullrefresh/build.gradle.kts b/libs/pullrefresh/build.gradle.kts new file mode 100644 index 000000000..e7c69ca10 --- /dev/null +++ b/libs/pullrefresh/build.gradle.kts @@ -0,0 +1,24 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +plugins { + alias(libs.plugins.mifos.android.library) + alias(libs.plugins.mifos.android.library.compose) +} + +android { + namespace = "com.mifos.library.pullrefresh" +} + +dependencies { + implementation(libs.androidx.compose.animation) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.compose.ui.util) +} diff --git a/libs/pullrefresh/src/main/AndroidManifest.xml b/libs/pullrefresh/src/main/AndroidManifest.xml new file mode 100644 index 000000000..367affcc3 --- /dev/null +++ b/libs/pullrefresh/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefresh.kt b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefresh.kt new file mode 100644 index 000000000..dd15d09b4 --- /dev/null +++ b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefresh.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +@file:Suppress("InvalidPackageDeclaration") + +package com.mifos.library.pullrefresh + +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.NestedScrollSource.Companion.Drag +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.debugInspectorInfo +import androidx.compose.ui.platform.inspectable +import androidx.compose.ui.unit.Velocity + +/** + * A nested scroll modifier that provides scroll events to [state]. + * + * Note that this modifier must be added above a scrolling container, such as a lazy column, in + * order to receive scroll events. For example: + * + * @sample androidx.compose.material.samples.PullRefreshSample + * + * @param state The [PullRefreshState] associated with this pull-to-refresh component. + * The state will be updated by this modifier. + * @param enabled If not enabled, all scroll delta and fling velocity will be ignored. + */ +fun Modifier.pullRefresh(state: PullRefreshState, enabled: Boolean = true) = inspectable( + inspectorInfo = debugInspectorInfo { + name = "pullRefresh" + properties["state"] = state + properties["enabled"] = enabled + }, +) { + Modifier.pullRefresh(state::onPull, state::onRelease, enabled) +} + +/** + * A nested scroll modifier that provides [onPull] and [onRelease] callbacks to aid building custom + * pull refresh components. + * + * Note that this modifier must be added above a scrolling container, such as a lazy column, in + * order to receive scroll events. For example: + * + * @sample androidx.compose.material.samples.CustomPullRefreshSample + * + * @param onPull Callback for dispatching vertical scroll delta, takes float pullDelta as argument. + * Positive delta (pulling down) is dispatched only if the child does not consume it (i.e. pulling + * down despite being at the top of a scrollable component), whereas negative delta (swiping up) is + * dispatched first (in case it is needed to push the indicator back up), and then the unconsumed + * delta is passed on to the child. The callback returns how much delta was consumed. + * @param onRelease Callback for when drag is released, takes float flingVelocity as argument. + * The callback returns how much velocity was consumed - in most cases this should only consume + * velocity if pull refresh has been dragged already and the velocity is positive (the fling is + * downwards), as an upwards fling should typically still scroll a scrollable component beneath the + * pullRefresh. This is invoked before any remaining velocity is passed to the child. + * @param enabled If not enabled, all scroll delta and fling velocity will be ignored and neither + * [onPull] nor [onRelease] will be invoked. + */ +fun Modifier.pullRefresh( + onPull: (pullDelta: Float) -> Float, + onRelease: suspend (flingVelocity: Float) -> Float, + enabled: Boolean = true, +) = inspectable( + inspectorInfo = debugInspectorInfo { + name = "pullRefresh" + properties["onPull"] = onPull + properties["onRelease"] = onRelease + properties["enabled"] = enabled + }, +) { + Modifier.nestedScroll(PullRefreshNestedScrollConnection(onPull, onRelease, enabled)) +} + +private class PullRefreshNestedScrollConnection( + private val onPull: (pullDelta: Float) -> Float, + private val onRelease: suspend (flingVelocity: Float) -> Float, + private val enabled: Boolean, +) : NestedScrollConnection { + override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset = when { + !enabled -> Offset.Zero + source == Drag && available.y < 0 -> Offset(0f, onPull(available.y)) // Swiping up + else -> Offset.Zero + } + + override fun onPostScroll( + consumed: Offset, + available: Offset, + source: NestedScrollSource, + ): Offset = when { + !enabled -> Offset.Zero + source == Drag && available.y > 0 -> Offset(0f, onPull(available.y)) // Pulling down + else -> Offset.Zero + } + + override suspend fun onPreFling(available: Velocity): Velocity { + return Velocity(0f, onRelease(available.y)) + } +} diff --git a/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicator.kt b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicator.kt new file mode 100644 index 000000000..cfae879f2 --- /dev/null +++ b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicator.kt @@ -0,0 +1,236 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +@file:Suppress("InvalidPackageDeclaration") + +package com.mifos.library.pullrefresh + +import androidx.compose.animation.Crossfade +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect +import androidx.compose.ui.geometry.center +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.PathFillType +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.graphics.drawscope.rotate +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import kotlin.math.abs +import kotlin.math.max +import kotlin.math.min +import kotlin.math.pow + +/** + * The default indicator for Compose pull-to-refresh, based on Android's SwipeRefreshLayout. + * + * @sample androidx.compose.material.samples.PullRefreshSample + * + * @param refreshing A boolean representing whether a refresh is occurring. + * @param state The [PullRefreshState] which controls where and how the indicator will be drawn. + * @param modifier Modifiers for the indicator. + * @param backgroundColor The color of the indicator's background. + * @param contentColor The color of the indicator's arc and arrow. + * @param scale A boolean controlling whether the indicator's size scales with pull progress or not. + */ +@Composable +fun PullRefreshIndicator( + refreshing: Boolean, + state: PullRefreshState, + modifier: Modifier = Modifier, + backgroundColor: Color = MaterialTheme.colorScheme.surface, + contentColor: Color = contentColorFor(backgroundColor), + scale: Boolean = false, +) { + val showElevation by remember(refreshing, state) { + derivedStateOf { refreshing || state.position > 0.5f } + } + + Box( + modifier = modifier + .size(IndicatorSize) + .pullRefreshIndicatorTransform(state, scale) + .shadow(if (showElevation) Elevation else 0.dp, SpinnerShape, clip = true) + .background(color = backgroundColor, shape = SpinnerShape), + ) { + Crossfade( + targetState = refreshing, + animationSpec = tween(durationMillis = CROSSFADE_DURATION_MS), + label = "PullRefreshAnimation", + ) { refreshing -> + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + val spinnerSize = (ArcRadius + StrokeWidth).times(2) + + if (refreshing) { + CircularProgressIndicator( + color = contentColor, + strokeWidth = StrokeWidth, + modifier = Modifier.size(spinnerSize), + ) + } else { + CircularArrowIndicator(state, contentColor, Modifier.size(spinnerSize)) + } + } + } + } +} + +/** + * Modifier.size MUST be specified. + */ +@Composable +private fun CircularArrowIndicator( + state: PullRefreshState, + color: Color, + modifier: Modifier = Modifier, +) { + val path = remember { Path().apply { fillType = PathFillType.EvenOdd } } + + val targetAlpha by remember(state) { + derivedStateOf { + if (state.progress >= 1f) MAX_ALPHA else MIN_ALPHA + } + } + + val alphaState = animateFloatAsState( + targetValue = targetAlpha, + animationSpec = AlphaTween, + label = "alphaStateAnimation", + ) + + // Empty semantics for tests + Canvas(modifier.semantics {}) { + val values = ArrowValues(state.progress) + val alpha = alphaState.value + + rotate(degrees = values.rotation) { + val arcRadius = ArcRadius.toPx() + StrokeWidth.toPx() / 2f + val arcBounds = Rect( + size.center.x - arcRadius, + size.center.y - arcRadius, + size.center.x + arcRadius, + size.center.y + arcRadius, + ) + drawArc( + color = color, + alpha = alpha, + startAngle = values.startAngle, + sweepAngle = values.endAngle - values.startAngle, + useCenter = false, + topLeft = arcBounds.topLeft, + size = arcBounds.size, + style = Stroke( + width = StrokeWidth.toPx(), + cap = StrokeCap.Square, + ), + ) + drawArrow(path, arcBounds, color, alpha, values) + } + } +} + +@Immutable +private class ArrowValues( + val rotation: Float, + val startAngle: Float, + val endAngle: Float, + val scale: Float, +) + +private fun ArrowValues(progress: Float): ArrowValues { + // Discard first 40% of progress. Scale remaining progress to full range between 0 and 100%. + val adjustedPercent = max(min(1f, progress) - 0.4f, 0f) * 5 / 3 + // How far beyond the threshold pull has gone, as a percentage of the threshold. + val overshootPercent = abs(progress) - 1.0f + // Limit the overshoot to 200%. Linear between 0 and 200. + val linearTension = overshootPercent.coerceIn(0f, 2f) + // Non-linear tension. Increases with linearTension, but at a decreasing rate. + val tensionPercent = linearTension - linearTension.pow(2) / 4 + + // Calculations based on SwipeRefreshLayout specification. + val endTrim = adjustedPercent * MAX_PROGRESS_ARC + val rotation = (-0.25f + 0.4f * adjustedPercent + tensionPercent) * 0.5f + val startAngle = rotation * 360 + val endAngle = (rotation + endTrim) * 360 + val scale = min(1f, adjustedPercent) + + return ArrowValues(rotation, startAngle, endAngle, scale) +} + +private fun DrawScope.drawArrow( + arrow: Path, + bounds: Rect, + color: Color, + alpha: Float, + values: ArrowValues, +) { + arrow.reset() + arrow.moveTo(0f, 0f) // Move to left corner + arrow.lineTo(x = ArrowWidth.toPx() * values.scale, y = 0f) // Line to right corner + + // Line to tip of arrow + arrow.lineTo( + x = ArrowWidth.toPx() * values.scale / 2, + y = ArrowHeight.toPx() * values.scale, + ) + + val radius = min(bounds.width, bounds.height) / 2f + val inset = ArrowWidth.toPx() * values.scale / 2f + arrow.translate( + Offset( + x = radius + bounds.center.x - inset, + y = bounds.center.y + StrokeWidth.toPx() / 2f, + ), + ) + arrow.close() + rotate(degrees = values.endAngle) { + drawPath(path = arrow, color = color, alpha = alpha) + } +} + +private const val CROSSFADE_DURATION_MS = 100 +private const val MAX_PROGRESS_ARC = 0.8f + +private val IndicatorSize = 40.dp +private val SpinnerShape = CircleShape +private val ArcRadius = 7.5.dp +private val StrokeWidth = 2.5.dp +private val ArrowWidth = 10.dp +private val ArrowHeight = 5.dp +private val Elevation = 6.dp + +// Values taken from SwipeRefreshLayout +private const val MIN_ALPHA = 0.3f +private const val MAX_ALPHA = 1f +private val AlphaTween = tween(300, easing = LinearEasing) diff --git a/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicatorTransform.kt b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicatorTransform.kt new file mode 100644 index 000000000..d586986be --- /dev/null +++ b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshIndicatorTransform.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +@file:Suppress("InvalidPackageDeclaration") + +package com.mifos.library.pullrefresh + +import androidx.compose.animation.core.LinearOutSlowInEasing +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithContent +import androidx.compose.ui.graphics.drawscope.clipRect +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.debugInspectorInfo +import androidx.compose.ui.platform.inspectable + +/** + * A modifier for translating the position and scaling the size of a pull-to-refresh indicator + * based on the given [PullRefreshState]. + * + * @sample androidx.compose.material.samples.PullRefreshIndicatorTransformSample + * + * @param state The [PullRefreshState] which determines the position of the indicator. + * @param scale A boolean controlling whether the indicator's size scales with pull progress or not. + */ +fun Modifier.pullRefreshIndicatorTransform(state: PullRefreshState, scale: Boolean = false) = inspectable( + inspectorInfo = debugInspectorInfo { + name = "pullRefreshIndicatorTransform" + properties["state"] = state + properties["scale"] = scale + }, +) { + Modifier + // Essentially we only want to clip the at the top, so the indicator will not appear when + // the position is 0. It is preferable to clip the indicator as opposed to the layout that + // contains the indicator, as this would also end up clipping shadows drawn by items in a + // list for example - so we leave the clipping to the scrolling container. We use MAX_VALUE + // for the other dimensions to allow for more room for elevation / arbitrary indicators - we + // only ever really want to clip at the top edge. + .drawWithContent { + clipRect( + top = 0f, + left = -Float.MAX_VALUE, + right = Float.MAX_VALUE, + bottom = Float.MAX_VALUE, + ) { + this@drawWithContent.drawContent() + } + } + .graphicsLayer { + translationY = state.position - size.height + + if (scale && !state.refreshing) { + val scaleFraction = LinearOutSlowInEasing + .transform(state.position / state.threshold) + .coerceIn(0f, 1f) + scaleX = scaleFraction + scaleY = scaleFraction + } + } +} diff --git a/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshState.kt b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshState.kt new file mode 100644 index 000000000..076e26844 --- /dev/null +++ b/libs/pullrefresh/src/main/kotlin/com.mifos.library.pullrefresh/PullRefreshState.kt @@ -0,0 +1,229 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +@file:Suppress("InvalidPackageDeclaration") + +package com.mifos.library.pullrefresh + +import androidx.compose.animation.core.animate +import androidx.compose.foundation.MutatorMutex +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.State +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import kotlin.math.abs +import kotlin.math.pow + +/** + * Creates a [PullRefreshState] that is remembered across compositions. + * + * Changes to [refreshing] will result in [PullRefreshState] being updated. + * + * @sample androidx.compose.material.samples.PullRefreshSample + * + * @param refreshing A boolean representing whether a refresh is currently occurring. + * @param onRefresh The function to be called to trigger a refresh. + * @param refreshThreshold The threshold below which, if a release + * occurs, [onRefresh] will be called. + * @param refreshingOffset The offset at which the indicator will be drawn while refreshing. This + * offset corresponds to the position of the bottom of the indicator. + */ +@Composable +@Suppress("InvalidPackageDeclaration") +fun rememberPullRefreshState( + refreshing: Boolean, + onRefresh: () -> Unit, + refreshThreshold: Dp = PullRefreshDefaults.RefreshThreshold, + refreshingOffset: Dp = PullRefreshDefaults.RefreshingOffset, +): PullRefreshState { + require(refreshThreshold > 0.dp) { "The refresh trigger must be greater than zero!" } + + val scope = rememberCoroutineScope() + val onRefreshState = rememberUpdatedState(onRefresh) + val thresholdPx: Float + val refreshingOffsetPx: Float + + with(LocalDensity.current) { + thresholdPx = refreshThreshold.toPx() + refreshingOffsetPx = refreshingOffset.toPx() + } + + val state = remember(scope) { + PullRefreshState(scope, onRefreshState, refreshingOffsetPx, thresholdPx) + } + + SideEffect { + state.setRefreshing(refreshing) + state.setThreshold(thresholdPx) + state.setRefreshingOffset(refreshingOffsetPx) + } + + return state +} + +/** + * A state object that can be used in conjunction with [pullRefresh] to add pull-to-refresh + * behaviour to a scroll component. Based on Android's SwipeRefreshLayout. + * + * Provides [progress], a float representing how far the user has pulled as a percentage of the + * refreshThreshold. Values of one or less indicate that the user has not yet pulled past the + * threshold. Values greater than one indicate how far past the threshold the user has pulled. + * + * Can be used in conjunction with [pullRefreshIndicatorTransform] to implement Android-like + * pull-to-refresh behaviour with a custom indicator. + * + * Should be created using [rememberPullRefreshState]. + */ +@Suppress("ktlint:standard:property-naming") +class PullRefreshState internal constructor( + private val animationScope: CoroutineScope, + private val onRefreshState: State<() -> Unit>, + refreshingOffset: Float, + threshold: Float, +) { + /** + * A float representing how far the user has pulled as a percentage of the refreshThreshold. + * + * If the component has not been pulled at all, progress is zero. If the pull has reached + * halfway to the threshold, progress is 0.5f. A value greater than 1 indicates that pull has + * gone beyond the refreshThreshold - e.g. a value of 2f indicates that the user has pulled to + * two times the refreshThreshold. + */ + val progress get() = adjustedDistancePulled / threshold + + internal val refreshing get() = _refreshing + internal val position get() = _position + internal val threshold get() = _threshold + + private val adjustedDistancePulled by derivedStateOf { distancePulled * DRAG_MULTIPLIER } + + private var _refreshing by mutableStateOf(false) + + private var _position by mutableFloatStateOf(0f) + private var distancePulled by mutableFloatStateOf(0f) + + private var _threshold by mutableFloatStateOf(threshold) + + private var _refreshingOffset by mutableFloatStateOf(refreshingOffset) + + internal fun onPull(pullDelta: Float): Float { + if (_refreshing) return 0f // Already refreshing, do nothing. + + val newOffset = (distancePulled + pullDelta).coerceAtLeast(0f) + val dragConsumed = newOffset - distancePulled + distancePulled = newOffset + _position = calculateIndicatorPosition() + return dragConsumed + } + + internal fun onRelease(velocity: Float): Float { + if (refreshing) return 0f // Already refreshing, do nothing + + if (adjustedDistancePulled > threshold) { + onRefreshState.value() + } + animateIndicatorTo(0f) + val consumed = when { + // We are flinging without having dragged the pull refresh (for example a fling inside + // a list) - don't consume + distancePulled == 0f -> 0f + // If the velocity is negative, the fling is upwards, and we don't want to prevent the + // the list from scrolling + velocity < 0f -> 0f + // We are showing the indicator, and the fling is downwards - consume everything + else -> velocity + } + distancePulled = 0f + return consumed + } + + internal fun setRefreshing(refreshing: Boolean) { + if (_refreshing != refreshing) { + _refreshing = refreshing + distancePulled = 0f + animateIndicatorTo(if (refreshing) _refreshingOffset else 0f) + } + } + + internal fun setThreshold(threshold: Float) { + _threshold = threshold + } + + internal fun setRefreshingOffset(refreshingOffset: Float) { + if (_refreshingOffset != refreshingOffset) { + _refreshingOffset = refreshingOffset + if (refreshing) animateIndicatorTo(refreshingOffset) + } + } + + // Make sure to cancel any existing animations when we launch a new one. We use this instead of + // Animatable as calling snapTo() on every drag delta has a one frame delay, and some extra + // overhead of running through the animation pipeline instead of directly mutating the state. + private val mutatorMutex = MutatorMutex() + + private fun animateIndicatorTo(offset: Float) = animationScope.launch { + mutatorMutex.mutate { + animate(initialValue = _position, targetValue = offset) { value, _ -> + _position = value + } + } + } + + private fun calculateIndicatorPosition(): Float = when { + // If drag hasn't gone past the threshold, the position is the adjustedDistancePulled. + adjustedDistancePulled <= threshold -> adjustedDistancePulled + else -> { + // How far beyond the threshold pull has gone, as a percentage of the threshold. + val overshootPercent = abs(progress) - 1.0f + // Limit the overshoot to 200%. Linear between 0 and 200. + val linearTension = overshootPercent.coerceIn(0f, 2f) + // Non-linear tension. Increases with linearTension, but at a decreasing rate. + val tensionPercent = linearTension - linearTension.pow(2) / 4 + // The additional offset beyond the threshold. + val extraOffset = threshold * tensionPercent + threshold + extraOffset + } + } +} + +/** + * Default parameter values for [rememberPullRefreshState]. + */ +object PullRefreshDefaults { + /** + * If the indicator is below this threshold offset when it is released, a refresh + * will be triggered. + */ + val RefreshThreshold = 80.dp + + /** + * The offset at which the indicator should be rendered whilst a refresh is occurring. + */ + val RefreshingOffset = 56.dp +} + +/** + * The distance pulled is multiplied by this value to give us the adjusted distance pulled, which + * is used in calculating the indicator position (when the adjusted distance pulled is less than + * the refresh threshold, it is the indicator position, otherwise the indicator position is + * derived from the progress). + */ +private const val DRAG_MULTIPLIER = 0.5f diff --git a/lint/.gitignore b/lint/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/lint/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/lint/build.gradle.kts b/lint/build.gradle.kts new file mode 100644 index 000000000..26b8acd38 --- /dev/null +++ b/lint/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + `java-library` + kotlin("jvm") + alias(libs.plugins.mifos.android.lint) +} + +java { + // Up to Java 11 APIs are available through desugaring + // https://developer.android.com/studio/write/java11-minimal-support-table + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_11 + } +} + +dependencies { + compileOnly(libs.kotlin.stdlib) + compileOnly(libs.lint.api) + testImplementation(libs.lint.checks) + testImplementation(libs.lint.tests) + testImplementation(kotlin("test")) +} diff --git a/lint/lint-baseline.xml b/lint/lint-baseline.xml new file mode 100644 index 000000000..654f8d1b2 --- /dev/null +++ b/lint/lint-baseline.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/MifosIssueRegistry.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/MifosIssueRegistry.kt new file mode 100644 index 000000000..cc942207d --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/MifosIssueRegistry.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint + +import com.android.tools.lint.client.api.IssueRegistry +import com.android.tools.lint.client.api.Vendor +import com.android.tools.lint.detector.api.CURRENT_API +import org.mifos.mifospay.lint.designsystem.DesignSystemDetector +import org.mifos.mifospay.lint.designsystem.Material2Detector + +class MifosIssueRegistry : IssueRegistry() { + + override val issues = listOf( + DesignSystemDetector.ISSUE, + Material2Detector.ISSUE, + TestMethodNameDetector.FORMAT, + TestMethodNameDetector.PREFIX, + ) + + override val api: Int = CURRENT_API + + override val minApi: Int = 12 + + override val vendor: Vendor = Vendor( + vendorName = "Mifos Mobile", + feedbackUrl = "https://github.com/openMF/mobile-mobile/issues", + contact = "https://github.com/openMF/mobile-mobile", + ) +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/TestMethodNameDetector.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/TestMethodNameDetector.kt new file mode 100644 index 000000000..b49471fbb --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/TestMethodNameDetector.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint + +import com.android.tools.lint.detector.api.AnnotationInfo +import com.android.tools.lint.detector.api.AnnotationUsageInfo +import com.android.tools.lint.detector.api.Category.Companion.TESTING +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.LintFix +import com.android.tools.lint.detector.api.Scope.JAVA_FILE +import com.android.tools.lint.detector.api.Scope.TEST_SOURCES +import com.android.tools.lint.detector.api.Severity.WARNING +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.android.tools.lint.detector.api.TextFormat.RAW +import com.intellij.psi.PsiMethod +import org.jetbrains.uast.UElement +import java.util.EnumSet +import kotlin.io.path.Path + +/** + * A detector that checks for common patterns in naming the test methods: + * - [detectPrefix] removes unnecessary "test" prefix in all unit test. + * - [detectFormat] Checks the `given_when_then` format of Android instrumented tests (backticks are not supported). + */ +class TestMethodNameDetector : Detector(), SourceCodeScanner { + + override fun applicableAnnotations() = listOf("org.junit.Test") + + override fun visitAnnotationUsage( + context: JavaContext, + element: UElement, + annotationInfo: AnnotationInfo, + usageInfo: AnnotationUsageInfo, + ) { + val method = usageInfo.referenced as? PsiMethod ?: return + + method.detectPrefix(context, usageInfo) + method.detectFormat(context, usageInfo) + } + + private fun JavaContext.isAndroidTest() = Path("androidTest") in file.toPath() + + private fun PsiMethod.detectPrefix( + context: JavaContext, + usageInfo: AnnotationUsageInfo, + ) { + if (!name.startsWith("test")) return + context.report( + issue = PREFIX, + scope = usageInfo.usage, + location = context.getNameLocation(this), + message = PREFIX.getBriefDescription(RAW), + quickfixData = LintFix.create() + .name("Remove prefix") + .replace().pattern("""test[\s_]*""") + .with("") + .autoFix() + .build(), + ) + } + + private fun PsiMethod.detectFormat( + context: JavaContext, + usageInfo: AnnotationUsageInfo, + ) { + if (!context.isAndroidTest()) return + if ("""[^\W_]+(_[^\W_]+){1,2}""".toRegex().matches(name)) return + context.report( + issue = FORMAT, + scope = usageInfo.usage, + location = context.getNameLocation(this), + message = FORMAT.getBriefDescription(RAW), + ) + } + + companion object { + + private fun issue( + id: String, + briefDescription: String, + explanation: String, + ): Issue = Issue.create( + id = id, + briefDescription = briefDescription, + explanation = explanation, + category = TESTING, + priority = 5, + severity = WARNING, + implementation = Implementation( + TestMethodNameDetector::class.java, + EnumSet.of(JAVA_FILE, TEST_SOURCES), + ), + ) + + @JvmField + val PREFIX: Issue = issue( + id = "TestMethodPrefix", + briefDescription = "Test method starts with `test`", + explanation = "Test method should not start with `test`.", + ) + + @JvmField + val FORMAT: Issue = issue( + id = "TestMethodFormat", + briefDescription = "Test method does not follow the `given_when_then` or `when_then` format", + explanation = "Test method should follow the `given_when_then` or `when_then` format.", + ) + } +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/config/Priorities.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/config/Priorities.kt new file mode 100644 index 000000000..f5010c129 --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/config/Priorities.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.config + +object Priorities { + const val HIGH = 10 + const val NORMAL = 5 + const val LOW = 3 + const val NONE = 1 +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetector.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetector.kt new file mode 100644 index 000000000..802399b7e --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetector.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.designsystem + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UQualifiedReferenceExpression + +/** + * A detector that checks for incorrect usages of Compose Material APIs over equivalents in + * the Now in Android design system module. + */ +class DesignSystemDetector : Detector(), Detector.UastScanner { + + override fun getApplicableUastTypes(): List> = listOf( + UCallExpression::class.java, + UQualifiedReferenceExpression::class.java, + ) + + override fun createUastHandler(context: JavaContext): UElementHandler = + object : UElementHandler() { + override fun visitCallExpression(node: UCallExpression) { + val name = node.methodName ?: return + val preferredName = METHOD_NAMES[name] ?: return + reportIssue(context, node, name, preferredName) + } + + override fun visitQualifiedReferenceExpression(node: UQualifiedReferenceExpression) { + val name = node.receiver.asRenderString() + val preferredName = RECEIVER_NAMES[name] ?: return + reportIssue(context, node, name, preferredName) + } + } + + companion object { + @JvmField + val ISSUE: Issue = Issue.create( + id = "DesignSystem", + briefDescription = "Design system", + explanation = "This check highlights calls in code that use Compose Material " + + "composables instead of equivalents from the Mifos design system " + + "module.", + category = Category.CUSTOM_LINT_CHECKS, + priority = 7, + severity = Severity.ERROR, + implementation = Implementation( + DesignSystemDetector::class.java, + Scope.JAVA_FILE_SCOPE, + ), + ) + + // Unfortunately :lint is a Java module and thus can't depend on the :core-designsystem + // Android module, so we can't use composable function references (eg. ::Button.name) + // instead of hardcoded names. + val METHOD_NAMES = mapOf( + "MaterialTheme" to "MifosMobileTheme", + "Button" to "MifosButton", + "OutlinedButton" to "MifosOutlinedButton", + "TextButton" to "MifosTextButton", + "FilterChip" to "MifosFilterChip", + "ElevatedFilterChip" to "MifosFilterChip", + "NavigationBar" to "MifosNavigationBar", + "NavigationBarItem" to "MifosNavigationBarItem", + "NavigationRail" to "MifosNavigationRail", + "NavigationRailItem" to "MifosNavigationRailItem", + "TabRow" to "MifosTabRow", + "Tab" to "MifosTab", + "IconToggleButton" to "MifosIconToggleButton", + "FilledIconToggleButton" to "MifosIconToggleButton", + "FilledTonalIconToggleButton" to "MifosIconToggleButton", + "OutlinedIconToggleButton" to "MifosIconToggleButton", + "CenterAlignedTopAppBar" to "MifosTopAppBar", + "SmallTopAppBar" to "MifosTopAppBar", + "MediumTopAppBar" to "MifosTopAppBar", + "LargeTopAppBar" to "MifosTopAppBar", + ) + val RECEIVER_NAMES = mapOf( + "Icons" to "MifosIcons", + ) + + fun reportIssue( + context: JavaContext, + node: UElement, + name: String, + preferredName: String, + ) { + context.report( + ISSUE, + node, + context.getLocation(node), + "Using $name instead of $preferredName", + ) + } + } +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/Material2Detector.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/Material2Detector.kt new file mode 100644 index 000000000..3546a034f --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/designsystem/Material2Detector.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.designsystem + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.android.tools.lint.detector.api.StringOption +import com.android.tools.lint.detector.api.TextFormat +import com.android.tools.lint.detector.api.isKotlin +import com.intellij.psi.PsiNamedElement +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UQualifiedReferenceExpression +import org.jetbrains.uast.UResolvable +import org.mifos.mifospay.lint.config.Priorities +import org.mifos.mifospay.lint.util.OptionLoadingDetector +import org.mifos.mifospay.lint.util.StringSetLintOption +import org.mifos.mifospay.lint.util.sourceImplementation + +/** + * Checks and reports any usage of Material2 for compose. Material3 should be used everywhere instead. + */ +@Suppress("ReturnCount") +internal class Material2Detector @JvmOverloads constructor( + private val allowList: StringSetLintOption = StringSetLintOption(ALLOW_LIST), +) : OptionLoadingDetector(allowList), SourceCodeScanner { + override fun getApplicableUastTypes(): List> = listOf>( + UCallExpression::class.java, + UQualifiedReferenceExpression::class.java, + ) + + override fun createUastHandler(context: JavaContext): UElementHandler? { + // Only applicable to Kotlin files + val language = context.uastFile?.lang ?: return null + if (!isKotlin(language)) return null + return object : UElementHandler() { + override fun visitCallExpression(node: UCallExpression) = checkNode(node) + + override fun visitQualifiedReferenceExpression(node: UQualifiedReferenceExpression) = + checkNode(node) + + private fun checkNode(node: UResolvable) { + val resolved = node.resolve() ?: return + val packageName = context.evaluator.getPackage(resolved)?.qualifiedName ?: return + if (packageName == M2_PACKAGE) { + // https://github.com/slackhq/compose-lints/issues/167 + // https://issuetracker.google.com/issues/297544175 + val resolvedName = (resolved as? PsiNamedElement)?.name + val unmanagedResolvedName = resolvedName?.substringBefore("-") + if (unmanagedResolvedName in allowList.value) { + // Ignore any in the allow-list. + return + } + context.report( + issue = ISSUE, + location = context.getLocation(node), + message = ISSUE.getExplanation(TextFormat.TEXT), + ) + } + } + } + } + + companion object { + private const val M2_PACKAGE = "androidx.compose.material" + private const val MATERIAL2_DETECTOR_ISSUE_ID = "ComposeM2Api" + + internal val ALLOW_LIST = StringOption( + "allowed-m2-apis", + "A comma-separated list of APIs in androidx.compose.material " + + "that should be allowed.", + null, + "This property should define a comma-separated list " + + "of APIs in androidx.compose.material that should be allowed", + ) + + val ISSUE = Issue.create( + id = MATERIAL2_DETECTOR_ISSUE_ID, + briefDescription = "Using a Compose M2 API is not recommended", + explanation = "Compose Material 2 (M2) is succeeded by Material 3 (M3)." + + " Please use M3 APIs. " + + "See https://slackhq.github.io/compose-lints/rules/#use-material-3 " + + "for more information.", + category = Category.CORRECTNESS, + priority = Priorities.NORMAL, + severity = Severity.ERROR, + implementation = sourceImplementation(), + ) + .setOptions(listOf(ALLOW_LIST)) + .setEnabledByDefault(true) + } +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintOption.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintOption.kt new file mode 100644 index 000000000..6d14aaf0e --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintOption.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.util + +import com.android.tools.lint.client.api.Configuration + +/** + * A layer of indirection for implementations of option loaders without needing to extend from + * Detector. This goes along with [OptionLoadingDetector]. + */ +interface LintOption { + fun load(configuration: Configuration) +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintUtils.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintUtils.kt new file mode 100644 index 000000000..8c2ea765b --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/LintUtils.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.util + +import com.android.tools.lint.client.api.Configuration +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.android.tools.lint.detector.api.StringOption +import java.util.EnumSet + +@Suppress("SpreadOperator") +internal inline fun sourceImplementation( + shouldRunOnTestSources: Boolean = true, +): Implementation where T : Detector, T : SourceCodeScanner { + // We use the overloaded constructor that takes a varargs of `Scope` as the last param. + // This is to enable on-the-fly IDE checks. We are telling lint to run on both + // JAVA and TEST_SOURCES in the `scope` parameter but by providing the `analysisScopes` + // params, we're indicating that this check can run on either JAVA or TEST_SOURCES and + // doesn't require both of them together. + // From discussion on lint-dev https://groups.google.com/d/msg/lint-dev/ULQMzW1ZlP0/1dG4Vj3-AQAJ + // This was supposed to be fixed in AS 3.4 but still required as recently as 3.6-alpha10. + return if (shouldRunOnTestSources) { + Implementation( + T::class.java, + EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES), + EnumSet.of(Scope.JAVA_FILE), + EnumSet.of(Scope.TEST_SOURCES), + ) + } else { + Implementation(T::class.java, EnumSet.of(Scope.JAVA_FILE)) + } +} + +/** Loads a [StringOption] as a [delimiter]-delimited [Set] of strings. */ +internal fun StringOption.loadAsSet( + configuration: Configuration, + delimiter: String = ",", +): Set { + return getValue(configuration) + ?.splitToSequence(delimiter) + .orEmpty() + .map(String::trim) + .filter(String::isNotBlank) + .toSet() +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/util/OptionLoadingDetector.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/OptionLoadingDetector.kt new file mode 100644 index 000000000..c985d525a --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/OptionLoadingDetector.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.util + +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Detector + +/** A [Detector] that supports reading the given [options]. */ +abstract class OptionLoadingDetector(vararg options: LintOption) : Detector() { + + private val options = options.toList() + + override fun beforeCheckRootProject(context: Context) { + super.beforeCheckRootProject(context) + val config = context.configuration + options.forEach { it.load(config) } + } +} diff --git a/lint/src/main/kotlin/org/mifos/mifospay/lint/util/StringSetLintOption.kt b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/StringSetLintOption.kt new file mode 100644 index 000000000..b84c06def --- /dev/null +++ b/lint/src/main/kotlin/org/mifos/mifospay/lint/util/StringSetLintOption.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.util + +import com.android.tools.lint.client.api.Configuration +import com.android.tools.lint.detector.api.StringOption + +open class StringSetLintOption(private val option: StringOption) : LintOption { + var value: Set = emptySet() + private set + + override fun load(configuration: Configuration) { + value = option.loadAsSet(configuration) + } +} diff --git a/lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry b/lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry new file mode 100644 index 000000000..2ad9bf910 --- /dev/null +++ b/lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry @@ -0,0 +1 @@ +org.mifos.mifospay.lint.MifosIssueRegistry diff --git a/lint/src/test/kotlin/org/mifos/mifospay/lint/TestMethodNameDetectorTest.kt b/lint/src/test/kotlin/org/mifos/mifospay/lint/TestMethodNameDetectorTest.kt new file mode 100644 index 000000000..3111e8eb5 --- /dev/null +++ b/lint/src/test/kotlin/org/mifos/mifospay/lint/TestMethodNameDetectorTest.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint + +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestFiles.kotlin +import com.android.tools.lint.checks.infrastructure.TestLintTask.lint +import org.junit.Test +import org.mifos.mifospay.lint.TestMethodNameDetector.Companion.FORMAT +import org.mifos.mifospay.lint.TestMethodNameDetector.Companion.PREFIX + +class TestMethodNameDetectorTest { + + @Test + fun `detect prefix`() { + lint().issues(PREFIX) + .files( + JUNIT_TEST_STUB, + kotlin( + """ + import org.junit.Test + class Test { + @Test + fun foo() = Unit + @Test + fun test_foo() = Unit + @Test + fun `test foo`() = Unit + } + """, + ).indented(), + ) + .run() + .expect( + """ + src/Test.kt:6: Warning: Test method starts with test [TestMethodPrefix] + fun test_foo() = Unit + ~~~~~~~~ + src/Test.kt:8: Warning: Test method starts with test [TestMethodPrefix] + fun `test foo`() = Unit + ~~~~~~~~~~ + 0 errors, 2 warnings + """.trimIndent(), + ) + .expectFixDiffs( + """ + Autofix for src/Test.kt line 6: Remove prefix: + @@ -6 +6 + - fun test_foo() = Unit + + fun foo() = Unit + Autofix for src/Test.kt line 8: Remove prefix: + @@ -8 +8 + - fun `test foo`() = Unit + + fun `foo`() = Unit + """.trimIndent(), + ) + } + + @Test + fun `detect format`() { + lint().issues(FORMAT) + .files( + JUNIT_TEST_STUB, + kotlin( + "src/androidTest/com/example/Test.kt", + """ + import org.junit.Test + class Test { + @Test + fun when_then() = Unit + @Test + fun given_when_then() = Unit + + @Test + fun foo() = Unit + @Test + fun foo_bar_baz_qux() = Unit + @Test + fun `foo bar baz`() = Unit + } + """, + ).indented(), + ) + .run() + .expect( + """ + src/androidTest/com/example/Test.kt:9: Warning: Test method does not follow the given_when_then or when_then format [TestMethodFormat] + fun foo() = Unit + ~~~ + src/androidTest/com/example/Test.kt:11: Warning: Test method does not follow the given_when_then or when_then format [TestMethodFormat] + fun foo_bar_baz_qux() = Unit + ~~~~~~~~~~~~~~~ + src/androidTest/com/example/Test.kt:13: Warning: Test method does not follow the given_when_then or when_then format [TestMethodFormat] + fun `foo bar baz`() = Unit + ~~~~~~~~~~~~~ + 0 errors, 3 warnings + """.trimIndent(), + ) + } + + private companion object { + private val JUNIT_TEST_STUB: TestFile = kotlin( + """ + package org.junit + annotation class Test + """, + ).indented() + } +} diff --git a/lint/src/test/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetectorTest.kt b/lint/src/test/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetectorTest.kt new file mode 100644 index 000000000..b82bf3d18 --- /dev/null +++ b/lint/src/test/kotlin/org/mifos/mifospay/lint/designsystem/DesignSystemDetectorTest.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2024 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-wallet/blob/master/LICENSE.md + */ +package org.mifos.mifospay.lint.designsystem + +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestFiles.kotlin +import com.android.tools.lint.checks.infrastructure.TestLintTask.lint +import org.junit.Test +import org.mifos.mifospay.lint.designsystem.DesignSystemDetector.Companion.ISSUE +import org.mifos.mifospay.lint.designsystem.DesignSystemDetector.Companion.METHOD_NAMES +import org.mifos.mifospay.lint.designsystem.DesignSystemDetector.Companion.RECEIVER_NAMES + +class DesignSystemDetectorTest { + + @Test + fun `detect replacements of Composable`() { + lint() + .issues(ISSUE) + .allowMissingSdk() + .files( + COMPOSABLE_STUB, + STUBS, + @Suppress("LintImplTrimIndent") + kotlin( + """ + |import androidx.compose.runtime.Composable + | + |@Composable + |fun App() { + ${METHOD_NAMES.keys.joinToString("\n") { "| $it()" }} + |} + """.trimMargin(), + ).indented(), + ) + .run() + .expect( + """ + src/test.kt:5: Error: Using MaterialTheme instead of MifosMobileTheme [DesignSystem] + MaterialTheme() + ~~~~~~~~~~~~~~~ + src/test.kt:6: Error: Using Button instead of MifosButton [DesignSystem] + Button() + ~~~~~~~~ + src/test.kt:7: Error: Using OutlinedButton instead of MifosOutlinedButton [DesignSystem] + OutlinedButton() + ~~~~~~~~~~~~~~~~ + src/test.kt:8: Error: Using TextButton instead of MifosTextButton [DesignSystem] + TextButton() + ~~~~~~~~~~~~ + src/test.kt:9: Error: Using FilterChip instead of MifosFilterChip [DesignSystem] + FilterChip() + ~~~~~~~~~~~~ + src/test.kt:10: Error: Using ElevatedFilterChip instead of MifosFilterChip [DesignSystem] + ElevatedFilterChip() + ~~~~~~~~~~~~~~~~~~~~ + src/test.kt:11: Error: Using NavigationBar instead of MifosNavigationBar [DesignSystem] + NavigationBar() + ~~~~~~~~~~~~~~~ + src/test.kt:12: Error: Using NavigationBarItem instead of MifosNavigationBarItem [DesignSystem] + NavigationBarItem() + ~~~~~~~~~~~~~~~~~~~ + src/test.kt:13: Error: Using NavigationRail instead of MifosNavigationRail [DesignSystem] + NavigationRail() + ~~~~~~~~~~~~~~~~ + src/test.kt:14: Error: Using NavigationRailItem instead of MifosNavigationRailItem [DesignSystem] + NavigationRailItem() + ~~~~~~~~~~~~~~~~~~~~ + src/test.kt:15: Error: Using TabRow instead of MifosTabRow [DesignSystem] + TabRow() + ~~~~~~~~ + src/test.kt:16: Error: Using Tab instead of MifosTab [DesignSystem] + Tab() + ~~~~~ + src/test.kt:17: Error: Using IconToggleButton instead of MifosIconToggleButton [DesignSystem] + IconToggleButton() + ~~~~~~~~~~~~~~~~~~ + src/test.kt:18: Error: Using FilledIconToggleButton instead of MifosIconToggleButton [DesignSystem] + FilledIconToggleButton() + ~~~~~~~~~~~~~~~~~~~~~~~~ + src/test.kt:19: Error: Using FilledTonalIconToggleButton instead of MifosIconToggleButton [DesignSystem] + FilledTonalIconToggleButton() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test.kt:20: Error: Using OutlinedIconToggleButton instead of MifosIconToggleButton [DesignSystem] + OutlinedIconToggleButton() + ~~~~~~~~~~~~~~~~~~~~~~~~~~ + src/test.kt:21: Error: Using CenterAlignedTopAppBar instead of MifosTopAppBar [DesignSystem] + CenterAlignedTopAppBar() + ~~~~~~~~~~~~~~~~~~~~~~~~ + src/test.kt:22: Error: Using SmallTopAppBar instead of MifosTopAppBar [DesignSystem] + SmallTopAppBar() + ~~~~~~~~~~~~~~~~ + src/test.kt:23: Error: Using MediumTopAppBar instead of MifosTopAppBar [DesignSystem] + MediumTopAppBar() + ~~~~~~~~~~~~~~~~~ + src/test.kt:24: Error: Using LargeTopAppBar instead of MifosTopAppBar [DesignSystem] + LargeTopAppBar() + ~~~~~~~~~~~~~~~~ + 20 errors, 0 warnings + """.trimIndent(), + ) + } + + @Test + fun `detect replacements of Receiver`() { + lint() + .issues(ISSUE) + .allowMissingSdk() + .files( + COMPOSABLE_STUB, + STUBS, + @Suppress("LintImplTrimIndent") + kotlin( + """ + |fun main() { + ${RECEIVER_NAMES.keys.joinToString("\n") { "| $it.toString()" }} + |} + """.trimMargin(), + ).indented(), + ) + .run() + .expect( + """ + src/test.kt:2: Error: Using Icons instead of MifosIcons [DesignSystem] + Icons.toString() + ~~~~~~~~~~~~~~~~ + 1 errors, 0 warnings + """.trimIndent(), + ) + } + + private companion object { + + private val COMPOSABLE_STUB: TestFile = kotlin( + """ + package androidx.compose.runtime + annotation class Composable + """.trimIndent(), + ).indented() + + private val STUBS: TestFile = kotlin( + """ + |import androidx.compose.runtime.Composable + | + ${METHOD_NAMES.keys.joinToString("\n") { "|@Composable fun $it() = {}" }} + ${RECEIVER_NAMES.keys.joinToString("\n") { "|object $it" }} + | + """.trimMargin(), + ).indented() + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 86a0641da..63a57a52f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,8 +19,12 @@ dependencyResolutionManagement { rootProject.name = "mifos-mobile" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + include(":androidApp") -include(":ui") + +// Core Modules +include(":core:ui") +include(":core:designsystem") include(":core:logs") include(":feature:guarantor") include(":core:model") @@ -28,6 +32,8 @@ include(":core:common") include(":core:data") include(":core:network") include(":core:datastore") + +// Feature Modules include(":feature:loan") include(":feature:beneficiary") include(":feature:savings") @@ -46,4 +52,15 @@ include(":feature:auth") include(":feature:update-password") include(":feature:home") include(":feature:user_profile") + +// Lint Modules +include(":lint") + +// Library Modules +include(":libs:country-code-picker") +include(":libs:pullrefresh") +include(":libs:material3-navigation") +include(":libs:mifos-passcode") + +// Kotlin Multiplatform Modules include(":shared") diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts deleted file mode 100644 index 1ab8acab0..000000000 --- a/ui/build.gradle.kts +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - alias(libs.plugins.mifos.android.library) - alias(libs.plugins.mifos.android.library.compose) -} - -android { - defaultConfig { - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - namespace = "org.mifos.mobile.core" -} - -dependencies { - api(libs.androidx.compose.foundation) - api(libs.androidx.compose.foundation.layout) - api(libs.androidx.compose.material.iconsExtended) - api(libs.androidx.compose.material3) - api(libs.androidx.compose.runtime) - api(libs.androidx.compose.ui.tooling.preview) - api(libs.androidx.compose.ui.util) - - debugApi(libs.androidx.compose.ui.tooling) - - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("com.google.android.material:material:1.9.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") -} diff --git a/ui/src/androidTest/java/org/mifos/mifos/core/ExampleInstrumentedTest.kt b/ui/src/androidTest/java/org/mifos/mifos/core/ExampleInstrumentedTest.kt deleted file mode 100644 index 37dea0c3c..000000000 --- a/ui/src/androidTest/java/org/mifos/mifos/core/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.mifos.mifos.core - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.example.core.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68a..000000000 --- a/ui/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt deleted file mode 100644 index fc8fd215d..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/AboutUsItemCard.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -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.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp - -@Composable -fun AboutUsItemCard(title: String, subtitle: Int?, iconUrl: Int?) { - Row( - modifier = Modifier.padding(16.dp) - ) { - iconUrl?.let { painterResource(id = it) }?.let { - Image( - painter = it, - contentDescription = null, - modifier = Modifier.padding(end = 8.dp) - ) - } - Column { - Text( - text = title, - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.padding(end = 8.dp) - ) - if (subtitle != null) { - Text( - text = stringResource(id = subtitle), - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.padding(end = 8.dp) - ) - } - } - } -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt deleted file mode 100644 index c0a31947c..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosAlertDialog.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.vector.ImageVector - -@Composable -fun MifosAlertDialog( - onDismissRequest: () -> Unit, - dismissText: String, - onConfirmation: () -> Unit, - confirmationText: String, - dialogTitle: String, - dialogText: String, - icon: ImageVector? = null -) { - AlertDialog( - icon = { - if (icon != null) { - Icon(imageVector = icon, contentDescription = null) - } - }, - title = { Text(text = dialogTitle) }, - text = { Text(text = dialogText) }, - onDismissRequest = { onDismissRequest() }, - confirmButton = { - TextButton( - onClick = { onConfirmation() } - ) { - Text(confirmationText) - } - }, - dismissButton = { - TextButton( - onClick = { onDismissRequest() } - ) { - Text(dismissText) - } - } - ) -} diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt deleted file mode 100644 index 4e8effcf1..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosLinkText.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.unit.dp -import org.mifos.mobile.core.ui.theme.Blue700 - -@Composable -fun MifosLinkText( - modifier: Modifier = Modifier, - text: String, - onClick: () -> Unit, - isUnderlined: Boolean = true -) { - Text( - text = text, - style = MaterialTheme.typography.bodyMedium.copy( - color = MaterialTheme.colorScheme.primary, - textDecoration = if(isUnderlined) TextDecoration.Underline else null - ), - modifier = modifier - .padding(vertical = 2.dp) - .clickable { - onClick() - }, - ) -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt deleted file mode 100644 index 4c2dba29f..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosMobileIcon.kt +++ /dev/null @@ -1,27 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp - -@Composable -fun MifosMobileIcon( - id: Int -) { - Column { - Image( - painter = painterResource(id = id), - contentDescription = null, - modifier = Modifier - .fillMaxWidth() - .align(Alignment.CenterHorizontally) - .padding(0.dp, 56.dp) - ) - } -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButton.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButton.kt deleted file mode 100644 index e54efcc52..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButton.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.layout.Row -import androidx.compose.material3.RadioButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import org.mifos.mobile.core.ui.theme.MifosMobileTheme - -@Composable -fun MifosRadioButton( - selected: Boolean, - onClick: () -> Unit, - textResId: Int -) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - RadioButton( - selected = selected, - onClick = { onClick.invoke() } - ) - Text(text = stringResource(id = textResId)) - } -} - -@Preview(showSystemUi = true) -@Composable -fun MifosRadioButtonPreview() { - MifosMobileTheme { - MifosRadioButton( - selected = false, - onClick = {}, - textResId = 1 - ) - } -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt deleted file mode 100644 index 2e3ae3957..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRadioButtonAlertDialog.kt +++ /dev/null @@ -1,86 +0,0 @@ -package org.mifos.mobile.core.ui.component - - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.RadioButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import org.mifos.mobile.core.ui.theme.MifosMobileTheme - -@Composable -fun MifosRadioButtonDialog( - titleResId: Int, - selectedItem: String, - items: Array, - selectItem: (item: String, index: Int) -> Unit, - onDismissRequest: () -> Unit, -) { - Dialog( - onDismissRequest = { onDismissRequest.invoke() } - ){ - Card { - Column(modifier = Modifier.padding(20.dp)) { - Text(text = stringResource(id = titleResId)) - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .heightIn(max = 500.dp) - ) { - itemsIndexed(items = items) { index, item -> - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .clickable { - onDismissRequest.invoke() - selectItem.invoke(item, index) - } - .fillMaxWidth() - ) { - RadioButton( - selected = (item == selectedItem), - onClick = { - onDismissRequest.invoke() - selectItem.invoke(item, index) - } - ) - Text( - text = item, - modifier = Modifier.padding(start = 4.dp) - ) - } - } - } - } - } - } -} - -@Preview -@Composable -fun PreviewRadioButtonDialog() { - MifosMobileTheme { - MifosRadioButtonDialog( - titleResId = 1, - items = arrayOf("1", "2", "3"), - selectedItem = "1", - onDismissRequest = { }, - selectItem = { _, _ ->} - ) - } -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt deleted file mode 100644 index 7ab3d7a7a..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosRoundIcon.kt +++ /dev/null @@ -1,31 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp - -@Composable -fun MifosRoundIcon( - iconId: Int, - contentDescription: String? = null, - modifier: Modifier = Modifier -) { - Surface( - color = MaterialTheme.colorScheme.surfaceVariant, - modifier = modifier - .clip(CircleShape) - ) { - Image( - modifier = Modifier.padding(all = 6.dp), - painter = painterResource(id = iconId), - contentDescription = contentDescription - ) - } -} \ No newline at end of file diff --git a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButton.kt b/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButton.kt deleted file mode 100644 index 0b6d38347..000000000 --- a/ui/src/main/java/org/mifos/mobile/core/ui/component/MifosTextButton.kt +++ /dev/null @@ -1,61 +0,0 @@ -package org.mifos.mobile.core.ui.component - -import android.graphics.drawable.Icon -import androidx.compose.foundation.layout.Row -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Edit -import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource - -@Composable -fun MifosTextButton( - modifier: Modifier = Modifier, - onClick: () -> Unit, - textResId: Int, -) { - Button( - modifier = modifier, - onClick = { onClick() }, - content = { - Text(text = stringResource(id = textResId)) - } - ) -} - -@Composable -fun MifosOutlinedTextButton( - onClick: () -> Unit, - textResId: Int, -) { - Button( - onClick = { onClick() }, - content = { - Text(text = stringResource(id = textResId)) - } - ) -} - -@Composable -fun MifosIconTextButton( - imageVector: ImageVector, - text: String, - enabled: Boolean, - onClick: () -> Unit -) { - TextButton( - onClick = { onClick.invoke() }, - enabled = enabled - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(imageVector = imageVector, contentDescription = null) - Text(text = text) - } - } -} \ No newline at end of file diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml deleted file mode 100644 index 840498f23..000000000 --- a/ui/src/main/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - No Internet - Retry - No Data - Something went wrong - \ No newline at end of file diff --git a/ui/src/test/java/org/mifos/mobile/core/ExampleUnitTest.kt b/ui/src/test/java/org/mifos/mobile/core/ExampleUnitTest.kt deleted file mode 100644 index 87e67e231..000000000 --- a/ui/src/test/java/org/mifos/mobile/core/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.mifos.mobile.core - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file