mirror of
https://github.com/openMF/mobile-wallet.git
synced 2026-02-06 11:56:48 +00:00
Merge kmm-impl into dev (#1813)
* Feat: KMP Library Setup (#1766) * Migrating from hilt to koin (This) (#1764) * Migrating from hilt to koin * Fixed Instance creation error * refactor: Removed Hilt and migrated to Koin This commit removes Hilt and migrates the project to Koin for dependency injection. The following changes were made: - Removed the `AndroidHiltConventionPlugin`. - Added the `AndroidKoinConventionPlugin`. - Updated dependencies to use Koin. - Updated KSP configuration for Koin. - Updated feature modules to use Koin. - Updated common modules to use Koin . - Removed Hilt annotations and replaced them with Koin annotations. - Updated ViewModels to use Koin for dependency injection. - Updated modules to use Koin for dependency injection. * Formatted Dependencies * migrating from hilt to koin clean up commit * Revert "migrating from hilt to koin clean up commit" This reverts commitbb63058e49. --------- Co-authored-by: Sk Niyaj Ali <niyaj639@gmail.com> * Feat: KMP Library Setup --------- Co-authored-by: Nagarjuna <99315689+Nagarjuna0033@users.noreply.github.com> * Feat: [:core:model] - Migrated to KMM (#1770) * Feat: [:core:common] KMP Migration (#1768) * Feat: [:core:common] KMP Migration * Updated Usage Declaration * Feat: [:core:datastore] - Migrated to KMP (#1769) * Feat: [:core:network] - Migrated to KMP (#1772) * Feat: [:core:network] - Migrated to KMP * Feat: [:core:data] - Migrated to KMP Library * Feat: [:core:designsystem] - Migrated to KMP with CMP Library (#1774) * Feat: [:core:ui] - Migrated to KMP with CMP Library (#1775) * Feat: [:feature:auth] - Migrated to Kotlin Multiplatform (#1782) * Feat: [:feature:auth] - Migrated to Kotlin Multiplatform * Added Support For Web * Feat: Migrated Passcode Module to KMP (#1783) * Feat: Migrated Home Module to KMP (#1784) * Feat: Migrated Edit Password Module to KMP (#1787) * Feat: Migrated FAQ module to kmp (#1786) * Feat: Migrated Settings Module to KMP (#1785) * Feat: Migrated Profile Module to KMP (#1788) * Feat: Migrated History Module to KMP (#1790) * Feat: Migrated Payments Module to KMP (#1791) * Feat: Migrated Finance Module to KMP (#1792) * Feat: Migrated Accounts Module to KMP (#1793) * Feat: Migrated Accounts Module to KMP * Updated README.md * Update README.md * Feat: Migrated Invoices Module to KMP (#1794) * Feat: Migrated KYC Module to KMP (#1798) * Migrated Notification Module to KMP (#1799) * Feat: Migrated KYC Module to KMP * Feat: Migrated Notification Module to KMP * Feat: Migrated Saved Card Module to KMP (#1800) * Feat: Migrated Receipt Module to KMP (#1801) * fix: Ios Build (#1802) * Feat: Migrated SI Module to KMP (#1803) * Feat: Migrated Request Money Module to KMP (#1807) * Feat: Migrated Send Money Module to KMP (#1808) * Feat: Migrated Make Transfer Module to KMP (#1809) * Feat: Migrated QR Module to KMP (#1810) * Feat: Migrated UPI Setup Module to KMP (#1811) * Feat: Final Clean-up For KMP (#1812) * Feat: Final Cleanup For KMP * Update README.md * Update EditPassword README.md * Update FAQ README.md * Update Finance README.md * Update History README.md * Update Home README.md * Update Invoice README.md * Update KYC README.md * Update Make Transfer README.md * Update Notification README.md * Update Payments README.md * Update Profile README.md * Update Saved Card README.md * Update Send Money README.md * Update Settings README.md * Update SI README.md * Migrating from hilt to koin (This) (#1764) * Migrating from hilt to koin * Fixed Instance creation error * refactor: Removed Hilt and migrated to Koin This commit removes Hilt and migrates the project to Koin for dependency injection. The following changes were made: - Removed the `AndroidHiltConventionPlugin`. - Added the `AndroidKoinConventionPlugin`. - Updated dependencies to use Koin. - Updated KSP configuration for Koin. - Updated feature modules to use Koin. - Updated common modules to use Koin . - Removed Hilt annotations and replaced them with Koin annotations. - Updated ViewModels to use Koin for dependency injection. - Updated modules to use Koin for dependency injection. * Formatted Dependencies * migrating from hilt to koin clean up commit * Revert "migrating from hilt to koin clean up commit" This reverts commitbb63058e49. --------- Co-authored-by: Sk Niyaj Ali <niyaj639@gmail.com> * Profile UI redesign (#1767) * Refactor Profile UI * Fixed Build Issue * Profile UI Bug Fix & Improvement * added placeholder for when uri is null cleanup fix spotless test failure * Fix - CI Build Issue --------- Co-authored-by: Sk Niyaj Ali <niyaj639@gmail.com> * refactor: Redesign payment screen (#1773) * refactor: Redesign payment screen * resolved detekt error * refactor : changed current theme instead of using NewUi * resolved spotless errors * refactor: Redesign finance screen (#1777) * refactor: Redesign payment screen * resolved detekt error * refactor : changed current theme instead of using NewUi * resolved spotless errors * refactor: Redesign finance screen UI * resolved spotless errors * resolved conflicts * changed structure of accounts screen * refactor padding values in finance screen * fix: dark theme colors (#1789) * fix: dark theme colors * fixed edit icon tint * Fix invoice api (#1797) * Redesign requeset screen UI * fix MissingKoinDefinitionException * removed comments and fixed share qr code bug * fix: Invoice APIs * update readme file (#1804) * update readme file * update readme file * update readme file with how to contribute * Add branch policy (#1805) * update readme file * update readme file * update readme file with how to contribute * update readme file with how to contribute * update readme file with branch Policy --------- Co-authored-by: Rajan Maurya <therajanmaurya@users.noreply.github.com> * Migrating from hilt to koin (This) (#1764) * Migrating from hilt to koin * Fixed Instance creation error * refactor: Removed Hilt and migrated to Koin This commit removes Hilt and migrates the project to Koin for dependency injection. The following changes were made: - Removed the `AndroidHiltConventionPlugin`. - Added the `AndroidKoinConventionPlugin`. - Updated dependencies to use Koin. - Updated KSP configuration for Koin. - Updated feature modules to use Koin. - Updated common modules to use Koin . - Removed Hilt annotations and replaced them with Koin annotations. - Updated ViewModels to use Koin for dependency injection. - Updated modules to use Koin for dependency injection. * Formatted Dependencies * migrating from hilt to koin clean up commit * Revert "migrating from hilt to koin clean up commit" This reverts commitbb63058e49. --------- Co-authored-by: Sk Niyaj Ali <niyaj639@gmail.com> * Merge kmm-impl to dev --------- Co-authored-by: Nagarjuna <99315689+Nagarjuna0033@users.noreply.github.com> Co-authored-by: Rajan Maurya <therajanmaurya@users.noreply.github.com> Co-authored-by: Pronay Sarker <pronaycoding@gmail.com> Co-authored-by: kapmaurya <152150716+kapmaurya@users.noreply.github.com>
This commit is contained in:
parent
49101cde9a
commit
3782fd0d6f
32
.github/workflows/feature_branch_ci.yml
vendored
32
.github/workflows/feature_branch_ci.yml
vendored
@ -1,32 +0,0 @@
|
|||||||
name: Mobile-Wallet CI[Feature]
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
- '!dev'
|
|
||||||
- '!master'
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build APK
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Set up JDK
|
|
||||||
- name: Set Up JDK 17
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
# Install NDK
|
|
||||||
- name: Install NDK
|
|
||||||
run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT}
|
|
||||||
|
|
||||||
# Update Gradle Permission
|
|
||||||
- name: Change gradlew Permission
|
|
||||||
run: chmod +x gradlew
|
|
||||||
|
|
||||||
# Build App
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew assemble
|
|
||||||
11
.github/workflows/master_dev_ci.yml
vendored
11
.github/workflows/master_dev_ci.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
|||||||
- name: Check Dependency Guard
|
- name: Check Dependency Guard
|
||||||
id: dependencyguard_verify
|
id: dependencyguard_verify
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew dependencyGuard
|
run: ./gradlew :mifospay-android:dependencyGuard
|
||||||
|
|
||||||
- name: Prevent updating Dependency Guard baselines if this is a fork
|
- name: Prevent updating Dependency Guard baselines if this is a fork
|
||||||
id: checkfork_dependencyguard
|
id: checkfork_dependencyguard
|
||||||
@ -88,7 +88,7 @@ jobs:
|
|||||||
id: dependencyguard_baseline
|
id: dependencyguard_baseline
|
||||||
if: steps.dependencyguard_verify.outcome == 'failure' && github.event_name == 'pull_request'
|
if: steps.dependencyguard_verify.outcome == 'failure' && github.event_name == 'pull_request'
|
||||||
run: |
|
run: |
|
||||||
./gradlew dependencyGuardBaseline
|
./gradlew :mifospay-android:dependencyGuardBaseline
|
||||||
|
|
||||||
- name: Push new Dependency Guard baselines if available
|
- name: Push new Dependency Guard baselines if available
|
||||||
uses: stefanzweifel/git-auto-commit-action@v5
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
@ -109,7 +109,8 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
./gradlew testDemoDebug :lint:test :mifospay:lintProdRelease :lint:lint
|
./gradlew :mifospay-android:testDemoDebug
|
||||||
|
# ./gradlew testDemoDebug :lint:test :mifospay-android:lintProdRelease :lint:lint
|
||||||
- name: Upload reports
|
- name: Upload reports
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@ -130,12 +131,12 @@ jobs:
|
|||||||
java-version: 17
|
java-version: 17
|
||||||
|
|
||||||
- name: Build APKs
|
- name: Build APKs
|
||||||
run: ./gradlew :mifospay:assembleDemoDebug
|
run: ./gradlew :mifospay-android:assembleDemoDebug
|
||||||
|
|
||||||
- name: Check badging
|
- name: Check badging
|
||||||
# This step is allowed to fail, as it's not critical for the build
|
# This step is allowed to fail, as it's not critical for the build
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew :mifospay:checkProdReleaseBadging
|
run: ./gradlew :mifospay-android:checkProdReleaseBadging
|
||||||
|
|
||||||
- name: Upload APKs
|
- name: Upload APKs
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|||||||
70
.run/mifospay-android.run.xml
Normal file
70
.run/mifospay-android.run.xml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="mifospay-android" type="AndroidRunConfigurationType" factoryName="Android App" activateToolWindowBeforeRun="false">
|
||||||
|
<module name="mobile-wallet.mifospay-android.main" />
|
||||||
|
<option name="DEPLOY" value="true" />
|
||||||
|
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
|
||||||
|
<option name="DEPLOY_AS_INSTANT" value="false" />
|
||||||
|
<option name="ARTIFACT_NAME" value="" />
|
||||||
|
<option name="PM_INSTALL_OPTIONS" value="" />
|
||||||
|
<option name="ALL_USERS" value="false" />
|
||||||
|
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
|
||||||
|
<option name="CLEAR_APP_STORAGE" value="false" />
|
||||||
|
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
|
||||||
|
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
|
||||||
|
<option name="MODE" value="default_activity" />
|
||||||
|
<option name="RESTORE_ENABLED" value="false" />
|
||||||
|
<option name="RESTORE_FILE" value="" />
|
||||||
|
<option name="CLEAR_LOGCAT" value="false" />
|
||||||
|
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
|
||||||
|
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
|
||||||
|
<option name="DEBUGGER_TYPE" value="Auto" />
|
||||||
|
<Auto>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Auto>
|
||||||
|
<Hybrid>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Hybrid>
|
||||||
|
<Java>
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Java>
|
||||||
|
<Native>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||||
|
<option name="DEBUG_SANDBOX_SDK" value="false" />
|
||||||
|
</Native>
|
||||||
|
<Profilers>
|
||||||
|
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
|
||||||
|
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
|
||||||
|
</Profilers>
|
||||||
|
<option name="DEEP_LINK" value="" />
|
||||||
|
<option name="ACTIVITY_CLASS" value="" />
|
||||||
|
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
|
||||||
|
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
24
.run/mifospay-desktop.run.xml
Normal file
24
.run/mifospay-desktop.run.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="mifospay-desktop" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="-DmainClass=MainKt --quiet" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value=":mifospay-desktop:desktopRun" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
24
.run/mifospay-web-js.run.xml
Normal file
24
.run/mifospay-web-js.run.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="mifospay-web-js" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value=":mifospay-web:jsBrowserRun" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
24
.run/mifospay-web-wasm.run.xml
Normal file
24
.run/mifospay-web-wasm.run.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="mifospay-web-wasm" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value=":mifospay-web:wasmJsBrowserRun" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
91
README.md
91
README.md
@ -6,24 +6,103 @@ Mobile Wallet is an Android-based framework for mobile wallets based on top of <
|
|||||||
<a href='https://github.com/openMF/mobile-wallet/wiki/Architecture'>clean architecture</a> and contains a core library module
|
<a href='https://github.com/openMF/mobile-wallet/wiki/Architecture'>clean architecture</a> and contains a core library module
|
||||||
that can be used as a dependency in any other wallet based project. It is developed at <a href='https://mifos.org/'>MIFOS</a> together with a global community.
|
that can be used as a dependency in any other wallet based project. It is developed at <a href='https://mifos.org/'>MIFOS</a> together with a global community.
|
||||||
|
|
||||||
|
# Run the project
|
||||||
|

|
||||||
|
- To run the android-app select the `mifospay-android` run configuration and click run.
|
||||||
|
- To run the desktop-app select the `mifospay-desktop` run configuration and click run.
|
||||||
|
- To run the web-app-js select the `mifospay-web-js` run configuration and click run.
|
||||||
|
|
||||||
|
## KMP Status for modules
|
||||||
|
|
||||||
|
| Module | Progress | Desktop supported | Android supported | iOS supported | Web supported(JS) | Web supported(WASM-JS) |
|
||||||
|
|-------------------------------|----------|-------------------|-------------------|---------------|-------------------|-------------------------|
|
||||||
|
| mifospay-android | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
|
||||||
|
| mifospay-desktop | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
|
||||||
|
| mifospay-web | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
|
||||||
|
| mifospay-ios | NO OP | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||||
|
| :core:analytics | Done | ❌ | ✔️ | ❔ | ❌ | ❔ |
|
||||||
|
| :core:common | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:data | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:datastore | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:datastore-proto | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:designsystem | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:domain | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:model | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:network | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :core:ui | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:auth | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:editpassword | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:faq | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:history | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:home | Done | ✅ | ✅ | ❔ | ✅ | ❌ |
|
||||||
|
| :feature:profile | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:settings | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:payments | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:finance | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:account | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:invoices | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:kyc | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:make-transfer | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:merchants | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:notification | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:qr | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:receipt | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:request-money | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:saved-cards | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:send-money | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:standing-instruction | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
| :feature:upi-setup | Done | ✅ | ✅ | ❔ | ✅ | ✅ |
|
||||||
|
|
||||||
|
✅: Functioning properly
|
||||||
|
❔: Not yet tested, but expected to work
|
||||||
|
✔️: Successfully compiled
|
||||||
|
❌: Not functioning, requires further attention
|
||||||
|
|
||||||
## Notice
|
## Notice
|
||||||
|
|
||||||
:warning: We are fully committed to implement [Jetpack Compose](https://developer.android.com/jetpack/compose) and moving ourself to support
|
:warning: We are fully committed to implement [Jetpack Compose](https://developer.android.com/jetpack/compose) and moving ourself to support
|
||||||
`kotlin multi-platform`. **If you are sending any PR regarding `XML changes` we will `not` consider at this moment but converting XML to jetpack compose are most welcome.** If you sending any PR regarding logical changes in Activity/Fragment you are most welcome.
|
`kotlin multi-platform`. **If you are sending any PR regarding `XML changes` we will `not` consider at this moment but converting XML to jetpack compose are most welcome.** If you sending any PR regarding logical changes in Activity/Fragment you are most welcome.
|
||||||
|
|
||||||
|
|
||||||
|
| Development | Chat |
|
||||||
Development | Chat |
|
|--------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|-----------------|-----------------|
|
| ![Mobile-Wallet CI[Master/Dev]](https://github.com/openMF/mobile-wallet/workflows/Mobile-Wallet%20CI%5BMaster/Dev%5D/badge.svg?branch=dev) | [](https://mifos.slack.com/) |
|
||||||
![Mobile-Wallet CI[Master/Dev]](https://github.com/openMF/mobile-wallet/workflows/Mobile-Wallet%20CI%5BMaster/Dev%5D/badge.svg?branch=dev) | [](https://mifos.slack.com/) |
|
|
||||||
|
|
||||||
|
|
||||||
## Join Us on Slack
|
## Join Us on Slack
|
||||||
|
|
||||||
Mifos boasts an active and vibrant contributor community, Please join us on [slack](https://join.slack.com/t/mifos/shared_invite/zt-2f4nr6tk3-ZJlHMi1lc0R19FFEHxdvng). Once you've joined the mifos slack community, please join the `#mobile-wallet` channel to engage with mobile-wallet development. If you encounter any difficulties joining our Slack channel, please don't hesitate to open an issue. This will allow us to assist you promptly or send you an invitation.
|
Mifos boasts an active and vibrant contributor community, Please join us on [slack](https://join.slack.com/t/mifos/shared_invite/zt-2f4nr6tk3-ZJlHMi1lc0R19FFEHxdvng). Once you've joined the mifos slack community, please join the `#mobile-wallet` channel to engage with mobile-wallet development. If you encounter any difficulties joining our Slack channel, please don't hesitate to open an issue. This will allow us to assist you promptly or send you an invitation.
|
||||||
|
|
||||||
### [How to Contribute](https://github.com/openMF/mobile-wallet/wiki/How-to-Contribute)
|
|
||||||
### [Branch Policy](https://github.com/openMF/mobile-wallet/wiki/Branch-Policy)
|
## How to Contribute
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to the Mobile Wallet project by Mifos! We welcome all contributions and encourage you to follow these guidelines to ensure a smooth and efficient collaboration process.
|
||||||
|
|
||||||
|
The issues should be raised via the GitHub issue tracker. For Issue tracker guidelines please click <a href="https://github.com/openMF/mobile-wallet/blob/master/.github/CONTRIBUTING.md#issue-tracker">here</a>. All fixes should be proposed via pull requests. For pull request guidelines please click <a href="https://github.com/openMF/mobile-wallet/blob/master/.github/CONTRIBUTING.md#pull-requests">here</a>. For commit style guidelines please click <a href="https://github.com/openMF/mobile-wallet/wiki/Commit-style-guide">here</a>.
|
||||||
|
|
||||||
|
### Branch Policy
|
||||||
|
|
||||||
|
We have the following branches :
|
||||||
|
|
||||||
|
* **dev**
|
||||||
|
All the contributions should be pushed to this branch. If you're making a contribution,
|
||||||
|
you are supposed to make a pull request to _dev_.
|
||||||
|
Please make sure it passes a build check on Travis.
|
||||||
|
|
||||||
|
It is advisable to clone only the development branch using the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone -b <branch> <remote_repo>
|
||||||
|
```
|
||||||
|
|
||||||
|
With Git 1.7.10 and later, add --single-branch to prevent fetching of all branches. Example, with development branch:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone -b dev --single-branch https://github.com/username/mobile-wallet.git`
|
||||||
|
```
|
||||||
|
|
||||||
|
* **master**
|
||||||
|
The master branch contains all the stable and bug-free working code. The development branch once complete will be merged with this branch.
|
||||||
|
|
||||||
### Demo credentials
|
### Demo credentials
|
||||||
Fineract Instance: demo.mifos.io
|
Fineract Instance: demo.mifos.io
|
||||||
|
|||||||
@ -23,11 +23,8 @@ dependencies {
|
|||||||
compileOnly(libs.android.gradlePlugin)
|
compileOnly(libs.android.gradlePlugin)
|
||||||
compileOnly(libs.android.tools.common)
|
compileOnly(libs.android.tools.common)
|
||||||
compileOnly(libs.compose.gradlePlugin)
|
compileOnly(libs.compose.gradlePlugin)
|
||||||
compileOnly(libs.firebase.crashlytics.gradlePlugin)
|
|
||||||
compileOnly(libs.firebase.performance.gradlePlugin)
|
|
||||||
compileOnly(libs.kotlin.gradlePlugin)
|
compileOnly(libs.kotlin.gradlePlugin)
|
||||||
compileOnly(libs.ksp.gradlePlugin)
|
compileOnly(libs.ksp.gradlePlugin)
|
||||||
compileOnly(libs.room.gradlePlugin)
|
|
||||||
compileOnly(libs.detekt.gradlePlugin)
|
compileOnly(libs.detekt.gradlePlugin)
|
||||||
compileOnly(libs.ktlint.gradlePlugin)
|
compileOnly(libs.ktlint.gradlePlugin)
|
||||||
compileOnly(libs.spotless.gradle)
|
compileOnly(libs.spotless.gradle)
|
||||||
@ -43,6 +40,7 @@ tasks {
|
|||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
plugins {
|
plugins {
|
||||||
|
// Android Plugins
|
||||||
register("androidApplicationCompose") {
|
register("androidApplicationCompose") {
|
||||||
id = "mifospay.android.application.compose"
|
id = "mifospay.android.application.compose"
|
||||||
implementationClass = "AndroidApplicationComposeConventionPlugin"
|
implementationClass = "AndroidApplicationComposeConventionPlugin"
|
||||||
@ -51,46 +49,28 @@ gradlePlugin {
|
|||||||
id = "mifospay.android.application"
|
id = "mifospay.android.application"
|
||||||
implementationClass = "AndroidApplicationConventionPlugin"
|
implementationClass = "AndroidApplicationConventionPlugin"
|
||||||
}
|
}
|
||||||
register("androidLibraryCompose") {
|
|
||||||
id = "mifospay.android.library.compose"
|
|
||||||
implementationClass = "AndroidLibraryComposeConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidLibrary") {
|
|
||||||
id = "mifospay.android.library"
|
|
||||||
implementationClass = "AndroidLibraryConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidFeature") {
|
|
||||||
id = "mifospay.android.feature"
|
|
||||||
implementationClass = "AndroidFeatureConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidTest") {
|
|
||||||
id = "mifospay.android.test"
|
|
||||||
implementationClass = "AndroidTestConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidRoom") {
|
|
||||||
id = "mifospay.android.room"
|
|
||||||
implementationClass = "AndroidRoomConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidFirebase") {
|
|
||||||
id = "mifospay.android.application.firebase"
|
|
||||||
implementationClass = "AndroidApplicationFirebaseConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidLint") {
|
|
||||||
id = "mifospay.android.lint"
|
|
||||||
implementationClass = "AndroidLintConventionPlugin"
|
|
||||||
}
|
|
||||||
register("jvmLibrary") {
|
|
||||||
id = "mifospay.jvm.library"
|
|
||||||
implementationClass = "JvmLibraryConventionPlugin"
|
|
||||||
}
|
|
||||||
register("androidFlavors") {
|
register("androidFlavors") {
|
||||||
id = "mifospay.android.application.flavors"
|
id = "mifospay.android.application.flavors"
|
||||||
implementationClass = "AndroidApplicationFlavorsConventionPlugin"
|
implementationClass = "AndroidApplicationFlavorsConventionPlugin"
|
||||||
}
|
}
|
||||||
register("androidKoin") {
|
|
||||||
id = "mifospay.android.koin"
|
// KMP & CMP Plugins
|
||||||
implementationClass = "AndroidKoinConventionPlugin"
|
register("cmpFeature") {
|
||||||
|
id = "mifospay.cmp.feature"
|
||||||
|
implementationClass = "CMPFeatureConventionPlugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register("kmpKoin") {
|
||||||
|
id = "mifospay.kmp.koin"
|
||||||
|
implementationClass = "KMPKoinConventionPlugin"
|
||||||
|
}
|
||||||
|
register("kmpLibrary") {
|
||||||
|
id = "mifospay.kmp.library"
|
||||||
|
implementationClass = "KMPLibraryConventionPlugin"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static Analysis & Formatting Plugins
|
||||||
register("detekt") {
|
register("detekt") {
|
||||||
id = "mifos.detekt.plugin"
|
id = "mifos.detekt.plugin"
|
||||||
implementationClass = "MifosDetektConventionPlugin"
|
implementationClass = "MifosDetektConventionPlugin"
|
||||||
|
|||||||
@ -15,11 +15,9 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
|
|||||||
with(pluginManager) {
|
with(pluginManager) {
|
||||||
apply("com.android.application")
|
apply("com.android.application")
|
||||||
apply("org.jetbrains.kotlin.android")
|
apply("org.jetbrains.kotlin.android")
|
||||||
apply("mifospay.android.lint")
|
|
||||||
apply("com.dropbox.dependency-guard")
|
apply("com.dropbox.dependency-guard")
|
||||||
apply("mifos.detekt.plugin")
|
apply("mifos.detekt.plugin")
|
||||||
apply("mifos.spotless.plugin")
|
apply("mifos.spotless.plugin")
|
||||||
apply("mifos.ktlint.plugin")
|
|
||||||
apply("mifos.git.hooks")
|
apply("mifos.git.hooks")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
import com.android.build.api.dsl.ApplicationExtension
|
|
||||||
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.gradle.kotlin.dsl.dependencies
|
|
||||||
import org.mifospay.libs
|
|
||||||
|
|
||||||
class AndroidApplicationFirebaseConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
with(pluginManager) {
|
|
||||||
apply("com.google.gms.google-services")
|
|
||||||
apply("com.google.firebase.firebase-perf")
|
|
||||||
apply("com.google.firebase.crashlytics")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
val bom = libs.findLibrary("firebase-bom").get()
|
|
||||||
add("implementation", platform(bom))
|
|
||||||
"implementation"(libs.findLibrary("firebase.analytics").get())
|
|
||||||
"implementation"(libs.findLibrary("firebase.performance").get())
|
|
||||||
"implementation"(libs.findLibrary("firebase.crashlytics").get())
|
|
||||||
"implementation"(libs.findLibrary("firebase.cloud.messaging").get())
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<ApplicationExtension> {
|
|
||||||
buildTypes.configureEach {
|
|
||||||
// Disable the Crashlytics mapping file upload. This feature should only be
|
|
||||||
// enabled if a Firebase backend is available and configured in
|
|
||||||
// google-services.json.
|
|
||||||
configure<CrashlyticsExtension> {
|
|
||||||
mappingFileUploadEnabled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
|
|
||||||
import com.android.build.gradle.LibraryExtension
|
|
||||||
import com.google.devtools.ksp.gradle.KspExtension
|
|
||||||
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.mifospay.libs
|
|
||||||
|
|
||||||
class AndroidFeatureConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
pluginManager.apply {
|
|
||||||
apply("mifospay.android.library")
|
|
||||||
apply("mifospay.android.koin")
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<LibraryExtension> {
|
|
||||||
defaultConfig {
|
|
||||||
// set custom test runner
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
|
||||||
testOptions.animationsDisabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<KspExtension> {
|
|
||||||
arg("KOIN_USE_COMPOSE_VIEWMODEL","true")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
add("implementation", project(":core:ui"))
|
|
||||||
add("implementation", project(":core:designsystem"))
|
|
||||||
add("implementation", project(":core:data"))
|
|
||||||
|
|
||||||
add("implementation", project(":libs:material3-navigation"))
|
|
||||||
|
|
||||||
add("implementation", libs.findLibrary("androidx.navigation.compose").get())
|
|
||||||
add("implementation", libs.findLibrary("kotlinx.collections.immutable").get())
|
|
||||||
add("implementation", libs.findLibrary("androidx.lifecycle.runtimeCompose").get())
|
|
||||||
add("implementation", libs.findLibrary("androidx.lifecycle.viewModelCompose").get())
|
|
||||||
add("implementation", libs.findLibrary("androidx.tracing.ktx").get())
|
|
||||||
|
|
||||||
add("implementation", platform(libs.findLibrary("koin-bom").get()))
|
|
||||||
add("implementation", libs.findLibrary("koin-android").get())
|
|
||||||
add("implementation", libs.findLibrary("koin.androidx.compose").get())
|
|
||||||
|
|
||||||
add("implementation", libs.findLibrary("koin.android").get())
|
|
||||||
add("implementation", libs.findLibrary("koin.androidx.navigation").get())
|
|
||||||
add("implementation", libs.findLibrary("koin.androidx.compose").get())
|
|
||||||
add("implementation", libs.findLibrary("koin.core.viewmodel").get())
|
|
||||||
|
|
||||||
add("androidTestImplementation", libs.findLibrary("androidx.lifecycle.runtimeTesting").get())
|
|
||||||
|
|
||||||
add("testImplementation", kotlin("test"))
|
|
||||||
|
|
||||||
add("testImplementation", libs.findLibrary("koin.test").get())
|
|
||||||
add("testImplementation", libs.findLibrary("koin.test.junit4").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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
import com.google.devtools.ksp.gradle.KspExtension
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.gradle.kotlin.dsl.dependencies
|
|
||||||
import org.mifospay.libs
|
|
||||||
|
|
||||||
|
|
||||||
class AndroidKoinConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
with(pluginManager) {
|
|
||||||
apply("com.google.devtools.ksp")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
val bom = libs.findLibrary("koin-bom").get()
|
|
||||||
add("implementation", platform(bom))
|
|
||||||
add("implementation", libs.findLibrary("koin.core").get())
|
|
||||||
|
|
||||||
add("implementation", libs.findLibrary("koin.annotations").get())
|
|
||||||
add("ksp", libs.findLibrary("koin.ksp.compiler").get())
|
|
||||||
|
|
||||||
|
|
||||||
add("testImplementation", libs.findLibrary("koin.test").get())
|
|
||||||
add("testImplementation", libs.findLibrary("koin.test.junit4").get())
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<KspExtension> {
|
|
||||||
arg("KOIN_CONFIG_CHECK","true")
|
|
||||||
arg("USE_COMPOSE_VIEWMODEL", "false")
|
|
||||||
arg("KOIN_USE_COMPOSE_VIEWMODEL", "true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import com.android.build.gradle.LibraryExtension
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.apply
|
|
||||||
import org.gradle.kotlin.dsl.getByType
|
|
||||||
import org.mifospay.configureAndroidCompose
|
|
||||||
|
|
||||||
class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
pluginManager.apply("com.android.library")
|
|
||||||
apply(plugin = "org.jetbrains.kotlin.plugin.compose")
|
|
||||||
|
|
||||||
val extension = extensions.getByType<LibraryExtension>()
|
|
||||||
configureAndroidCompose(extension)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
import com.android.build.api.variant.LibraryAndroidComponentsExtension
|
|
||||||
import com.android.build.gradle.LibraryExtension
|
|
||||||
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.mifospay.configureFlavors
|
|
||||||
import org.mifospay.configureKotlinAndroid
|
|
||||||
import org.mifospay.configurePrintApksTask
|
|
||||||
import org.mifospay.disableUnnecessaryAndroidTests
|
|
||||||
import org.mifospay.libs
|
|
||||||
|
|
||||||
class AndroidLibraryConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
with(pluginManager) {
|
|
||||||
apply("com.android.library")
|
|
||||||
apply("org.jetbrains.kotlin.android")
|
|
||||||
apply("mifospay.android.lint")
|
|
||||||
apply("mifos.detekt.plugin")
|
|
||||||
apply("mifos.spotless.plugin")
|
|
||||||
apply("mifos.ktlint.plugin")
|
|
||||||
apply("mifospay.android.koin")
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<LibraryExtension> {
|
|
||||||
configureKotlinAndroid(this)
|
|
||||||
defaultConfig.targetSdk = 34
|
|
||||||
testOptions.animationsDisabled = true
|
|
||||||
configureFlavors(this)
|
|
||||||
// The resource prefix is derived from the module name,
|
|
||||||
// so resources inside ":core:module1" must be prefixed with "core_module1_"
|
|
||||||
resourcePrefix = path.split("""\W""".toRegex()).drop(1).distinct().joinToString(separator = "_").lowercase() + "_"
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<LibraryAndroidComponentsExtension> {
|
|
||||||
configurePrintApksTask(this)
|
|
||||||
disableUnnecessaryAndroidTests(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
add("testImplementation", kotlin("test"))
|
|
||||||
add("implementation", libs.findLibrary("androidx.tracing.ktx").get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
import com.android.build.api.dsl.ApplicationExtension
|
|
||||||
import com.android.build.api.dsl.LibraryExtension
|
|
||||||
import com.android.build.api.dsl.Lint
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class AndroidLintConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
when {
|
|
||||||
pluginManager.hasPlugin("com.android.application") ->
|
|
||||||
configure<ApplicationExtension> { lint(Lint::configure) }
|
|
||||||
|
|
||||||
pluginManager.hasPlugin("com.android.library") ->
|
|
||||||
configure<LibraryExtension> { lint(Lint::configure) }
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
pluginManager.apply("com.android.lint")
|
|
||||||
configure<Lint>(Lint::configure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Lint.configure() {
|
|
||||||
xmlReport = true
|
|
||||||
checkDependencies = true
|
|
||||||
abortOnError = false
|
|
||||||
// Disable this rule until we ship the libraries to some maven.
|
|
||||||
disable += "ResourceName"
|
|
||||||
baseline = File("lint-baseline.xml")
|
|
||||||
explainIssues = true
|
|
||||||
htmlReport = true
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
import androidx.room.gradle.RoomExtension
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.gradle.kotlin.dsl.dependencies
|
|
||||||
import org.mifospay.libs
|
|
||||||
|
|
||||||
class AndroidRoomConventionPlugin : Plugin<Project> {
|
|
||||||
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
pluginManager.apply("androidx.room")
|
|
||||||
pluginManager.apply("com.google.devtools.ksp")
|
|
||||||
|
|
||||||
extensions.configure<RoomExtension> {
|
|
||||||
// The schemas directory contains a schema file for each version of the Room database.
|
|
||||||
// This is required to enable Room auto migrations.
|
|
||||||
// See https://developer.android.com/reference/kotlin/androidx/room/AutoMigration.
|
|
||||||
schemaDirectory("$projectDir/schemas")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
add("implementation", libs.findLibrary("room.runtime").get())
|
|
||||||
add("implementation", libs.findLibrary("room.ktx").get())
|
|
||||||
add("ksp", libs.findLibrary("room.compiler").get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import com.android.build.gradle.TestExtension
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.kotlin.dsl.configure
|
|
||||||
import org.mifospay.configureKotlinAndroid
|
|
||||||
|
|
||||||
class AndroidTestConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
with(pluginManager) {
|
|
||||||
apply("com.android.test")
|
|
||||||
apply("org.jetbrains.kotlin.android")
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions.configure<TestExtension> {
|
|
||||||
configureKotlinAndroid(this)
|
|
||||||
defaultConfig.targetSdk = 34
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.mifospay.libs
|
||||||
|
|
||||||
|
class CMPFeatureConventionPlugin : Plugin<Project> {
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
pluginManager.apply {
|
||||||
|
apply("mifospay.kmp.library")
|
||||||
|
apply("mifospay.kmp.koin")
|
||||||
|
apply("org.jetbrains.kotlin.plugin.compose")
|
||||||
|
apply("org.jetbrains.compose")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
add("commonMainImplementation", project(":core:ui"))
|
||||||
|
add("commonMainImplementation", project(":core:designsystem"))
|
||||||
|
add("commonMainImplementation", project(":core:data"))
|
||||||
|
|
||||||
|
add("commonMainImplementation", libs.findLibrary("koin.compose").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("koin.compose.viewmodel").get())
|
||||||
|
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.composeRuntime").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.composeViewmodel").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.lifecycleViewmodel").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.lifecycleViewmodelSavedState").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.savedstate").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.bundle").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("jb.composeNavigation").get())
|
||||||
|
add("commonMainImplementation", libs.findLibrary("kotlinx.collections.immutable").get())
|
||||||
|
|
||||||
|
add("androidMainImplementation", libs.findLibrary("androidx.lifecycle.runtimeCompose").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("androidx.lifecycle.viewModelCompose").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("androidx.tracing.ktx").get())
|
||||||
|
|
||||||
|
add("androidMainImplementation", platform(libs.findLibrary("koin-bom").get()))
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin-android").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin.androidx.compose").get())
|
||||||
|
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin.android").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin.androidx.navigation").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin.androidx.compose").get())
|
||||||
|
add("androidMainImplementation", libs.findLibrary("koin.core.viewmodel").get())
|
||||||
|
|
||||||
|
add("androidTestImplementation", libs.findLibrary("koin.test.junit4").get())
|
||||||
|
|
||||||
|
add("androidInstrumentedTestImplementation", libs.findLibrary("androidx.navigation.testing").get())
|
||||||
|
add("androidInstrumentedTestImplementation", libs.findLibrary("androidx.compose.ui.test").get())
|
||||||
|
add("androidInstrumentedTestImplementation", libs.findLibrary("androidx.lifecycle.runtimeTesting").get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.mifospay.configureKotlinJvm
|
|
||||||
|
|
||||||
class JvmLibraryConventionPlugin : Plugin<Project> {
|
|
||||||
override fun apply(target: Project) {
|
|
||||||
with(target) {
|
|
||||||
with(pluginManager) {
|
|
||||||
apply("org.jetbrains.kotlin.jvm")
|
|
||||||
apply("mifospay.android.lint")
|
|
||||||
}
|
|
||||||
configureKotlinJvm()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import com.google.devtools.ksp.gradle.KspExtension
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.mifospay.libs
|
||||||
|
|
||||||
|
|
||||||
|
class KMPKoinConventionPlugin : Plugin<Project> {
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
with(pluginManager) {
|
||||||
|
apply("com.google.devtools.ksp")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val bom = libs.findLibrary("koin-bom").get()
|
||||||
|
add("commonMainImplementation", platform(bom))
|
||||||
|
add("commonMainImplementation", libs.findLibrary("koin.core").get())
|
||||||
|
|
||||||
|
add("commonMainImplementation", libs.findLibrary("koin.annotations").get())
|
||||||
|
add("kspCommonMainMetadata", libs.findLibrary("koin.ksp.compiler").get())
|
||||||
|
|
||||||
|
add("commonTestImplementation", libs.findLibrary("koin.test").get())
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.configure<KspExtension> {
|
||||||
|
arg("KOIN_CONFIG_CHECK","true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
import com.android.build.gradle.LibraryExtension
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.mifospay.configureFlavors
|
||||||
|
import org.mifospay.configureKotlinAndroid
|
||||||
|
import org.mifospay.configureKotlinMultiplatform
|
||||||
|
import org.mifospay.libs
|
||||||
|
|
||||||
|
class KMPLibraryConventionPlugin: Plugin<Project> {
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
with(pluginManager) {
|
||||||
|
apply("com.android.library")
|
||||||
|
apply("org.jetbrains.kotlin.multiplatform")
|
||||||
|
apply("mifospay.kmp.koin")
|
||||||
|
apply("mifos.detekt.plugin")
|
||||||
|
apply("mifos.spotless.plugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
configureKotlinMultiplatform()
|
||||||
|
|
||||||
|
extensions.configure<LibraryExtension> {
|
||||||
|
configureKotlinAndroid(this)
|
||||||
|
defaultConfig.targetSdk = 34
|
||||||
|
configureFlavors(this)
|
||||||
|
// The resource prefix is derived from the module name,
|
||||||
|
// so resources inside ":core:module1" must be prefixed with "core_module1_"
|
||||||
|
resourcePrefix = path
|
||||||
|
.split("""\W""".toRegex())
|
||||||
|
.drop(1).distinct()
|
||||||
|
.joinToString(separator = "_")
|
||||||
|
.lowercase() + "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
add("commonTestImplementation", libs.findLibrary("kotlin.test").get())
|
||||||
|
add("commonTestImplementation", libs.findLibrary("kotlinx.coroutines.test").get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,11 +5,9 @@ import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.kotlin.dsl.dependencies
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
import org.gradle.kotlin.dsl.named
|
import org.gradle.kotlin.dsl.named
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
||||||
|
|
||||||
internal fun Project.configureDetekt(extension: DetektExtension) = extension.apply {
|
internal fun Project.configureDetekt(extension: DetektExtension) = extension.apply {
|
||||||
tasks.named<Detekt>("detekt") {
|
tasks.named<Detekt>("detekt") {
|
||||||
jvmTarget = "17"
|
|
||||||
reports {
|
reports {
|
||||||
xml.required.set(true)
|
xml.required.set(true)
|
||||||
html.required.set(true)
|
html.required.set(true)
|
||||||
|
|||||||
@ -10,9 +10,6 @@ import org.gradle.kotlin.dsl.dependencies
|
|||||||
import org.gradle.kotlin.dsl.provideDelegate
|
import org.gradle.kotlin.dsl.provideDelegate
|
||||||
import org.gradle.kotlin.dsl.withType
|
import org.gradle.kotlin.dsl.withType
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +34,7 @@ internal fun Project.configureKotlinAndroid(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configureKotlin<KotlinAndroidProjectExtension>()
|
configureKotlin()
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get())
|
add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get())
|
||||||
@ -55,29 +52,26 @@ internal fun Project.configureKotlinJvm() {
|
|||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
configureKotlin<KotlinJvmProjectExtension>()
|
configureKotlin()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure base Kotlin options
|
* Configure base Kotlin options
|
||||||
*/
|
*/
|
||||||
private inline fun <reified T : KotlinTopLevelExtension> Project.configureKotlin() = configure<T> {
|
private fun Project.configureKotlin() {
|
||||||
|
// Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
compilerOptions {
|
||||||
|
// Set JVM target to 17
|
||||||
|
jvmTarget = JvmTarget.JVM_17
|
||||||
// Treat all Kotlin warnings as errors (disabled by default)
|
// Treat all Kotlin warnings as errors (disabled by default)
|
||||||
// Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
|
// Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
|
||||||
val warningsAsErrors: String? by project
|
val warningsAsErrors: String? by project
|
||||||
when (this) {
|
|
||||||
is KotlinAndroidProjectExtension -> compilerOptions
|
|
||||||
is KotlinJvmProjectExtension -> compilerOptions
|
|
||||||
else -> TODO("Unsupported project extension $this ${T::class}")
|
|
||||||
}.apply {
|
|
||||||
jvmTarget = JvmTarget.JVM_17
|
|
||||||
allWarningsAsErrors = warningsAsErrors.toBoolean()
|
allWarningsAsErrors = warningsAsErrors.toBoolean()
|
||||||
freeCompilerArgs.add(
|
freeCompilerArgs.add(
|
||||||
// Enable experimental coroutines APIs, including Flow
|
// Enable experimental coroutines APIs, including Flow
|
||||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
)
|
)
|
||||||
freeCompilerArgs.add(
|
}
|
||||||
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package org.mifospay
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.configure
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
|
||||||
|
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||||
|
internal fun Project.configureKotlinMultiplatform() {
|
||||||
|
extensions.configure<KotlinMultiplatformExtension> {
|
||||||
|
applyDefaultHierarchyTemplate()
|
||||||
|
|
||||||
|
jvm("desktop")
|
||||||
|
androidTarget()
|
||||||
|
iosSimulatorArm64()
|
||||||
|
iosX64()
|
||||||
|
iosArm64()
|
||||||
|
js(IR) {
|
||||||
|
this.nodejs()
|
||||||
|
binaries.executable()
|
||||||
|
}
|
||||||
|
wasmJs() {
|
||||||
|
browser()
|
||||||
|
nodejs()
|
||||||
|
}
|
||||||
|
// Suppress 'expect'/'actual' classes are in Beta.
|
||||||
|
targets.configureEach {
|
||||||
|
compilations.configureEach {
|
||||||
|
compilerOptions.configure {
|
||||||
|
freeCompilerArgs.addAll("-Xexpect-actual-classes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixes Cannot locate tasks that match ':core:model:testClasses' as task 'testClasses'
|
||||||
|
// not found in project ':core:model'. Some candidates are: 'jsTestClasses', 'jvmTestClasses'.
|
||||||
|
project.tasks.create("testClasses") {
|
||||||
|
dependsOn("allTests")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,7 +21,6 @@ plugins {
|
|||||||
alias(libs.plugins.ksp) apply false
|
alias(libs.plugins.ksp) apply false
|
||||||
alias(libs.plugins.roborazzi) apply false
|
alias(libs.plugins.roborazzi) apply false
|
||||||
alias(libs.plugins.secrets) apply false
|
alias(libs.plugins.secrets) apply false
|
||||||
alias(libs.plugins.room) apply false
|
|
||||||
alias(libs.plugins.kotlin.android) apply false
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
alias(libs.plugins.module.graph) apply true
|
alias(libs.plugins.module.graph) apply true
|
||||||
alias(libs.plugins.detekt) apply false
|
alias(libs.plugins.detekt) apply false
|
||||||
@ -33,6 +32,7 @@ plugins {
|
|||||||
alias(libs.plugins.compose.compiler) apply false
|
alias(libs.plugins.compose.compiler) apply false
|
||||||
alias(libs.plugins.kotlinMultiplatform) apply false
|
alias(libs.plugins.kotlinMultiplatform) apply false
|
||||||
alias(libs.plugins.wire) apply false
|
alias(libs.plugins.wire) apply false
|
||||||
|
alias(libs.plugins.ktrofit) apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
object DynamicVersion {
|
object DynamicVersion {
|
||||||
|
|||||||
@ -12,11 +12,9 @@ echo Starting all checks and tests...
|
|||||||
call :run_gradle_task "check -p build-logic"
|
call :run_gradle_task "check -p build-logic"
|
||||||
call :run_gradle_task "spotlessApply --no-configuration-cache"
|
call :run_gradle_task "spotlessApply --no-configuration-cache"
|
||||||
call :run_gradle_task "dependencyGuardBaseline"
|
call :run_gradle_task "dependencyGuardBaseline"
|
||||||
call :run_gradle_task "formatVersionCatalog"
|
|
||||||
call :run_gradle_task "detekt"
|
call :run_gradle_task "detekt"
|
||||||
call :run_gradle_task "testDemoDebug :lint:test :mifospay:lintProdRelease :lint:lint"
|
call :run_gradle_task ":mifospay-android:build"
|
||||||
call :run_gradle_task "build"
|
call :run_gradle_task ":mifospay-android:updateProdReleaseBadging"
|
||||||
call :run_gradle_task "updateProdReleaseBadging"
|
|
||||||
|
|
||||||
echo All checks and tests completed successfully.
|
echo All checks and tests completed successfully.
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|||||||
@ -28,10 +28,8 @@ tasks=(
|
|||||||
"spotlessApply --no-configuration-cache"
|
"spotlessApply --no-configuration-cache"
|
||||||
"dependencyGuardBaseline"
|
"dependencyGuardBaseline"
|
||||||
"detekt"
|
"detekt"
|
||||||
"formatVersionCatalog"
|
":mifospay-android:build"
|
||||||
"testDemoDebug :lint:test :lint:lint :mifospay:lintProdRelease"
|
":mifospay-android:updateProdReleaseBadging"
|
||||||
"build"
|
|
||||||
"updateProdReleaseBadging"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for task in "${tasks[@]}"; do
|
for task in "${tasks[@]}"; do
|
||||||
|
|||||||
@ -8,17 +8,23 @@
|
|||||||
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.mifospay.android.library)
|
alias(libs.plugins.mifospay.kmp.library)
|
||||||
alias(libs.plugins.mifospay.android.library.compose)
|
alias(libs.plugins.jetbrainsCompose)
|
||||||
|
alias(libs.plugins.compose.compiler)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "org.mifospay.core.analytics"
|
namespace = "org.mifospay.core.analytics"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
kotlin {
|
||||||
implementation(libs.androidx.compose.runtime)
|
sourceSets {
|
||||||
|
commonMain.dependencies {
|
||||||
implementation(platform(libs.firebase.bom))
|
implementation(compose.runtime)
|
||||||
|
}
|
||||||
|
androidMain.dependencies {
|
||||||
|
implementation(project.dependencies.platform(libs.firebase.bom))
|
||||||
implementation(libs.firebase.analytics)
|
implementation(libs.firebase.analytics)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
core/analytics/proguard-rules.pro
vendored
21
core/analytics/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
@ -8,14 +8,56 @@
|
|||||||
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.mifospay.android.library)
|
alias(libs.plugins.mifospay.kmp.library)
|
||||||
|
alias(libs.plugins.kotlin.parcelize)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "org.mifospay.common"
|
namespace = "org.mifospay.common"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
kotlin {
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
iosX64(),
|
||||||
|
iosArm64(),
|
||||||
|
iosSimulatorArm64(),
|
||||||
|
).forEach {
|
||||||
|
it.binaries.framework {
|
||||||
|
isStatic = false
|
||||||
|
export(libs.kermit.simple)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain.dependencies {
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
|
api(libs.coil.kt)
|
||||||
|
api(libs.coil.core)
|
||||||
|
api(libs.coil.svg)
|
||||||
|
api(libs.coil.network.ktor)
|
||||||
|
api(libs.kermit.logging)
|
||||||
|
api(libs.squareup.okio)
|
||||||
|
api(libs.jb.kotlin.stdlib)
|
||||||
|
api(libs.kotlinx.datetime)
|
||||||
|
}
|
||||||
|
|
||||||
|
androidMain.dependencies {
|
||||||
implementation(libs.kotlinx.coroutines.android)
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
}
|
}
|
||||||
|
commonTest.dependencies {
|
||||||
|
implementation(libs.kotlinx.coroutines.test)
|
||||||
|
}
|
||||||
|
iosMain.dependencies {
|
||||||
|
api(libs.kermit.simple)
|
||||||
|
}
|
||||||
|
desktopMain.dependencies {
|
||||||
|
implementation(libs.kotlinx.coroutines.swing)
|
||||||
|
implementation(libs.kotlin.reflect)
|
||||||
|
}
|
||||||
|
jsMain.dependencies {
|
||||||
|
api(libs.jb.kotlin.stdlib.js)
|
||||||
|
api(libs.jb.kotlin.dom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
core/common/proguard-rules.pro
vendored
21
core/common/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
import java.text.NumberFormat
|
||||||
|
import java.util.Currency
|
||||||
|
|
||||||
|
actual object CurrencyFormatter {
|
||||||
|
actual fun format(
|
||||||
|
balance: Double?,
|
||||||
|
currencyCode: String?,
|
||||||
|
maximumFractionDigits: Int?,
|
||||||
|
): String {
|
||||||
|
val balanceFormatter = NumberFormat.getCurrencyInstance()
|
||||||
|
balanceFormatter.maximumFractionDigits = maximumFractionDigits ?: 0
|
||||||
|
balanceFormatter.currency = Currency.getInstance(currencyCode)
|
||||||
|
return balanceFormatter.format(balance)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
// JVM and Android implementation
|
||||||
|
actual fun createPlatformFileUtils(): FileUtils = CommonFileUtils()
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.IgnoredOnParcel
|
||||||
|
import kotlinx.parcelize.Parceler
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import kotlinx.parcelize.TypeParceler
|
||||||
|
|
||||||
|
actual typealias Parcelize = Parcelize
|
||||||
|
|
||||||
|
actual typealias Parcelable = Parcelable
|
||||||
|
|
||||||
|
actual typealias IgnoredOnParcel = IgnoredOnParcel
|
||||||
|
|
||||||
|
actual typealias Parceler<P> = Parceler<P>
|
||||||
|
|
||||||
|
actual typealias TypeParceler<T, P> = TypeParceler<T, P>
|
||||||
|
|
||||||
|
actual typealias Parcel = Parcel
|
||||||
@ -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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
actual val ioDispatcherModule: Module
|
||||||
|
get() = module {
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.IO }
|
||||||
|
}
|
||||||
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by naman on 17/6/17.
|
||||||
|
*/
|
||||||
|
object Constants {
|
||||||
|
const val BASIC = "Basic "
|
||||||
|
const val CLIENT_ID = "client_id"
|
||||||
|
const val ACCOUNT_ID = "account_id"
|
||||||
|
const val ACCOUNT = "account"
|
||||||
|
const val TO_EXTERNAL_ID = "to_external_id"
|
||||||
|
const val RUPEE = "₹"
|
||||||
|
const val QR_DATA = "qr_data"
|
||||||
|
const val MERCHANT_NAME = "merchant_name"
|
||||||
|
const val MERCHANT_VPA = "merchant_vpa"
|
||||||
|
const val MERCHANT_ACCOUNT_NO = "merchant_account_no"
|
||||||
|
const val FILE = "file"
|
||||||
|
const val MULTIPART_FORM_DATA = "multipart/form-data"
|
||||||
|
const val CHOOSE_A_FILE_TO_UPLOAD = "Choose a file to upload."
|
||||||
|
const val ERROR_UPLOADING_DOCS = "Error uploading docs."
|
||||||
|
const val KYC_LEVEL_2_DOCUMENTS_ADDED_SUCCESSFULLY = "KYC Level 2 documents added successfully."
|
||||||
|
const val IMAGE = "image/*"
|
||||||
|
const val APPLICATION_PDF = "application/pdf"
|
||||||
|
const val ERROR_ADDING_KYC_LEVEL_1_DETAILS = "Error adding KYC Level 1 details."
|
||||||
|
const val KYC_LEVEL_1_DETAILS_ADDED_SUCCESSFULLY = "KYC Level 1 details added successfully."
|
||||||
|
const val PLEASE_WAIT = "Please wait.."
|
||||||
|
const val COMPLETE_KYC = "Complete KYC"
|
||||||
|
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_BROWSE_DOCUMENTS =
|
||||||
|
"Need external storage permission to browse documents."
|
||||||
|
const val CHOOSE_FILE = "Choose File"
|
||||||
|
const val KYC_REGISTRATION_LEVEL_2 = "KYC Registration Level 2"
|
||||||
|
const val KYC_REGISTRATION_LEVEL_1 = "KYC Registration Level 1"
|
||||||
|
const val DD_MM_YY = "dd/MM/yy"
|
||||||
|
const val ERROR_DELETING_CARD = "Error deleting card."
|
||||||
|
const val CARD_DELETED_SUCCESSFULLY = "Card deleted successfully."
|
||||||
|
const val DELETING_CARD = "Deleting Card.."
|
||||||
|
const val ERROR_UPDATING_CARD = "Error updating card."
|
||||||
|
const val CARD_UPDATED_SUCCESSFULLY = "Card updated successfully."
|
||||||
|
const val INVALID_CREDIT_CARD_NUMBER = "Invalid Credit Card Number"
|
||||||
|
const val UPDATING_CARD = "Updating Card.."
|
||||||
|
const val ERROR_ADDING_CARD = "Error adding card."
|
||||||
|
const val CARD_ADDED_SUCCESSFULLY = "Card added successfully."
|
||||||
|
const val ADDING_CARD = "Adding Card.."
|
||||||
|
const val ADD_CARD_DIALOG = "Add Card Dialog"
|
||||||
|
const val EDIT_CARD_DIALOG = "Edit Card Dialog"
|
||||||
|
const val SAVED_CARDS = "Saved Cards"
|
||||||
|
const val UPDATE = "Update"
|
||||||
|
const val KYC_REGISTRATION_LEVEL_3 = "KYC Registration Level 3"
|
||||||
|
const val OK = "OK"
|
||||||
|
const val SCAN_CODE = "Scan code"
|
||||||
|
const val QR_CODE = "QR code"
|
||||||
|
const val FAILED_TO_WRITE_DATA_TO_QR = "Failed to write data to qr"
|
||||||
|
const val ERROR_OCCURRED = "Error occurred"
|
||||||
|
const val LOGGING_IN = "Logging in.."
|
||||||
|
const val HOME = "Home"
|
||||||
|
const val PROFILE = "Profile"
|
||||||
|
const val ERROR_FETCHING_BALANCE = "Error fetching balance"
|
||||||
|
const val UNABLE_TO_PROCESS_TRANSFER = "Unable to process transfer"
|
||||||
|
const val TRANSACTION_SUCCESSFUL = "Transaction successful"
|
||||||
|
const val SENDING_MONEY = "Sending money..."
|
||||||
|
const val INSUFFICIENT_BALANCE = "Insufficient balance"
|
||||||
|
const val ERROR_FINDING_VPA = "Error finding Virtual Payment Address"
|
||||||
|
const val ERROR_FINDING_MOBILE_NUMBER = "Error finding Mobile Number"
|
||||||
|
const val PLEASE_ENTER_VALID_AMOUNT = "Please enter a valid amount"
|
||||||
|
const val VPA_VALIDATION_REGEX = "^\\w.+@\\w+$"
|
||||||
|
const val SELF_ACCOUNT_ERROR = "Self Account transfer is not allowed"
|
||||||
|
const val PLEASE_ENTER_AMOUNT = "Please enter a valid amount before making the transfer"
|
||||||
|
const val NEED_READ_CONTACTS_PERMISSION = "Need read contacts permission"
|
||||||
|
const val NEED_CAMERA_PERMISSION_TO_SCAN_QR_CODE = "Need camera permission to scan qr code."
|
||||||
|
const val ERROR_CHOOSING_CONTACT = "Error choosing contact"
|
||||||
|
const val MAKE_TRANSFER_FRAGMENT = "Make Transfer Fragment"
|
||||||
|
const val PLEASE_ENTER_ALL_THE_FIELDS = "Please enter all the fields"
|
||||||
|
const val TRANSFER = "Transfer"
|
||||||
|
const val TRANSACTION_DETAILS = "Transaction Details"
|
||||||
|
const val ACCOUNT_NUMBER = "Account Number : "
|
||||||
|
const val TRANSACTION = "transaction"
|
||||||
|
const val TRANSACTIONS_HISTORY = "Transactions History History"
|
||||||
|
const val SPECIFIC_TRANSACTIONS = "Specific Transactions History"
|
||||||
|
const val HISTORY_NOT_AVAILABLE = "No Transaction History Available"
|
||||||
|
const val RECEIPT_DOMAIN = "https://receipt.mifospay.com/"
|
||||||
|
const val OTHER = "Other"
|
||||||
|
const val CREDIT = "Credit"
|
||||||
|
const val DEBIT = "Debit"
|
||||||
|
const val RECEIPT_ID = "Receipt ID"
|
||||||
|
const val DATE = "Date"
|
||||||
|
const val TRANSACTION_ID = "Transaction ID"
|
||||||
|
const val TRANSACTIONS = "transactions"
|
||||||
|
const val ERROR_FETCHING_TRANSACTIONS = "Error fetching transactions"
|
||||||
|
const val TRANSFER_DETAILS = "transfer details"
|
||||||
|
const val UNIQUE_PAYMENT_LINK_COPIED_TO_CLIPBOARD = "Unique Payment Link copied to clipboard"
|
||||||
|
const val UNIQUE_PAYMENT_LINK = "Unique Payment Link"
|
||||||
|
const val STATUS = "Status"
|
||||||
|
const val UNIQUE_RECEIPT_LINK_COPIED_TO_CLIPBOARD = "Unique Receipt Link copied to clipboard"
|
||||||
|
const val UNIQUE_RECEIPT_LINK = "Unique Receipt Link"
|
||||||
|
const val DONE = "Done"
|
||||||
|
const val PENDING = "Pending"
|
||||||
|
const val ITEMS = "Item(s)"
|
||||||
|
const val AMOUNT = "Amount"
|
||||||
|
const val INR = "INR"
|
||||||
|
const val CONSUMER = "Consumer"
|
||||||
|
const val MERCHANT = "Merchant"
|
||||||
|
const val INVOICE = "Invoice"
|
||||||
|
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_DOWNLOAD_RECEIPT =
|
||||||
|
"Need external storage permission to download receipt"
|
||||||
|
const val RECEIPT_DOWNLOADED_SUCCESSFULLY = "Receipt Downloaded Successfully"
|
||||||
|
const val ERROR_DOWNLOADING_RECEIPT = "Error downloading receipt"
|
||||||
|
const val MIFOSPAY = "mifospay"
|
||||||
|
const val RECEIPT = "Receipt"
|
||||||
|
const val PDF = ".pdf"
|
||||||
|
const val ERROR_FETCHING_RECEIPT = "Error fetching receipt"
|
||||||
|
const val INVOICE_DOMAIN = "https://invoice.mifospay.com/"
|
||||||
|
const val SENDING_OTP_TO_YOUR_MOBILE_NUMBER = "Sending OTP to your mobile number.."
|
||||||
|
const val MOBILE_NUMBER = "Mobile Number"
|
||||||
|
const val COUNTRY = "Country"
|
||||||
|
const val GOOGLE_SIGN_IN_FAILED = "Google Sign in failed."
|
||||||
|
const val GOOGLE_GIVEN_NAME = "GOOGLE_GIVEN_NAME"
|
||||||
|
const val GOOGLE_FAMILY_NAME = "GOOGLE_FAMILY_NAME"
|
||||||
|
const val GOOGLE_EMAIL = "GOOGLE_EMAIL"
|
||||||
|
const val GOOGLE_DISPLAY_NAME = "GOOGLE_DISPLAY_NAME"
|
||||||
|
const val GOOGLE_PHOTO_URI = "GOOGLE_PHOTO_URI"
|
||||||
|
const val CHOOSE_SIGNUP_METHOD = "Choose Signup Method"
|
||||||
|
const val LOGGING_OUT = "Logging out..."
|
||||||
|
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_BROWSE_IMAGES =
|
||||||
|
"Need external storage permission to browse images"
|
||||||
|
const val SETTINGS = "Settings"
|
||||||
|
const val EDIT_PROFILE = "Edit Profile"
|
||||||
|
const val FAQ = "Frequent Asked Questions"
|
||||||
|
const val LINKED_BANK_ACCOUNTS = "Linked Bank Accounts"
|
||||||
|
const val BANK_ACCOUNT_DETAILS = "Bank Account Details"
|
||||||
|
const val NEW_BANK_ACCOUNT = "newBankAccount"
|
||||||
|
const val VERIFYING_MOBILE_NUMBER = "Verifying mobile number.."
|
||||||
|
const val VERIFYING_OTP = "Verifying Otp.."
|
||||||
|
const val MIFOS_SAVINGS_PRODUCT_ID = "Mifos Savings Product Id"
|
||||||
|
const val MERCHANTS = "Merchants"
|
||||||
|
const val UPI_PIN = "UPI PIN"
|
||||||
|
const val STEP = "step"
|
||||||
|
const val TYPE = "Type"
|
||||||
|
const val SETUP = "Setup"
|
||||||
|
const val BANK_DELETED_SUCCESSFULLY = "Bank deleted successfully"
|
||||||
|
const val ERROR_OCCURRED_WHILE_CHANGING_UPI_PIN = "Error occurred while changing UPI PIN"
|
||||||
|
const val SETUP_UPI = "Setup UPI"
|
||||||
|
const val ERROR_WHILE_SETTING_UP_UPI_PIN = "Error while setting up UPI PIN"
|
||||||
|
const val UPI_PIN_SETUP_COMPLETED_SUCCESSFULLY = "UPI PIN Setup Completed Successfully"
|
||||||
|
const val FORGOT = "Forgot"
|
||||||
|
const val CHANGE = "Change"
|
||||||
|
const val OTP = "otp"
|
||||||
|
const val SETUP_UPI_PIN = "Setup UPI PIN"
|
||||||
|
const val SETTING_UP_UPI_PIN = "Setting up UPI PIN.."
|
||||||
|
const val UPDATED_BANK_ACCOUNT = "Updated Bank Account"
|
||||||
|
const val INDEX = "Index"
|
||||||
|
const val CHANGE_UPI_PIN = "Change UPI PIN"
|
||||||
|
const val FORGOT_UPI_PIN = "Forgot UPI PIN"
|
||||||
|
|
||||||
|
// broadcast receiver intent filters
|
||||||
|
const val REGISTRATION_COMPLETE = "registrationComplete"
|
||||||
|
const val PUSH_NOTIFICATION = "pushNotification"
|
||||||
|
|
||||||
|
// id to handle the notification in the notification tray
|
||||||
|
const val NOTIFICATION_ID = 100
|
||||||
|
const val NOTIFICATION_ID_BIG_IMAGE = 101
|
||||||
|
const val ERROR_FIELDS_CANNOT_BE_EMPTY = "Fields cannot be empty"
|
||||||
|
const val ERROR_VALIDATING_PASSWORD = "Passwords are not the same"
|
||||||
|
const val ERROR_PASSWORDS_CANT_BE_SAME = "New password can't be the same as old password."
|
||||||
|
const val CHANGE_PROFILE_IMAGE_KEY = "CHANGE_PROFILE_IMAGE_KEY"
|
||||||
|
const val CHANGE_PROFILE_IMAGE_VALUE = "CHANGE_PROFILE_IMAGE_VALUE"
|
||||||
|
const val TAP_TO_REVEAL = "Tap to Reveal"
|
||||||
|
const val NAME = "Name : "
|
||||||
|
const val ERROR_FETCHING_TRANSACTION_DETAILS = "Error fetching details"
|
||||||
|
|
||||||
|
// const val WHITE_BACK_BUTTON = R.drawable.ic_arrow_back_white_24dp
|
||||||
|
// const val BLACK_BACK_BUTTON = R.drawable.ic_arrow_back_black_24dp
|
||||||
|
const val VIEW = "View"
|
||||||
|
const val CURRENT_PASSCODE = "current passcode"
|
||||||
|
const val UPDATE_PASSCODE = "update passcode"
|
||||||
|
const val SELECT_DATE = "SELECT DATE"
|
||||||
|
const val SI_ID = "standing_instruction_id"
|
||||||
|
const val UNAUTHORIZED_ERROR = "401 Unauthorized"
|
||||||
|
const val RECEIPT_SHARING_MESSAGE = "Receipt link for the transaction "
|
||||||
|
const val TO = " to "
|
||||||
|
const val COLON = " : "
|
||||||
|
const val REQUEST_CAMERA = 0
|
||||||
|
const val SCAN_QR_REQUEST_CODE = 666
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
expect object CurrencyFormatter {
|
||||||
|
fun format(balance: Double?, currencyCode: String?, maximumFractionDigits: Int?): String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> List<T>.toArrayList(): ArrayList<T> {
|
||||||
|
return ArrayList(this)
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onStart
|
||||||
|
|
||||||
|
sealed class DataState<out T> {
|
||||||
|
abstract val data: T?
|
||||||
|
|
||||||
|
data object Loading : DataState<Nothing>() {
|
||||||
|
override val data: Nothing? get() = null
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Success<T>(
|
||||||
|
override val data: T,
|
||||||
|
) : DataState<T>()
|
||||||
|
|
||||||
|
data class Error<T>(
|
||||||
|
val exception: Throwable,
|
||||||
|
override val data: T? = null,
|
||||||
|
) : DataState<T>() {
|
||||||
|
val message = exception.message.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Flow<T>.asDataStateFlow(): Flow<DataState<T>> =
|
||||||
|
map<T, DataState<T>> { DataState.Success(it) }
|
||||||
|
.onStart { emit(DataState.Loading) }
|
||||||
|
.catch { emit(DataState.Error(it, null)) }
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.transformWhile
|
||||||
|
|
||||||
|
inline fun <T : Any?, R : Any?> DataState<T>.map(
|
||||||
|
transform: (T) -> R,
|
||||||
|
): DataState<R> = when (this) {
|
||||||
|
is DataState.Success -> DataState.Success(transform(data))
|
||||||
|
is DataState.Loading -> DataState.Loading
|
||||||
|
is DataState.Error -> DataState.Error(exception, data?.let(transform))
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : Any?, R : Any?> DataState<T>.mapNullable(
|
||||||
|
transform: (T?) -> R,
|
||||||
|
): DataState<R> = when (this) {
|
||||||
|
is DataState.Success -> DataState.Success(data = transform(data))
|
||||||
|
is DataState.Loading -> DataState.Loading
|
||||||
|
is DataState.Error -> DataState.Error(exception = exception, data = transform(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any?> Flow<DataState<T>>.takeUntilResultSuccess(): Flow<DataState<T>> = transformWhile {
|
||||||
|
emit(it)
|
||||||
|
it !is DataState.Success
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> combineResults(
|
||||||
|
dataState1: DataState<T1>,
|
||||||
|
dataState2: DataState<T2>,
|
||||||
|
transform: (t1: T1, t2: T2) -> R,
|
||||||
|
): DataState<R> {
|
||||||
|
val nullableTransform: (T1?, T2?) -> R? = { t1, t2 ->
|
||||||
|
if (t1 != null && t2 != null) transform(t1, t2) else null
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// Error states have highest priority, fail fast.
|
||||||
|
dataState1 is DataState.Error -> {
|
||||||
|
DataState.Error(
|
||||||
|
exception = dataState1.exception,
|
||||||
|
data = nullableTransform(dataState1.data, dataState2.data),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
dataState2 is DataState.Error -> {
|
||||||
|
DataState.Error(
|
||||||
|
exception = dataState2.exception,
|
||||||
|
data = nullableTransform(dataState1.data, dataState2.data),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something is still loading, we will wait for all the data.
|
||||||
|
dataState1 is DataState.Loading || dataState2 is DataState.Loading -> DataState.Loading
|
||||||
|
|
||||||
|
// Pending state for everything while any one piece of data is updating.
|
||||||
|
// Both states are _root_ide_package_.org.mifospay.core.common.Result.Success and have data
|
||||||
|
else -> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
DataState.Success(transform(dataState1.data as T1, dataState2.data as T2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, R> combineResults(
|
||||||
|
dataState1: DataState<T1>,
|
||||||
|
dataState2: DataState<T2>,
|
||||||
|
dataState3: DataState<T3>,
|
||||||
|
transform: (t1: T1, t2: T2, t3: T3) -> R,
|
||||||
|
): DataState<R> =
|
||||||
|
dataState1
|
||||||
|
.combineResultsWith(dataState2) { t1, t2 -> t1 to t2 }
|
||||||
|
.combineResultsWith(dataState3) { t1t2Pair, t3 ->
|
||||||
|
transform(t1t2Pair.first, t1t2Pair.second, t3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, R> combineResults(
|
||||||
|
dataState1: DataState<T1>,
|
||||||
|
dataState2: DataState<T2>,
|
||||||
|
dataState3: DataState<T3>,
|
||||||
|
dataState4: DataState<T4>,
|
||||||
|
transform: (t1: T1, t2: T2, t3: T3, t4: T4) -> R,
|
||||||
|
): DataState<R> =
|
||||||
|
dataState1
|
||||||
|
.combineResultsWith(dataState2) { t1, t2 -> t1 to t2 }
|
||||||
|
.combineResultsWith(dataState3) { t1t2Pair, t3 ->
|
||||||
|
Triple(t1t2Pair.first, t1t2Pair.second, t3)
|
||||||
|
}
|
||||||
|
.combineResultsWith(dataState4) { t1t2t3Triple, t3 ->
|
||||||
|
transform(t1t2t3Triple.first, t1t2t3Triple.second, t1t2t3Triple.third, t3)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> DataState<T1>.combineResultsWith(
|
||||||
|
dataState2: DataState<T2>,
|
||||||
|
transform: (t1: T1, t2: T2) -> R,
|
||||||
|
): DataState<R> =
|
||||||
|
combineResults(this, dataState2, transform)
|
||||||
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
import kotlinx.datetime.Clock
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlinx.datetime.LocalDateTime
|
||||||
|
import kotlinx.datetime.Month
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.format
|
||||||
|
import kotlinx.datetime.format.FormatStringsInDatetimeFormats
|
||||||
|
import kotlinx.datetime.format.byUnicodePattern
|
||||||
|
import kotlinx.datetime.toLocalDateTime
|
||||||
|
|
||||||
|
@OptIn(FormatStringsInDatetimeFormats::class)
|
||||||
|
object DateHelper {
|
||||||
|
/*
|
||||||
|
* This is the full month format for the date picker.
|
||||||
|
* "dd MM yyyy" is the format of the date picker.
|
||||||
|
*/
|
||||||
|
const val FULL_MONTH = "dd MM yyyy"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the short month format for the date picker.
|
||||||
|
* "dd-MM-yyyy" is the format of the date picker.
|
||||||
|
*/
|
||||||
|
const val SHORT_MONTH = "dd-MM-yyyy"
|
||||||
|
|
||||||
|
const val MONTH_FORMAT = "dd MMMM"
|
||||||
|
|
||||||
|
private val fullMonthFormat = LocalDateTime.Format {
|
||||||
|
byUnicodePattern(FULL_MONTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val shortMonthFormat = LocalDateTime.Format {
|
||||||
|
byUnicodePattern(SHORT_MONTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the result string uses the list given in a reverse order ([x, y, z] results in "z y x")
|
||||||
|
*
|
||||||
|
* @param integersOfDate [year-month-day] (ex [2016, 4, 14])
|
||||||
|
* @return date in the format day month year (ex 14 Apr 2016)
|
||||||
|
*/
|
||||||
|
fun getDateAsString(integersOfDate: List<Int>): String {
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
stringBuilder.append(integersOfDate[2])
|
||||||
|
.append(' ')
|
||||||
|
.append(getMonthName(integersOfDate[1]))
|
||||||
|
.append(' ')
|
||||||
|
.append(integersOfDate[0])
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDateAsString(integersOfDate: List<Long>, pattern: String): String {
|
||||||
|
return getFormatConverter(
|
||||||
|
currentFormat = FULL_MONTH,
|
||||||
|
requiredFormat = pattern,
|
||||||
|
dateString = getDateAsString(integersOfDate.map { it.toInt() }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Method converting the dd-MM-yyyy format type date string into dd MMMM yyyy
|
||||||
|
*
|
||||||
|
* @param format Final Format of date string
|
||||||
|
* @param dateString date string
|
||||||
|
* @return dd MMMM yyyy format date string.
|
||||||
|
*/
|
||||||
|
fun getSpecificFormat(format: String, dateString: String): String {
|
||||||
|
val pickerFormat = shortMonthFormat
|
||||||
|
val finalFormat = LocalDateTime.Format { byUnicodePattern(format) }
|
||||||
|
|
||||||
|
return finalFormat.format(pickerFormat.parse(dateString))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFormatConverter(
|
||||||
|
currentFormat: String,
|
||||||
|
requiredFormat: String,
|
||||||
|
dateString: String,
|
||||||
|
): String {
|
||||||
|
val pickerFormat = LocalDateTime.Format { byUnicodePattern(currentFormat) }
|
||||||
|
val finalFormat = LocalDateTime.Format { byUnicodePattern(requiredFormat) }
|
||||||
|
|
||||||
|
return pickerFormat.parse(dateString).format(finalFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date string in the format "dd-MM-yyyy" from an array of integers representing the year, month, and day.
|
||||||
|
*
|
||||||
|
* @param dateComponents An array of three integers representing the year, month, and day, e.g. [2024, 11, 10]
|
||||||
|
* @return The date string in the format "dd-MM-yyyy", e.g. "10-11-2024"
|
||||||
|
*/
|
||||||
|
fun formatTransferDate(dateComponents: List<Int>, pattern: String = SHORT_MONTH): String {
|
||||||
|
require(dateComponents.size == 3) { "dateComponents must have exactly 3 elements" }
|
||||||
|
val (year, month, day) = dateComponents
|
||||||
|
|
||||||
|
val localDate = LocalDate(year, Month(month), day)
|
||||||
|
return localDate.format(pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension function to format LocalDate
|
||||||
|
fun LocalDate.format(pattern: String): String {
|
||||||
|
val year = this.year.toString().padStart(4, '0')
|
||||||
|
val month = this.monthNumber.toString().padStart(2, '0')
|
||||||
|
val day = this.dayOfMonth.toString().padStart(2, '0')
|
||||||
|
|
||||||
|
return pattern
|
||||||
|
.replace("yyyy", year)
|
||||||
|
.replace("MM", month)
|
||||||
|
.replace("dd", day)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param month an integer from 1 to 12
|
||||||
|
* @return string representation of the month like Jan or Feb..etc
|
||||||
|
*/
|
||||||
|
private fun getMonthName(month: Int): String {
|
||||||
|
return when (month) {
|
||||||
|
1 -> "Jan"
|
||||||
|
2 -> "Feb"
|
||||||
|
3 -> "Mar"
|
||||||
|
4 -> "Apr"
|
||||||
|
5 -> "May"
|
||||||
|
6 -> "Jun"
|
||||||
|
7 -> "Jul"
|
||||||
|
8 -> "Aug"
|
||||||
|
9 -> "Sep"
|
||||||
|
10 -> "Oct"
|
||||||
|
11 -> "Nov"
|
||||||
|
12 -> "Dec"
|
||||||
|
else -> throw IllegalArgumentException("Month should be between 1 and 12")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input timestamp string in milliseconds
|
||||||
|
* Example timestamp "1698278400000"
|
||||||
|
* Output examples: "dd-MM-yyyy" - "14-04-2016"
|
||||||
|
*/
|
||||||
|
fun getDateAsStringFromLong(timeInMillis: Long): String {
|
||||||
|
val instant = Instant.fromEpochMilliseconds(timeInMillis)
|
||||||
|
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
|
return instant.format(shortMonthFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input timestamp string in milliseconds
|
||||||
|
* Example timestamp "1698278400000"
|
||||||
|
* Output examples: "14 April"
|
||||||
|
*/
|
||||||
|
fun getMonthAsStringFromLong(timeInMillis: Long): String {
|
||||||
|
val instant = Instant.fromEpochMilliseconds(timeInMillis)
|
||||||
|
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
|
val monthName = instant.month.name.lowercase().capitalize()
|
||||||
|
|
||||||
|
return "${instant.dayOfMonth} $monthName"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date string in the format "day month year" from an array of integers representing the day and month.
|
||||||
|
*
|
||||||
|
* @param integersOfDate An array of two integers representing the day and month, e.g. [11, 10]
|
||||||
|
* @return The date string in the format "day month year", e.g. "11 October"
|
||||||
|
*/
|
||||||
|
fun getDateMonthString(integersOfDate: List<Int>): String {
|
||||||
|
require(integersOfDate.size == 2) { "integersOfDate must have exactly 2 elements" }
|
||||||
|
val (day, month) = integersOfDate
|
||||||
|
|
||||||
|
val monthName = when (month) {
|
||||||
|
1 -> "January"
|
||||||
|
2 -> "February"
|
||||||
|
3 -> "March"
|
||||||
|
4 -> "April"
|
||||||
|
5 -> "May"
|
||||||
|
6 -> "June"
|
||||||
|
7 -> "July"
|
||||||
|
8 -> "August"
|
||||||
|
9 -> "September"
|
||||||
|
10 -> "October"
|
||||||
|
11 -> "November"
|
||||||
|
12 -> "December"
|
||||||
|
else -> throw IllegalArgumentException("Invalid month value: $month")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$day $monthName"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the specific format "yyyy-MM-dd HH:mm:ss.SSSSSS"
|
||||||
|
* For example "2024-09-19 05:41:18.558995"
|
||||||
|
* Possible outputs depending on current date:
|
||||||
|
* "Today at 05:41"
|
||||||
|
* "Tomorrow at 05:41"
|
||||||
|
*/
|
||||||
|
fun String.toFormattedDateTime(): String {
|
||||||
|
// Parse the datetime string
|
||||||
|
val dateTime = try {
|
||||||
|
// Split into date and time parts
|
||||||
|
val (datePart, timePart) = this.split(" ")
|
||||||
|
// Remove microseconds from time part
|
||||||
|
val simplifiedTime = timePart.split(".")[0]
|
||||||
|
// Combine date and simplified time
|
||||||
|
val isoString = "${datePart}T$simplifiedTime"
|
||||||
|
// Parse to LocalDateTime
|
||||||
|
LocalDateTime.parse(isoString)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return this // Return original string if parsing fails
|
||||||
|
}
|
||||||
|
|
||||||
|
val timeZone = TimeZone.currentSystemDefault()
|
||||||
|
val now = Clock.System.now()
|
||||||
|
val nowDateTime = now.toLocalDateTime(timeZone)
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// Same year
|
||||||
|
nowDateTime.year == dateTime.year -> {
|
||||||
|
when {
|
||||||
|
// Same month
|
||||||
|
nowDateTime.monthNumber == dateTime.monthNumber -> {
|
||||||
|
when {
|
||||||
|
// Tomorrow
|
||||||
|
dateTime.dayOfMonth - nowDateTime.dayOfMonth == 1 -> {
|
||||||
|
"Tomorrow at ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
// Today
|
||||||
|
dateTime.dayOfMonth == nowDateTime.dayOfMonth -> {
|
||||||
|
"Today at ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
// Yesterday
|
||||||
|
nowDateTime.dayOfMonth - dateTime.dayOfMonth == 1 -> {
|
||||||
|
"Yesterday at ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
// Same month but different day
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
dateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${dateTime.dayOfMonth}, ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Different month, same year
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
dateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${dateTime.dayOfMonth}, ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Different year
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
dateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${dateTime.dayOfMonth} ${dateTime.year}, ${dateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input timestamp string in milliseconds
|
||||||
|
* Example timestamp "1698278400000"
|
||||||
|
* Output examples:
|
||||||
|
* "Today at 12:00"
|
||||||
|
* "Tomorrow at 15:30"
|
||||||
|
*/
|
||||||
|
fun String.toPrettyDate(): String {
|
||||||
|
val timestamp = this.toLong()
|
||||||
|
val instant = Instant.fromEpochMilliseconds(timestamp)
|
||||||
|
val timeZone = TimeZone.currentSystemDefault()
|
||||||
|
val nowDateTime = Clock.System.now().toLocalDateTime(timeZone)
|
||||||
|
val neededDateTime = instant.toLocalDateTime(timeZone)
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// Same year
|
||||||
|
nowDateTime.year == neededDateTime.year -> {
|
||||||
|
when {
|
||||||
|
// Same month
|
||||||
|
nowDateTime.monthNumber == neededDateTime.monthNumber -> {
|
||||||
|
when {
|
||||||
|
// Tomorrow
|
||||||
|
neededDateTime.dayOfMonth - nowDateTime.dayOfMonth == 1 -> {
|
||||||
|
val time = neededDateTime.format()
|
||||||
|
"Tomorrow at $time"
|
||||||
|
}
|
||||||
|
// Today
|
||||||
|
neededDateTime.dayOfMonth == nowDateTime.dayOfMonth -> {
|
||||||
|
val time = neededDateTime.format()
|
||||||
|
"Today at $time"
|
||||||
|
}
|
||||||
|
// Yesterday
|
||||||
|
nowDateTime.dayOfMonth - neededDateTime.dayOfMonth == 1 -> {
|
||||||
|
val time = neededDateTime.format()
|
||||||
|
"Yesterday at $time"
|
||||||
|
}
|
||||||
|
// Same month but different day
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
neededDateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${neededDateTime.dayOfMonth}, ${neededDateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Different month, same year
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
neededDateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${neededDateTime.dayOfMonth}, ${neededDateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Different year
|
||||||
|
else -> {
|
||||||
|
"${
|
||||||
|
neededDateTime.month.name.lowercase().capitalize()
|
||||||
|
} ${neededDateTime.dayOfMonth} ${neededDateTime.year}, ${neededDateTime.format()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to format time
|
||||||
|
private fun LocalDateTime.format(): String {
|
||||||
|
return "${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension to capitalize first letter
|
||||||
|
private fun String.capitalize() = replaceFirstChar {
|
||||||
|
if (it.isLowerCase()) it.titlecase() else it.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the full date format for the date picker.
|
||||||
|
* "dd MM yyyy" is the format of the date picker.
|
||||||
|
*/
|
||||||
|
val formattedFullDate = currentDate.format(fullMonthFormat)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the short date format for the date picker.
|
||||||
|
* "dd-MM-yyyy" is the format of the date picker.
|
||||||
|
*/
|
||||||
|
val formattedShortDate = currentDate.format(shortMonthFormat)
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
|
||||||
|
object DebugUtil {
|
||||||
|
|
||||||
|
private val logger = Logger.withTag("QXZ")
|
||||||
|
|
||||||
|
fun log(vararg objects: Any): Array<out Any> {
|
||||||
|
val stringToPrint = objects.joinToString(", ")
|
||||||
|
logger.d { stringToPrint }
|
||||||
|
return objects
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
interface FileUtils {
|
||||||
|
suspend fun writeInputStreamDataToFile(inputStream: ByteArray, filePath: String): Boolean
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val logger = Logger.withTag("FileUtils")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect fun createPlatformFileUtils(): FileUtils
|
||||||
|
|
||||||
|
class CommonFileUtils : FileUtils {
|
||||||
|
override suspend fun writeInputStreamDataToFile(
|
||||||
|
inputStream: ByteArray,
|
||||||
|
filePath: String,
|
||||||
|
): Boolean =
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
try {
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
FileUtils.logger.e { "Error writing file: ${e.message}" }
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
import org.koin.core.annotation.Qualifier
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class Dispatcher(val mifosDispatcher: MifosDispatchers)
|
||||||
|
|
||||||
|
enum class MifosDispatchers {
|
||||||
|
Default,
|
||||||
|
IO,
|
||||||
|
Unconfined,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class ApplicationScope
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
const val PAYEE_EXTERNAL_ID_ARG = "payeeExternalId"
|
||||||
|
const val TRANSFER_AMOUNT_ARG = "transferAmount"
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
expect annotation class Parcelize()
|
||||||
|
|
||||||
|
expect interface Parcelable
|
||||||
|
|
||||||
|
expect annotation class IgnoredOnParcel()
|
||||||
|
|
||||||
|
expect interface Parceler<P> {
|
||||||
|
fun create(parcel: Parcel): P
|
||||||
|
|
||||||
|
fun P.write(parcel: Parcel, flags: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect annotation class TypeParceler<T, P : Parceler<in T>>()
|
||||||
|
|
||||||
|
expect class Parcel {
|
||||||
|
fun readByte(): Byte
|
||||||
|
fun readInt(): Int
|
||||||
|
|
||||||
|
fun readFloat(): Float
|
||||||
|
fun readDouble(): Double
|
||||||
|
fun readString(): String?
|
||||||
|
|
||||||
|
fun writeByte(value: Byte)
|
||||||
|
fun writeInt(value: Int)
|
||||||
|
|
||||||
|
fun writeFloat(value: Float)
|
||||||
|
|
||||||
|
fun writeDouble(value: Double)
|
||||||
|
fun writeString(value: String?)
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
val DispatchersModule = module {
|
||||||
|
includes(ioDispatcherModule)
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.Default.name)) { Dispatchers.Default }
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.Unconfined.name)) { Dispatchers.Unconfined }
|
||||||
|
single<CoroutineScope>(named("ApplicationScope")) {
|
||||||
|
CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect val ioDispatcherModule: Module
|
||||||
@ -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
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common.utils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not string is a valid email address.
|
||||||
|
*
|
||||||
|
* This just checks if the string contains the "@" symbol.
|
||||||
|
*/
|
||||||
|
fun String.isValidEmail(): Boolean = contains("@")
|
||||||
|
|
||||||
|
fun maskString(input: String, maskChar: Char = '*'): String {
|
||||||
|
if (input.length <= 3) return input
|
||||||
|
|
||||||
|
val visibleCount = 3
|
||||||
|
val maskLength = input.length - visibleCount
|
||||||
|
|
||||||
|
return buildString {
|
||||||
|
append(maskChar.toString().repeat(maskLength))
|
||||||
|
append(input.takeLast(visibleCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.capitalizeWords(): String = split(" ").joinToString(" ") { it ->
|
||||||
|
it.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
import java.text.NumberFormat
|
||||||
|
import java.util.Currency
|
||||||
|
|
||||||
|
actual object CurrencyFormatter {
|
||||||
|
actual fun format(
|
||||||
|
balance: Double?,
|
||||||
|
currencyCode: String?,
|
||||||
|
maximumFractionDigits: Int?,
|
||||||
|
): String {
|
||||||
|
val numberFormat = NumberFormat.getCurrencyInstance()
|
||||||
|
numberFormat.maximumFractionDigits = maximumFractionDigits ?: 0
|
||||||
|
numberFormat.currency = Currency.getInstance(currencyCode)
|
||||||
|
return numberFormat.format(balance)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
// JVM and Android implementation
|
||||||
|
actual fun createPlatformFileUtils(): FileUtils = CommonFileUtils()
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
actual interface Parcelable
|
||||||
|
actual annotation class IgnoredOnParcel
|
||||||
|
actual annotation class Parcelize
|
||||||
|
actual interface Parceler<P> {
|
||||||
|
actual fun create(parcel: Parcel): P
|
||||||
|
actual fun P.write(parcel: Parcel, flags: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual annotation class TypeParceler<T, P : Parceler<in T>>
|
||||||
|
|
||||||
|
actual class Parcel {
|
||||||
|
actual fun readString(): String? = null
|
||||||
|
actual fun readByte(): Byte = 1
|
||||||
|
|
||||||
|
actual fun readInt(): Int = 1
|
||||||
|
|
||||||
|
actual fun readFloat(): Float = 1f
|
||||||
|
|
||||||
|
actual fun readDouble(): Double = 1.0
|
||||||
|
|
||||||
|
actual fun writeByte(value: Byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeInt(value: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeFloat(value: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeDouble(value: Double) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeString(value: String?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
actual val ioDispatcherModule: Module
|
||||||
|
get() = module {
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.Default }
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common
|
||||||
|
|
||||||
|
actual object CurrencyFormatter {
|
||||||
|
actual fun format(
|
||||||
|
balance: Double?,
|
||||||
|
currencyCode: String?,
|
||||||
|
maximumFractionDigits: Int?,
|
||||||
|
): String {
|
||||||
|
if (balance == null || currencyCode == null) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
val options = js("{}").unsafeCast<dynamic>()
|
||||||
|
options.style = "currency"
|
||||||
|
options.currency = currencyCode
|
||||||
|
if (maximumFractionDigits != null) {
|
||||||
|
options.maximumFractionDigits = maximumFractionDigits
|
||||||
|
}
|
||||||
|
|
||||||
|
return try {
|
||||||
|
js("new Intl.NumberFormat('en-US', options).format(balance)").toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
console.error("Error formatting currency: ${e.message}")
|
||||||
|
balance.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
actual fun createPlatformFileUtils(): FileUtils = CommonFileUtils()
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
actual interface Parcelable
|
||||||
|
actual annotation class IgnoredOnParcel
|
||||||
|
actual annotation class Parcelize
|
||||||
|
actual interface Parceler<P> {
|
||||||
|
actual fun create(parcel: Parcel): P
|
||||||
|
actual fun P.write(parcel: Parcel, flags: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual annotation class TypeParceler<T, P : Parceler<in T>>
|
||||||
|
|
||||||
|
actual class Parcel {
|
||||||
|
actual fun readString(): String? = null
|
||||||
|
actual fun readByte(): Byte = 1
|
||||||
|
|
||||||
|
actual fun readInt(): Int = 1
|
||||||
|
|
||||||
|
actual fun readFloat(): Float = 1f
|
||||||
|
|
||||||
|
actual fun readDouble(): Double = 1.0
|
||||||
|
|
||||||
|
actual fun writeByte(value: Byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeInt(value: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeFloat(value: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeDouble(value: Double) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeString(value: String?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
actual val ioDispatcherModule: Module
|
||||||
|
get() = module {
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.Default }
|
||||||
|
}
|
||||||
@ -1,192 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by naman on 17/6/17.
|
|
||||||
*/
|
|
||||||
object Constants {
|
|
||||||
const val BASIC = "Basic "
|
|
||||||
const val CLIENT_ID = "client_id"
|
|
||||||
const val ACCOUNT_ID = "account_id"
|
|
||||||
const val ACCOUNT = "account"
|
|
||||||
const val TO_EXTERNAL_ID = "to_external_id"
|
|
||||||
const val RUPEE = "₹"
|
|
||||||
const val QR_DATA = "qr_data"
|
|
||||||
const val MERCHANT_NAME = "merchant_name"
|
|
||||||
const val MERCHANT_VPA = "merchant_vpa"
|
|
||||||
const val MERCHANT_ACCOUNT_NO = "merchant_account_no"
|
|
||||||
const val FILE = "file"
|
|
||||||
const val MULTIPART_FORM_DATA = "multipart/form-data"
|
|
||||||
const val CHOOSE_A_FILE_TO_UPLOAD = "Choose a file to upload."
|
|
||||||
const val ERROR_UPLOADING_DOCS = "Error uploading docs."
|
|
||||||
const val KYC_LEVEL_2_DOCUMENTS_ADDED_SUCCESSFULLY = "KYC Level 2 documents added successfully."
|
|
||||||
const val IMAGE = "image/*"
|
|
||||||
const val APPLICATION_PDF = "application/pdf"
|
|
||||||
const val ERROR_ADDING_KYC_LEVEL_1_DETAILS = "Error adding KYC Level 1 details."
|
|
||||||
const val KYC_LEVEL_1_DETAILS_ADDED_SUCCESSFULLY = "KYC Level 1 details added successfully."
|
|
||||||
const val PLEASE_WAIT = "Please wait.."
|
|
||||||
const val COMPLETE_KYC = "Complete KYC"
|
|
||||||
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_BROWSE_DOCUMENTS =
|
|
||||||
"Need external storage permission to browse documents."
|
|
||||||
const val CHOOSE_FILE = "Choose File"
|
|
||||||
const val KYC_REGISTRATION_LEVEL_2 = "KYC Registration Level 2"
|
|
||||||
const val KYC_REGISTRATION_LEVEL_1 = "KYC Registration Level 1"
|
|
||||||
const val DD_MM_YY = "dd/MM/yy"
|
|
||||||
const val ERROR_DELETING_CARD = "Error deleting card."
|
|
||||||
const val CARD_DELETED_SUCCESSFULLY = "Card deleted successfully."
|
|
||||||
const val DELETING_CARD = "Deleting Card.."
|
|
||||||
const val ERROR_UPDATING_CARD = "Error updating card."
|
|
||||||
const val CARD_UPDATED_SUCCESSFULLY = "Card updated successfully."
|
|
||||||
const val INVALID_CREDIT_CARD_NUMBER = "Invalid Credit Card Number"
|
|
||||||
const val UPDATING_CARD = "Updating Card.."
|
|
||||||
const val ERROR_ADDING_CARD = "Error adding card."
|
|
||||||
const val CARD_ADDED_SUCCESSFULLY = "Card added successfully."
|
|
||||||
const val ADDING_CARD = "Adding Card.."
|
|
||||||
const val ADD_CARD_DIALOG = "Add Card Dialog"
|
|
||||||
const val EDIT_CARD_DIALOG = "Edit Card Dialog"
|
|
||||||
const val SAVED_CARDS = "Saved Cards"
|
|
||||||
const val UPDATE = "Update"
|
|
||||||
const val KYC_REGISTRATION_LEVEL_3 = "KYC Registration Level 3"
|
|
||||||
const val OK = "OK"
|
|
||||||
const val SCAN_CODE = "Scan code"
|
|
||||||
const val QR_CODE = "QR code"
|
|
||||||
const val FAILED_TO_WRITE_DATA_TO_QR = "Failed to write data to qr"
|
|
||||||
const val ERROR_OCCURRED = "Error occurred"
|
|
||||||
const val LOGGING_IN = "Logging in.."
|
|
||||||
const val HOME = "Home"
|
|
||||||
const val PROFILE = "Profile"
|
|
||||||
const val ERROR_FETCHING_BALANCE = "Error fetching balance"
|
|
||||||
const val UNABLE_TO_PROCESS_TRANSFER = "Unable to process transfer"
|
|
||||||
const val TRANSACTION_SUCCESSFUL = "Transaction successful"
|
|
||||||
const val SENDING_MONEY = "Sending money..."
|
|
||||||
const val INSUFFICIENT_BALANCE = "Insufficient balance"
|
|
||||||
const val ERROR_FINDING_VPA = "Error finding Virtual Payment Address"
|
|
||||||
const val ERROR_FINDING_MOBILE_NUMBER = "Error finding Mobile Number"
|
|
||||||
const val PLEASE_ENTER_VALID_AMOUNT = "Please enter a valid amount"
|
|
||||||
const val VPA_VALIDATION_REGEX = "^\\w.+@\\w+$"
|
|
||||||
const val SELF_ACCOUNT_ERROR = "Self Account transfer is not allowed"
|
|
||||||
const val PLEASE_ENTER_AMOUNT = "Please enter a valid amount before making the transfer"
|
|
||||||
const val NEED_READ_CONTACTS_PERMISSION = "Need read contacts permission"
|
|
||||||
const val NEED_CAMERA_PERMISSION_TO_SCAN_QR_CODE = "Need camera permission to scan qr code."
|
|
||||||
const val ERROR_CHOOSING_CONTACT = "Error choosing contact"
|
|
||||||
const val MAKE_TRANSFER_FRAGMENT = "Make Transfer Fragment"
|
|
||||||
const val PLEASE_ENTER_ALL_THE_FIELDS = "Please enter all the fields"
|
|
||||||
const val TRANSFER = "Transfer"
|
|
||||||
const val TRANSACTION_DETAILS = "Transaction Details"
|
|
||||||
const val ACCOUNT_NUMBER = "Account Number : "
|
|
||||||
const val TRANSACTION = "transaction"
|
|
||||||
const val TRANSACTIONS_HISTORY = "Transactions History History"
|
|
||||||
const val SPECIFIC_TRANSACTIONS = "Specific Transactions History"
|
|
||||||
const val HISTORY_NOT_AVAILABLE = "No Transaction History Available"
|
|
||||||
const val RECEIPT_DOMAIN = "https://receipt.mifospay.com/"
|
|
||||||
const val OTHER = "Other"
|
|
||||||
const val CREDIT = "Credit"
|
|
||||||
const val DEBIT = "Debit"
|
|
||||||
const val RECEIPT_ID = "Receipt ID"
|
|
||||||
const val DATE = "Date"
|
|
||||||
const val TRANSACTION_ID = "Transaction ID"
|
|
||||||
const val TRANSACTIONS = "transactions"
|
|
||||||
const val ERROR_FETCHING_TRANSACTIONS = "Error fetching transactions"
|
|
||||||
const val TRANSFER_DETAILS = "transfer details"
|
|
||||||
const val UNIQUE_PAYMENT_LINK_COPIED_TO_CLIPBOARD = "Unique Payment Link copied to clipboard"
|
|
||||||
const val UNIQUE_PAYMENT_LINK = "Unique Payment Link"
|
|
||||||
const val STATUS = "Status"
|
|
||||||
const val UNIQUE_RECEIPT_LINK_COPIED_TO_CLIPBOARD = "Unique Receipt Link copied to clipboard"
|
|
||||||
const val UNIQUE_RECEIPT_LINK = "Unique Receipt Link"
|
|
||||||
const val DONE = "Done"
|
|
||||||
const val PENDING = "Pending"
|
|
||||||
const val ITEMS = "Item(s)"
|
|
||||||
const val AMOUNT = "Amount"
|
|
||||||
const val INR = "INR"
|
|
||||||
const val CONSUMER = "Consumer"
|
|
||||||
const val MERCHANT = "Merchant"
|
|
||||||
const val INVOICE = "Invoice"
|
|
||||||
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_DOWNLOAD_RECEIPT =
|
|
||||||
"Need external storage permission to download receipt"
|
|
||||||
const val RECEIPT_DOWNLOADED_SUCCESSFULLY = "Receipt Downloaded Successfully"
|
|
||||||
const val ERROR_DOWNLOADING_RECEIPT = "Error downloading receipt"
|
|
||||||
const val MIFOSPAY = "mifospay"
|
|
||||||
const val RECEIPT = "Receipt"
|
|
||||||
const val PDF = ".pdf"
|
|
||||||
const val ERROR_FETCHING_RECEIPT = "Error fetching receipt"
|
|
||||||
const val INVOICE_DOMAIN = "https://invoice.mifospay.com/"
|
|
||||||
const val SENDING_OTP_TO_YOUR_MOBILE_NUMBER = "Sending OTP to your mobile number.."
|
|
||||||
const val MOBILE_NUMBER = "Mobile Number"
|
|
||||||
const val COUNTRY = "Country"
|
|
||||||
const val GOOGLE_SIGN_IN_FAILED = "Google Sign in failed."
|
|
||||||
const val GOOGLE_GIVEN_NAME = "GOOGLE_GIVEN_NAME"
|
|
||||||
const val GOOGLE_FAMILY_NAME = "GOOGLE_FAMILY_NAME"
|
|
||||||
const val GOOGLE_EMAIL = "GOOGLE_EMAIL"
|
|
||||||
const val GOOGLE_DISPLAY_NAME = "GOOGLE_DISPLAY_NAME"
|
|
||||||
const val GOOGLE_PHOTO_URI = "GOOGLE_PHOTO_URI"
|
|
||||||
const val CHOOSE_SIGNUP_METHOD = "Choose Signup Method"
|
|
||||||
const val LOGGING_OUT = "Logging out..."
|
|
||||||
const val NEED_EXTERNAL_STORAGE_PERMISSION_TO_BROWSE_IMAGES =
|
|
||||||
"Need external storage permission to browse images"
|
|
||||||
const val SETTINGS = "Settings"
|
|
||||||
const val EDIT_PROFILE = "Edit Profile"
|
|
||||||
const val FAQ = "Frequent Asked Questions"
|
|
||||||
const val LINKED_BANK_ACCOUNTS = "Linked Bank Accounts"
|
|
||||||
const val BANK_ACCOUNT_DETAILS = "Bank Account Details"
|
|
||||||
const val NEW_BANK_ACCOUNT = "newBankAccount"
|
|
||||||
const val VERIFYING_MOBILE_NUMBER = "Verifying mobile number.."
|
|
||||||
const val VERIFYING_OTP = "Verifying Otp.."
|
|
||||||
const val MIFOS_SAVINGS_PRODUCT_ID = "Mifos Savings Product Id"
|
|
||||||
const val MERCHANTS = "Merchants"
|
|
||||||
const val UPI_PIN = "UPI PIN"
|
|
||||||
const val STEP = "step"
|
|
||||||
const val TYPE = "Type"
|
|
||||||
const val SETUP = "Setup"
|
|
||||||
const val BANK_DELETED_SUCCESSFULLY = "Bank deleted successfully"
|
|
||||||
const val ERROR_OCCURRED_WHILE_CHANGING_UPI_PIN = "Error occurred while changing UPI PIN"
|
|
||||||
const val SETUP_UPI = "Setup UPI"
|
|
||||||
const val ERROR_WHILE_SETTING_UP_UPI_PIN = "Error while setting up UPI PIN"
|
|
||||||
const val UPI_PIN_SETUP_COMPLETED_SUCCESSFULLY = "UPI PIN Setup Completed Successfully"
|
|
||||||
const val FORGOT = "Forgot"
|
|
||||||
const val CHANGE = "Change"
|
|
||||||
const val OTP = "otp"
|
|
||||||
const val SETUP_UPI_PIN = "Setup UPI PIN"
|
|
||||||
const val SETTING_UP_UPI_PIN = "Setting up UPI PIN.."
|
|
||||||
const val UPDATED_BANK_ACCOUNT = "Updated Bank Account"
|
|
||||||
const val INDEX = "Index"
|
|
||||||
const val CHANGE_UPI_PIN = "Change UPI PIN"
|
|
||||||
const val FORGOT_UPI_PIN = "Forgot UPI PIN"
|
|
||||||
|
|
||||||
// broadcast receiver intent filters
|
|
||||||
const val REGISTRATION_COMPLETE = "registrationComplete"
|
|
||||||
const val PUSH_NOTIFICATION = "pushNotification"
|
|
||||||
|
|
||||||
// id to handle the notification in the notification tray
|
|
||||||
const val NOTIFICATION_ID = 100
|
|
||||||
const val NOTIFICATION_ID_BIG_IMAGE = 101
|
|
||||||
const val ERROR_FIELDS_CANNOT_BE_EMPTY = "Fields cannot be empty"
|
|
||||||
const val ERROR_VALIDATING_PASSWORD = "Passwords are not the same"
|
|
||||||
const val ERROR_PASSWORDS_CANT_BE_SAME = "New password can't be the same as old password."
|
|
||||||
const val CHANGE_PROFILE_IMAGE_KEY = "CHANGE_PROFILE_IMAGE_KEY"
|
|
||||||
const val CHANGE_PROFILE_IMAGE_VALUE = "CHANGE_PROFILE_IMAGE_VALUE"
|
|
||||||
const val TAP_TO_REVEAL = "Tap to Reveal"
|
|
||||||
const val NAME = "Name : "
|
|
||||||
const val ERROR_FETCHING_TRANSACTION_DETAILS = "Error fetching details"
|
|
||||||
|
|
||||||
// const val WHITE_BACK_BUTTON = R.drawable.ic_arrow_back_white_24dp
|
|
||||||
// const val BLACK_BACK_BUTTON = R.drawable.ic_arrow_back_black_24dp
|
|
||||||
const val VIEW = "View"
|
|
||||||
const val CURRENT_PASSCODE = "current passcode"
|
|
||||||
const val UPDATE_PASSCODE = "update passcode"
|
|
||||||
const val SELECT_DATE = "SELECT DATE"
|
|
||||||
const val SI_ID = "standing_instruction_id"
|
|
||||||
const val UNAUTHORIZED_ERROR = "401 Unauthorized"
|
|
||||||
const val RECEIPT_SHARING_MESSAGE = "Receipt link for the transaction "
|
|
||||||
const val TO = " to "
|
|
||||||
const val COLON = " : "
|
|
||||||
const val REQUEST_CAMERA = 0
|
|
||||||
const val SCAN_QR_REQUEST_CODE = 666
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
object CreditCardUtils {
|
|
||||||
fun validateCreditCardNumber(str: String): Boolean {
|
|
||||||
if (str.isEmpty()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val ints = IntArray(str.length)
|
|
||||||
for (i in str.indices) {
|
|
||||||
ints[i] = str.substring(i, i + 1).toInt()
|
|
||||||
}
|
|
||||||
run {
|
|
||||||
var i = ints.size - 2
|
|
||||||
while (i >= 0) {
|
|
||||||
var j = ints[i]
|
|
||||||
j *= 2
|
|
||||||
if (j > 9) {
|
|
||||||
j = j % 10 + 1
|
|
||||||
}
|
|
||||||
ints[i] = j
|
|
||||||
i -= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var sum = 0
|
|
||||||
for (i in ints.indices) {
|
|
||||||
sum += ints[i]
|
|
||||||
}
|
|
||||||
return sum % 10 == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
|
|
||||||
// TODO Move into separate module
|
|
||||||
object DebugUtil {
|
|
||||||
|
|
||||||
fun log(vararg objects: Any): Array<Any> {
|
|
||||||
var stringToPrint = ""
|
|
||||||
for (`object` in objects) {
|
|
||||||
stringToPrint += "$`object`, "
|
|
||||||
}
|
|
||||||
stringToPrint = stringToPrint.substring(0, stringToPrint.lastIndexOf(','))
|
|
||||||
Log.d("QXZ:: ", stringToPrint)
|
|
||||||
return objects as Array<Any>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.OutputStream
|
|
||||||
|
|
||||||
object FileUtils {
|
|
||||||
|
|
||||||
fun writeInputStreamDataToFile(inputStream: InputStream, file: File?): Boolean {
|
|
||||||
return try {
|
|
||||||
val out: OutputStream = FileOutputStream(file)
|
|
||||||
val buf = ByteArray(1024)
|
|
||||||
var len: Int
|
|
||||||
while (inputStream.read(buf).also { len = it } > 0) {
|
|
||||||
out.write(buf, 0, len)
|
|
||||||
}
|
|
||||||
out.close()
|
|
||||||
inputStream.close()
|
|
||||||
true
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("Message", e.message.toString())
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
const val PAYEE_EXTERNAL_ID_ARG = "payeeExternalId"
|
|
||||||
const val TRANSFER_AMOUNT_ARG = "transferAmount"
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.common
|
|
||||||
|
|
||||||
import java.text.NumberFormat
|
|
||||||
import java.util.Currency
|
|
||||||
|
|
||||||
object Utils {
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun getFormattedAccountBalance(
|
|
||||||
balance: Double?,
|
|
||||||
currencyCode: String?,
|
|
||||||
maximumFractionDigits: Int? = 0,
|
|
||||||
): String {
|
|
||||||
val accountBalanceFormatter = NumberFormat.getCurrencyInstance()
|
|
||||||
accountBalanceFormatter.maximumFractionDigits = maximumFractionDigits ?: 0
|
|
||||||
accountBalanceFormatter.currency = Currency.getInstance(currencyCode)
|
|
||||||
return accountBalanceFormatter.format(balance)
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns in "$ 10,000.00" format
|
|
||||||
fun getNewCurrencyFormatter(
|
|
||||||
balance: Double,
|
|
||||||
currencySymbol: String,
|
|
||||||
minimumFractionDigit: Int = 0,
|
|
||||||
): String {
|
|
||||||
val accountBalanceFormatter = NumberFormat.getNumberInstance().apply {
|
|
||||||
maximumFractionDigits = 2
|
|
||||||
minimumFractionDigits = minimumFractionDigit
|
|
||||||
}
|
|
||||||
return currencySymbol + " " + accountBalanceFormatter.format(balance)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> List<T>.toArrayList(): ArrayList<T> {
|
|
||||||
val array: ArrayList<T> = ArrayList()
|
|
||||||
for (index in this) array.add(index)
|
|
||||||
return array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.core.network
|
|
||||||
|
|
||||||
import org.koin.core.annotation.Qualifier
|
|
||||||
|
|
||||||
@Qualifier
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class Dispatcher(val mifosDispatcher: MifosDispatchers)
|
|
||||||
|
|
||||||
enum class MifosDispatchers {
|
|
||||||
Default,
|
|
||||||
IO,
|
|
||||||
}
|
|
||||||
|
|
||||||
@Qualifier
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
annotation class ApplicationScope
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.core.network.di
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
|
||||||
import org.koin.core.qualifier.named
|
|
||||||
import org.koin.dsl.module
|
|
||||||
|
|
||||||
val CoroutineScopesModule = module {
|
|
||||||
|
|
||||||
single<CoroutineScope>(named("ApplicationScope")) {
|
|
||||||
CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.mifospay.core.network.di
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import org.koin.core.qualifier.named
|
|
||||||
import org.koin.dsl.module
|
|
||||||
import org.mifospay.core.network.MifosDispatchers
|
|
||||||
|
|
||||||
val DispatchersModule = module {
|
|
||||||
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.IO }
|
|
||||||
single<CoroutineDispatcher>(named(MifosDispatchers.Default.name)) { Dispatchers.Default }
|
|
||||||
}
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
import platform.Foundation.NSNumber
|
||||||
|
import platform.Foundation.NSNumberFormatter
|
||||||
|
import platform.Foundation.NSNumberFormatterCurrencyStyle
|
||||||
|
|
||||||
|
actual object CurrencyFormatter {
|
||||||
|
actual fun format(
|
||||||
|
balance: Double?,
|
||||||
|
currencyCode: String?,
|
||||||
|
maximumFractionDigits: Int?,
|
||||||
|
): String {
|
||||||
|
val numberFormatter = NSNumberFormatter()
|
||||||
|
numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle
|
||||||
|
numberFormatter.currencyCode = currencyCode ?: "$"
|
||||||
|
numberFormatter.maximumFractionDigits = (maximumFractionDigits ?: 0).toULong()
|
||||||
|
return numberFormatter.stringFromNumber(NSNumber(balance ?: 0.0)) ?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
import kotlinx.cinterop.BetaInteropApi
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
|
import kotlinx.cinterop.allocArrayOf
|
||||||
|
import kotlinx.cinterop.memScoped
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import platform.Foundation.NSData
|
||||||
|
import platform.Foundation.create
|
||||||
|
import platform.Foundation.writeToFile
|
||||||
|
|
||||||
|
// iOS implementation
|
||||||
|
@BetaInteropApi
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
actual fun createPlatformFileUtils(): FileUtils = object : FileUtils {
|
||||||
|
override suspend fun writeInputStreamDataToFile(
|
||||||
|
inputStream: ByteArray,
|
||||||
|
filePath: String,
|
||||||
|
): Boolean =
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
try {
|
||||||
|
val nsData = inputStream.toNSData()
|
||||||
|
nsData.writeToFile(filePath, true)
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
FileUtils.logger.e { "Error writing file: ${e.message}" }
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BetaInteropApi
|
||||||
|
fun ByteArray.toNSData(): NSData = memScoped {
|
||||||
|
NSData.create(bytes = allocArrayOf(this@toNSData), length = this@toNSData.size.toULong())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
actual interface Parcelable
|
||||||
|
actual annotation class IgnoredOnParcel
|
||||||
|
actual annotation class Parcelize
|
||||||
|
actual interface Parceler<P> {
|
||||||
|
actual fun create(parcel: Parcel): P
|
||||||
|
actual fun P.write(parcel: Parcel, flags: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual annotation class TypeParceler<T, P : Parceler<in T>>
|
||||||
|
|
||||||
|
actual class Parcel {
|
||||||
|
actual fun readString(): String? = null
|
||||||
|
actual fun readByte(): Byte = 1
|
||||||
|
|
||||||
|
actual fun readInt(): Int = 1
|
||||||
|
|
||||||
|
actual fun readFloat(): Float = 1f
|
||||||
|
|
||||||
|
actual fun readDouble(): Double = 1.0
|
||||||
|
|
||||||
|
actual fun writeByte(value: Byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeInt(value: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeFloat(value: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeDouble(value: Double) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeString(value: String?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
actual val ioDispatcherModule: Module
|
||||||
|
get() = module {
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.Default }
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
actual object CurrencyFormatter {
|
||||||
|
actual fun format(
|
||||||
|
balance: Double?,
|
||||||
|
currencyCode: String?,
|
||||||
|
maximumFractionDigits: Int?,
|
||||||
|
): String {
|
||||||
|
return "$currencyCode ${
|
||||||
|
balance?.let {
|
||||||
|
val formattedBalance = balance.toString()
|
||||||
|
val fractionDigits = formattedBalance.substringAfterLast(".")
|
||||||
|
val fractionDigitsLength = fractionDigits.length
|
||||||
|
val fractionDigitsToDisplay = if (fractionDigitsLength > maximumFractionDigits!!) {
|
||||||
|
fractionDigits.substring(0, maximumFractionDigits)
|
||||||
|
} else {
|
||||||
|
fractionDigits
|
||||||
|
}
|
||||||
|
val integerDigits = formattedBalance.substringBeforeLast(".")
|
||||||
|
val integerDigitsWithCommas =
|
||||||
|
integerDigits.reversed().chunked(3).joinToString(",").reversed()
|
||||||
|
"$integerDigitsWithCommas.$fractionDigitsToDisplay"
|
||||||
|
} ?: "0.00"
|
||||||
|
}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.common
|
||||||
|
|
||||||
|
actual fun createPlatformFileUtils(): FileUtils = CommonFileUtils()
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.common
|
||||||
|
|
||||||
|
actual interface Parcelable
|
||||||
|
actual annotation class IgnoredOnParcel
|
||||||
|
actual annotation class Parcelize
|
||||||
|
actual interface Parceler<P> {
|
||||||
|
actual fun create(parcel: Parcel): P
|
||||||
|
actual fun P.write(parcel: Parcel, flags: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual annotation class TypeParceler<T, P : Parceler<in T>>
|
||||||
|
|
||||||
|
actual class Parcel {
|
||||||
|
actual fun readString(): String? = null
|
||||||
|
actual fun readByte(): Byte = 1
|
||||||
|
|
||||||
|
actual fun readInt(): Int = 1
|
||||||
|
|
||||||
|
actual fun readFloat(): Float = 1f
|
||||||
|
|
||||||
|
actual fun readDouble(): Double = 1.0
|
||||||
|
|
||||||
|
actual fun writeByte(value: Byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeInt(value: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeFloat(value: Float) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeDouble(value: Double) {
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun writeString(value: String?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.common.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
|
||||||
|
actual val ioDispatcherModule: Module
|
||||||
|
get() = module {
|
||||||
|
single<CoroutineDispatcher>(named(MifosDispatchers.IO.name)) { Dispatchers.Default }
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@
|
|||||||
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.mifospay.android.library)
|
alias(libs.plugins.mifospay.kmp.library)
|
||||||
alias(libs.plugins.kotlin.parcelize)
|
alias(libs.plugins.kotlin.parcelize)
|
||||||
id("kotlinx-serialization")
|
id("kotlinx-serialization")
|
||||||
}
|
}
|
||||||
@ -23,26 +23,26 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
commonMain.dependencies {
|
||||||
api(projects.core.common)
|
api(projects.core.common)
|
||||||
|
api(projects.core.datastore)
|
||||||
api(projects.core.model)
|
api(projects.core.model)
|
||||||
api(projects.core.network)
|
implementation(projects.core.network)
|
||||||
|
implementation(projects.core.analytics)
|
||||||
implementation(libs.squareup.retrofit2) {
|
|
||||||
// exclude Retrofit’s OkHttp peer-dependency module and define your own module import
|
|
||||||
exclude(module = "okhttp")
|
|
||||||
}
|
|
||||||
implementation(libs.squareup.retrofit.adapter.rxjava)
|
|
||||||
implementation(libs.squareup.retrofit.converter.gson)
|
|
||||||
implementation(libs.squareup.okhttp)
|
|
||||||
implementation(libs.squareup.logging.interceptor)
|
|
||||||
|
|
||||||
implementation(libs.reactivex.rxjava.android)
|
|
||||||
implementation(libs.reactivex.rxjava)
|
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
|
||||||
androidTestImplementation(libs.espresso.core)
|
|
||||||
|
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTest.dependencies {
|
||||||
|
implementation(libs.multiplatform.settings)
|
||||||
|
implementation(libs.multiplatform.settings.test)
|
||||||
|
}
|
||||||
|
|
||||||
|
androidMain.dependencies {
|
||||||
|
implementation(libs.androidx.core.ktx)
|
||||||
|
implementation(libs.androidx.tracing.ktx)
|
||||||
implementation(libs.koin.android)
|
implementation(libs.koin.android)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import org.mifospay.core.data.util.ConnectivityManagerNetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.NetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneBroadcastMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneMonitor
|
||||||
|
|
||||||
|
class AndroidPlatformDependentDataModule(
|
||||||
|
private val context: Context,
|
||||||
|
private val dispatcher: CoroutineDispatcher,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
) : PlatformDependentDataModule {
|
||||||
|
override val networkMonitor: NetworkMonitor by lazy {
|
||||||
|
ConnectivityManagerNetworkMonitor(context, dispatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val timeZoneMonitor: TimeZoneMonitor by lazy {
|
||||||
|
TimeZoneBroadcastMonitor(context, scope, dispatcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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.mifospay.core.data.di
|
||||||
|
|
||||||
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
import org.mifospay.core.data.util.ConnectivityManagerNetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.NetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneBroadcastMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneMonitor
|
||||||
|
|
||||||
|
val AndroidDataModule = module {
|
||||||
|
single<NetworkMonitor> {
|
||||||
|
ConnectivityManagerNetworkMonitor(androidContext(), get(named(MifosDispatchers.IO.name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
single<TimeZoneMonitor> {
|
||||||
|
TimeZoneBroadcastMonitor(
|
||||||
|
context = androidContext(),
|
||||||
|
appScope = get(named("ApplicationScope")),
|
||||||
|
ioDispatcher = get(named(MifosDispatchers.IO.name)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
AndroidPlatformDependentDataModule(
|
||||||
|
context = androidContext(),
|
||||||
|
dispatcher = get(named(MifosDispatchers.IO.name)),
|
||||||
|
scope = get(named("ApplicationScope")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual val platformModule: Module = AndroidDataModule
|
||||||
|
|
||||||
|
actual val getPlatformDataModule: PlatformDependentDataModule
|
||||||
|
get() = org.koin.core.context.GlobalContext.get().get()
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.ConnectivityManager.NetworkCallback
|
||||||
|
import android.net.Network
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.net.NetworkRequest
|
||||||
|
import android.net.NetworkRequest.Builder
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.conflate
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
|
||||||
|
internal class ConnectivityManagerNetworkMonitor(
|
||||||
|
private val context: Context,
|
||||||
|
ioDispatcher: CoroutineDispatcher,
|
||||||
|
) : NetworkMonitor {
|
||||||
|
override val isOnline: Flow<Boolean> = callbackFlow {
|
||||||
|
val connectivityManager = context.getSystemService<ConnectivityManager>()
|
||||||
|
if (connectivityManager == null) {
|
||||||
|
channel.trySend(false)
|
||||||
|
channel.close()
|
||||||
|
return@callbackFlow
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback's methods are invoked on changes to *any* network matching the [NetworkRequest],
|
||||||
|
* not just the active network. So we can simply track the presence (or absence) of such [Network].
|
||||||
|
*/
|
||||||
|
val callback = object : NetworkCallback() {
|
||||||
|
|
||||||
|
private val networks = mutableSetOf<Network>()
|
||||||
|
|
||||||
|
override fun onAvailable(network: Network) {
|
||||||
|
networks += network
|
||||||
|
channel.trySend(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLost(network: Network) {
|
||||||
|
networks -= network
|
||||||
|
channel.trySend(networks.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val request = Builder()
|
||||||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
.build()
|
||||||
|
connectivityManager.registerNetworkCallback(request, callback)
|
||||||
|
/**
|
||||||
|
* Sends the latest connectivity status to the underlying channel.
|
||||||
|
*/
|
||||||
|
channel.trySend(connectivityManager.isCurrentlyConnected())
|
||||||
|
|
||||||
|
awaitClose {
|
||||||
|
connectivityManager.unregisterNetworkCallback(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flowOn(ioDispatcher)
|
||||||
|
.conflate()
|
||||||
|
|
||||||
|
private fun ConnectivityManager.isCurrentlyConnected() = activeNetwork
|
||||||
|
?.let(::getNetworkCapabilities)
|
||||||
|
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ?: false
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.util
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.os.Build.VERSION
|
||||||
|
import android.os.Build.VERSION_CODES
|
||||||
|
import androidx.tracing.trace
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.conflate
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.shareIn
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.toKotlinTimeZone
|
||||||
|
import java.time.ZoneId
|
||||||
|
|
||||||
|
internal class TimeZoneBroadcastMonitor(
|
||||||
|
private val context: Context,
|
||||||
|
appScope: CoroutineScope,
|
||||||
|
ioDispatcher: CoroutineDispatcher,
|
||||||
|
) : TimeZoneMonitor {
|
||||||
|
|
||||||
|
override val currentTimeZone: SharedFlow<TimeZone> =
|
||||||
|
callbackFlow {
|
||||||
|
// Send the default time zone first.
|
||||||
|
trySend(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
|
// Registers BroadcastReceiver for the TimeZone changes
|
||||||
|
val receiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (intent.action != Intent.ACTION_TIMEZONE_CHANGED) return
|
||||||
|
|
||||||
|
val zoneIdFromIntent = if (VERSION.SDK_INT < VERSION_CODES.R) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
// Starting Android R we also get the new TimeZone.
|
||||||
|
intent.getStringExtra(Intent.EXTRA_TIMEZONE)?.let { timeZoneId ->
|
||||||
|
// We need to convert it from java.util.Timezone to java.time.ZoneId
|
||||||
|
val zoneId = ZoneId.of(timeZoneId, ZoneId.SHORT_IDS)
|
||||||
|
// Convert to kotlinx.datetime.TimeZone
|
||||||
|
zoneId.toKotlinTimeZone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there isn't a zoneId in the intent, fallback to the systemDefault,
|
||||||
|
which should also reflect the change */
|
||||||
|
trySend(zoneIdFromIntent ?: TimeZone.currentSystemDefault())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("TimeZoneBroadcastReceiver.register") {
|
||||||
|
context.registerReceiver(receiver, IntentFilter(Intent.ACTION_TIMEZONE_CHANGED))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send here again, because registering the Broadcast Receiver can take up to several milliseconds.
|
||||||
|
// This way, we can reduce the likelihood that a TZ change wouldn't be caught with the Broadcast Receiver.
|
||||||
|
trySend(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
|
awaitClose {
|
||||||
|
context.unregisterReceiver(receiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We use to prevent multiple emissions of the same type, because we use trySend multiple times.
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.conflate()
|
||||||
|
.flowOn(ioDispatcher)
|
||||||
|
// Sharing the callback to prevent multiple BroadcastReceivers being registered
|
||||||
|
.shareIn(appScope, SharingStarted.WhileSubscribed(5_000), 1)
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.data.di
|
||||||
|
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.mifospay.core.data.util.NetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneMonitor
|
||||||
|
|
||||||
|
interface PlatformDependentDataModule {
|
||||||
|
val networkMonitor: NetworkMonitor
|
||||||
|
|
||||||
|
val timeZoneMonitor: TimeZoneMonitor
|
||||||
|
}
|
||||||
|
|
||||||
|
expect val platformModule: Module
|
||||||
|
|
||||||
|
expect val getPlatformDataModule: PlatformDependentDataModule
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.di
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.mifospay.core.common.MifosDispatchers
|
||||||
|
import org.mifospay.core.data.repository.AccountRepository
|
||||||
|
import org.mifospay.core.data.repository.AuthenticationRepository
|
||||||
|
import org.mifospay.core.data.repository.BeneficiaryRepository
|
||||||
|
import org.mifospay.core.data.repository.ClientRepository
|
||||||
|
import org.mifospay.core.data.repository.DocumentRepository
|
||||||
|
import org.mifospay.core.data.repository.InvoiceRepository
|
||||||
|
import org.mifospay.core.data.repository.KycLevelRepository
|
||||||
|
import org.mifospay.core.data.repository.LocalAssetRepository
|
||||||
|
import org.mifospay.core.data.repository.NotificationRepository
|
||||||
|
import org.mifospay.core.data.repository.RegistrationRepository
|
||||||
|
import org.mifospay.core.data.repository.RunReportRepository
|
||||||
|
import org.mifospay.core.data.repository.SavedCardRepository
|
||||||
|
import org.mifospay.core.data.repository.SavingsAccountRepository
|
||||||
|
import org.mifospay.core.data.repository.SearchRepository
|
||||||
|
import org.mifospay.core.data.repository.SelfServiceRepository
|
||||||
|
import org.mifospay.core.data.repository.StandingInstructionRepository
|
||||||
|
import org.mifospay.core.data.repository.ThirdPartyTransferRepository
|
||||||
|
import org.mifospay.core.data.repository.TwoFactorAuthRepository
|
||||||
|
import org.mifospay.core.data.repository.UserRepository
|
||||||
|
import org.mifospay.core.data.repositoryImp.AccountRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.AuthenticationRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.BeneficiaryRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.ClientRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.DocumentRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.InvoiceRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.KycLevelRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.LocalAssetRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.NotificationRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.RegistrationRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.RunReportRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.SavedCardRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.SavingsAccountRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.SearchRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.SelfServiceRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.StandingInstructionRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.ThirdPartyTransferRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.TwoFactorAuthRepositoryImpl
|
||||||
|
import org.mifospay.core.data.repositoryImp.UserRepositoryImpl
|
||||||
|
import org.mifospay.core.data.util.NetworkMonitor
|
||||||
|
import org.mifospay.core.data.util.TimeZoneMonitor
|
||||||
|
|
||||||
|
private val ioDispatcher = named(MifosDispatchers.IO.name)
|
||||||
|
private val unconfined = named(MifosDispatchers.Unconfined.name)
|
||||||
|
|
||||||
|
val RepositoryModule = module {
|
||||||
|
single<Json> { Json { ignoreUnknownKeys = true } }
|
||||||
|
|
||||||
|
single<AccountRepository> { AccountRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<AuthenticationRepository> {
|
||||||
|
AuthenticationRepositoryImpl(get(), get(ioDispatcher))
|
||||||
|
}
|
||||||
|
single<BeneficiaryRepository> { BeneficiaryRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<ClientRepository> {
|
||||||
|
ClientRepositoryImpl(
|
||||||
|
apiManager = get(),
|
||||||
|
fineractApiManager = get(),
|
||||||
|
ioDispatcher = get(ioDispatcher),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single<DocumentRepository> { DocumentRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<InvoiceRepository> { InvoiceRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<KycLevelRepository> { KycLevelRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<NotificationRepository> { NotificationRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<RegistrationRepository> { RegistrationRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<RunReportRepository> { RunReportRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<SavedCardRepository> { SavedCardRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<SavingsAccountRepository> { SavingsAccountRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<SearchRepository> { SearchRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<SelfServiceRepository> { SelfServiceRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<StandingInstructionRepository> {
|
||||||
|
StandingInstructionRepositoryImpl(get(), get(ioDispatcher))
|
||||||
|
}
|
||||||
|
single<ThirdPartyTransferRepository> {
|
||||||
|
ThirdPartyTransferRepositoryImpl(get(), get(ioDispatcher))
|
||||||
|
}
|
||||||
|
single<TwoFactorAuthRepository> { TwoFactorAuthRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
single<UserRepository> { UserRepositoryImpl(get(), get(ioDispatcher)) }
|
||||||
|
|
||||||
|
includes(platformModule)
|
||||||
|
single<PlatformDependentDataModule> { getPlatformDataModule }
|
||||||
|
single<NetworkMonitor> { getPlatformDataModule.networkMonitor }
|
||||||
|
single<TimeZoneMonitor> { getPlatformDataModule.timeZoneMonitor }
|
||||||
|
single<LocalAssetRepository> {
|
||||||
|
LocalAssetRepositoryImpl(
|
||||||
|
ioDispatcher = get(qualifier = ioDispatcher),
|
||||||
|
unconfinedDispatcher = get(unconfined),
|
||||||
|
networkJson = get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.model.account.Account
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingAccountEntity
|
||||||
|
import org.mifospay.core.network.model.entity.client.ClientAccountsEntity
|
||||||
|
|
||||||
|
fun ClientAccountsEntity.toAccount(): List<Account> {
|
||||||
|
return this.savingsAccounts.toAccount()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<SavingAccountEntity>.toAccount(): List<Account> {
|
||||||
|
return map {
|
||||||
|
Account(
|
||||||
|
name = it.productName,
|
||||||
|
number = it.accountNo,
|
||||||
|
id = it.id,
|
||||||
|
balance = it.accountBalance,
|
||||||
|
currency = it.currency,
|
||||||
|
productId = it.productId,
|
||||||
|
status = it.status,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.model.client.Client
|
||||||
|
import org.mifospay.core.model.client.ClientAddress
|
||||||
|
import org.mifospay.core.model.client.ClientStatus
|
||||||
|
import org.mifospay.core.model.client.ClientTimeline
|
||||||
|
import org.mifospay.core.model.client.NewClient
|
||||||
|
import org.mifospay.core.model.client.UpdatedClient
|
||||||
|
import org.mifospay.core.network.model.entity.Page
|
||||||
|
import org.mifospay.core.network.model.entity.client.Address
|
||||||
|
import org.mifospay.core.network.model.entity.client.ClientEntity
|
||||||
|
import org.mifospay.core.network.model.entity.client.ClientTimelineEntity
|
||||||
|
import org.mifospay.core.network.model.entity.client.NewClientEntity
|
||||||
|
import org.mifospay.core.network.model.entity.client.Status
|
||||||
|
import org.mifospay.core.network.model.entity.client.UpdateClientEntity
|
||||||
|
|
||||||
|
fun ClientEntity.toModel(): Client {
|
||||||
|
return Client(
|
||||||
|
id = id ?: 0,
|
||||||
|
accountNo = accountNo ?: "",
|
||||||
|
externalId = externalId ?: "",
|
||||||
|
active = active,
|
||||||
|
activationDate = activationDate,
|
||||||
|
firstname = firstname ?: "",
|
||||||
|
lastname = lastname ?: "",
|
||||||
|
displayName = displayName ?: "",
|
||||||
|
mobileNo = mobileNo ?: "",
|
||||||
|
emailAddress = emailAddress ?: "",
|
||||||
|
dateOfBirth = dateOfBirth,
|
||||||
|
isStaff = isStaff ?: false,
|
||||||
|
officeId = officeId ?: 0,
|
||||||
|
officeName = officeName ?: "",
|
||||||
|
savingsProductName = savingsProductName ?: "",
|
||||||
|
status = status?.toModel() ?: ClientStatus(),
|
||||||
|
timeline = timeline?.toModel() ?: ClientTimeline(),
|
||||||
|
legalForm = legalForm?.toModel() ?: ClientStatus(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<ClientEntity>.toModel(): List<Client> = map { it.toModel() }
|
||||||
|
|
||||||
|
fun Page<ClientEntity>.toModel(): Page<Client> {
|
||||||
|
return Page(
|
||||||
|
totalFilteredRecords = this.totalFilteredRecords,
|
||||||
|
pageItems = this.pageItems.map { it.toModel() }.toMutableList(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun NewClient.toEntity(): NewClientEntity {
|
||||||
|
return NewClientEntity(
|
||||||
|
firstname = firstname,
|
||||||
|
lastname = lastname,
|
||||||
|
externalId = externalId,
|
||||||
|
mobileNo = mobileNo,
|
||||||
|
address = address.toEntity(),
|
||||||
|
savingsProductId = savingsProductId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClientAddress.toEntity(): Address {
|
||||||
|
return Address(
|
||||||
|
addressLine1 = addressLine1,
|
||||||
|
addressLine2 = addressLine2,
|
||||||
|
postalCode = postalCode,
|
||||||
|
stateProvinceId = stateProvinceId,
|
||||||
|
countryId = countryId,
|
||||||
|
addressTypeId = addressTypeId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Status.toModel(): ClientStatus {
|
||||||
|
return ClientStatus(
|
||||||
|
id = id ?: 0,
|
||||||
|
code = code ?: "",
|
||||||
|
value = value ?: "",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClientTimelineEntity.toModel(): ClientTimeline {
|
||||||
|
return ClientTimeline(
|
||||||
|
submittedOnDate = submittedOnDate,
|
||||||
|
activatedOnDate = activatedOnDate,
|
||||||
|
activatedByUsername = activatedByUsername,
|
||||||
|
activatedByFirstname = activatedByFirstname,
|
||||||
|
activatedByLastname = activatedByLastname,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun UpdatedClient.toEntity(): UpdateClientEntity {
|
||||||
|
return UpdateClientEntity(
|
||||||
|
firstname = firstname,
|
||||||
|
lastname = lastname,
|
||||||
|
externalId = externalId,
|
||||||
|
mobileNo = mobileNo,
|
||||||
|
emailAddress = emailAddress,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingAccount
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingAccountDetail
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingAccountEntity
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingsWithAssociationsEntity
|
||||||
|
|
||||||
|
fun SavingAccountEntity.toModel(): SavingAccount {
|
||||||
|
return SavingAccount(
|
||||||
|
id = id,
|
||||||
|
accountNo = accountNo,
|
||||||
|
productId = productId,
|
||||||
|
productName = productName,
|
||||||
|
shortProductName = shortProductName,
|
||||||
|
status = status,
|
||||||
|
currency = currency,
|
||||||
|
accountBalance = accountBalance,
|
||||||
|
accountType = accountType,
|
||||||
|
timeline = timeline,
|
||||||
|
subStatus = subStatus,
|
||||||
|
lastActiveTransactionDate = lastActiveTransactionDate,
|
||||||
|
depositType = depositType,
|
||||||
|
externalId = externalId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SavingsWithAssociationsEntity.toSavingDetail(): SavingAccountDetail {
|
||||||
|
return SavingAccountDetail(
|
||||||
|
id = id,
|
||||||
|
accountNo = accountNo,
|
||||||
|
depositType = depositType,
|
||||||
|
clientId = clientId,
|
||||||
|
clientName = clientName,
|
||||||
|
savingsProductId = savingsProductId,
|
||||||
|
savingsProductName = savingsProductName,
|
||||||
|
fieldOfficerId = fieldOfficerId,
|
||||||
|
status = status,
|
||||||
|
timeline = timeline,
|
||||||
|
currency = currency,
|
||||||
|
nominalAnnualInterestRate = nominalAnnualInterestRate,
|
||||||
|
withdrawalFeeForTransfers = withdrawalFeeForTransfers,
|
||||||
|
allowOverdraft = allowOverdraft,
|
||||||
|
enforceMinRequiredBalance = enforceMinRequiredBalance,
|
||||||
|
lienAllowed = lienAllowed,
|
||||||
|
withHoldTax = withHoldTax,
|
||||||
|
lastActiveTransactionDate = lastActiveTransactionDate,
|
||||||
|
isDormancyTrackingActive = isDormancyTrackingActive,
|
||||||
|
summary = summary,
|
||||||
|
transactions = transactions.map { it.toModel() },
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +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-wallet/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
package org.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.model.search.SearchResult
|
||||||
|
import org.mifospay.core.network.model.entity.SearchedEntity
|
||||||
|
|
||||||
|
fun SearchedEntity.toModel(): SearchResult {
|
||||||
|
return SearchResult(
|
||||||
|
entityId = entityId,
|
||||||
|
entityAccountNo = entityAccountNo,
|
||||||
|
entityName = entityName,
|
||||||
|
entityType = entityType,
|
||||||
|
parentId = parentId,
|
||||||
|
parentName = parentName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<SearchedEntity>.toSearchResult(): List<SearchResult> = map { it.toModel() }
|
||||||
@ -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.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.common.DateHelper
|
||||||
|
import org.mifospay.core.model.savingsaccount.SavingsWithAssociationsEntity
|
||||||
|
import org.mifospay.core.model.savingsaccount.Transaction
|
||||||
|
import org.mifospay.core.model.savingsaccount.TransactionType
|
||||||
|
import org.mifospay.core.model.savingsaccount.TransactionsEntity
|
||||||
|
|
||||||
|
fun SavingsWithAssociationsEntity.toTransactionList(): List<Transaction> {
|
||||||
|
return this.transactions.map { it.toModel() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TransactionsEntity.toModel(): Transaction {
|
||||||
|
return Transaction(
|
||||||
|
transactionId = this.id,
|
||||||
|
amount = this.amount,
|
||||||
|
date = DateHelper.getDateAsString(this.submittedOnDate),
|
||||||
|
currency = this.currency,
|
||||||
|
transactionType = when {
|
||||||
|
this.transactionType.deposit -> TransactionType.CREDIT
|
||||||
|
this.transactionType.withdrawal -> TransactionType.DEBIT
|
||||||
|
else -> TransactionType.OTHER
|
||||||
|
},
|
||||||
|
transferId = this.transfer?.id,
|
||||||
|
accountId = this.accountId,
|
||||||
|
accountNo = this.accountNo,
|
||||||
|
originalTransactionId = this.originalTransactionId,
|
||||||
|
paymentDetailId = this.paymentDetailData?.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -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.mifospay.core.data.mapper
|
||||||
|
|
||||||
|
import org.mifospay.core.model.user.NewUser
|
||||||
|
import org.mifospay.core.model.user.RoleInfo
|
||||||
|
import org.mifospay.core.model.user.UserInfo
|
||||||
|
import org.mifospay.core.network.model.entity.Role
|
||||||
|
import org.mifospay.core.network.model.entity.user.NewUserEntity
|
||||||
|
import org.mifospay.core.network.model.entity.user.User
|
||||||
|
|
||||||
|
private const val OFFICE_ID = 1
|
||||||
|
private const val MOBILE_WALLET_ROLE_ID = 2
|
||||||
|
private const val SUPER_USER_ROLE_ID = 1
|
||||||
|
|
||||||
|
val NEW_USER_ROLE_IDS: ArrayList<Int> = arrayListOf(MOBILE_WALLET_ROLE_ID, SUPER_USER_ROLE_ID)
|
||||||
|
|
||||||
|
fun NewUser.toEntity(): NewUserEntity {
|
||||||
|
return NewUserEntity(
|
||||||
|
username = username,
|
||||||
|
firstname = firstname,
|
||||||
|
lastname = lastname,
|
||||||
|
email = email,
|
||||||
|
password = password,
|
||||||
|
officeId = OFFICE_ID,
|
||||||
|
roles = NEW_USER_ROLE_IDS,
|
||||||
|
sendPasswordToEmail = false,
|
||||||
|
isSelfServiceUser = true,
|
||||||
|
repeatPassword = password,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun User.toUserInfo() = UserInfo(
|
||||||
|
username = username,
|
||||||
|
userId = userId,
|
||||||
|
base64EncodedAuthenticationKey = base64EncodedAuthenticationKey,
|
||||||
|
authenticated = authenticated,
|
||||||
|
officeId = officeId,
|
||||||
|
officeName = officeName,
|
||||||
|
roles = roles.map { it.toRoleInfo() },
|
||||||
|
permissions = permissions,
|
||||||
|
clients = clients,
|
||||||
|
shouldRenewPassword = shouldRenewPassword,
|
||||||
|
isTwoFactorAuthenticationRequired = isTwoFactorAuthenticationRequired,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Role.toRoleInfo() = RoleInfo(
|
||||||
|
id = id ?: "",
|
||||||
|
name = name ?: "",
|
||||||
|
description = description ?: "",
|
||||||
|
disabled = disabled,
|
||||||
|
)
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.mifospay.core.data.repository
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import org.mifospay.core.common.DataState
|
||||||
|
import org.mifospay.core.model.account.Account
|
||||||
|
import org.mifospay.core.model.account.AccountTransferPayload
|
||||||
|
import org.mifospay.core.model.savingsaccount.Transaction
|
||||||
|
import org.mifospay.core.model.savingsaccount.TransferDetail
|
||||||
|
import org.mifospay.core.model.search.AccountResult
|
||||||
|
|
||||||
|
interface AccountRepository {
|
||||||
|
fun getTransaction(accountId: Long, transactionId: Long): Flow<DataState<Transaction>>
|
||||||
|
|
||||||
|
fun getAccountTransfer(transferId: Long): Flow<DataState<TransferDetail>>
|
||||||
|
|
||||||
|
fun searchAccounts(query: String): Flow<DataState<List<AccountResult>>>
|
||||||
|
|
||||||
|
fun getSelfAccounts(clientId: Long): Flow<DataState<List<Account>>>
|
||||||
|
|
||||||
|
suspend fun makeTransfer(payload: AccountTransferPayload): DataState<String>
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user