feat: Final KMM Clean Up (#1814)

* 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 commit bb63058e49.

---------

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 commit bb63058e49.

---------

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 commit bb63058e49.

---------

Co-authored-by: Sk Niyaj Ali <niyaj639@gmail.com>

* Merge kmm-impl to dev

* feat: Final Dev Cleanup

- Fixed CI Workflow
- Enabled Weekly & Monthly Release
- Fixed Release Build Issue

---------

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:
Sk Niyaj Ali 2024-11-19 08:47:00 +05:30 committed by GitHub
parent 3782fd0d6f
commit 6980ca7c5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 1970 additions and 1388 deletions

View File

@ -41,7 +41,7 @@ runs:
id: version-generator
shell: bash
run: |
mkdir -p ./app/build/outputs/
mkdir -p ./mifospay-android/build/outputs/
echo "Previous Release Tag:"
echo "${{ steps.latest-release-tag.outputs.result }}"
@ -49,8 +49,8 @@ runs:
echo "Full Changelog:"
CHANGELOG="${{ steps.generate-notes.outputs.result }}"
echo -e "$CHANGELOG"
printf "$CHANGELOG" > ./mifospay/build/outputs/changelogGithub
printf "$CHANGELOG" > ./mifospay-android/build/outputs/changelogGithub
echo "Beta Changelog:"
git log --format="* %s" HEAD^..HEAD
git log --format="* %s" HEAD^..HEAD > ./mifospay/build/outputs/changelogBeta
git log --format="* %s" HEAD^..HEAD > ./mifospay-android/build/outputs/changelogBeta

View File

@ -16,26 +16,25 @@ runs:
- name: Mock debug google-services.json
shell: bash
run: |
cp .github/mock-google-services.json mifospay/src/demo/google-services.json
cp .github/mock-google-services.json mifospay/src/prod/google-services.json
cp .github/mock-google-services.json mifospay-android/google-services.json
- name: Inflate release_keystore.keystore
shell: bash
env:
KEYSTORE: ${{ inputs.keystore }}
run: |
echo $KEYSTORE | base64 --decode > mifospay/release_keystore.keystore
echo $KEYSTORE | base64 --decode > mifospay-android/release_keystore.keystore
- name: Inflate google-services.json
shell: bash
env:
GOOGLE_SERVICES: ${{ inputs.google-services }}
run: |
echo $GOOGLE_SERVICES > mifospay/google-services.json
echo $GOOGLE_SERVICES > mifospay-android/google-services.json
- name: Inflate playStorePublishServiceCredentialsFile.json
shell: bash
env:
CREDS: ${{ inputs.playstore-creds }}
run: |
echo $CREDS > mifospay/playStorePublishServiceCredentialsFile.json
echo $CREDS > mifospay-android/playStorePublishServiceCredentialsFile.json

View File

@ -1,22 +1,49 @@
name: On Push
name: Internal Or Beta Release
on:
workflow_dispatch:
inputs:
beta:
description: 'true if this is a beta release'
release_type:
required: false
default: 'false'
push:
branches:
- master
default: 'internal'
description: Please select the release type
type: choice
options:
- internal
- beta
env:
SUPPLY_UPLOAD_MAX_RETRIES: 5
jobs:
build_desktop_app:
strategy:
matrix:
os:
- macos-latest
- ubuntu-latest
- windows-latest
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 17
- name: Build Desktop App
env:
NOTARIZATION_APPLE_ID: ${{ secrets.NOTARIZATION_APPLE_ID }}
NOTARIZATION_PASSWORD: ${{ secrets.NOTARIZATION_PASSWORD }}
NOTARIZATION_TEAM_ID: ${{ secrets.NOTARIZATION_TEAM_ID }}
run: ./gradlew packageReleaseDistributionForCurrentOS
app_build:
name: Github, Firebase, and Sentry Release
needs: [ build_desktop_app ]
runs-on: ubuntu-latest
permissions:
contents: write
@ -63,7 +90,7 @@ jobs:
KEYSTORE_ALIAS_PASSWORD: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS_PASSWORD }}
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
run: |
./gradlew :mifospay:assembleRelease
./gradlew :mifospay-android:assembleRelease
- name: Archive Build
uses: actions/upload-artifact@v4
@ -71,25 +98,29 @@ jobs:
path: ./**/*.apk
- name: Create Version File
if: github.event.inputs.beta == 'true'
if: github.event.inputs.release_type == 'beta'
shell: bash
env:
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
run: |
echo $VERSION_CODE > ./app/build/outputs/version_code.txt
echo $VERSION_CODE > ./mifospay-android/build/outputs/version_code.txt
- name: Create Github Pre-Release
if: github.event.inputs.beta == 'true'
if: github.event.inputs.release_type == 'beta'
uses: softprops/action-gh-release@v2.0.8
with:
tag_name: ${{ steps.rel_number.outputs.version }}
body_path: ./app/build/outputs/changelogGithub
body_path: ./mifospay-android/build/outputs/changelogGithub
draft: false
prerelease: true
files: |
./mifospay/build/outputs/apk/demo/release/mifospay-demo-release.apk
./mifospay/build/outputs/apk/prod/release/mifospay-prod-release.apk
./mifospay/build/outputs/version_code.txt
./mifospay-android/build/outputs/apk/demo/release/mifospay-android-demo-release.apk
./mifospay-android/build/outputs/apk/prod/release/mifospay-android-prod-release.apk
./mifospay-android/build/outputs/version_code.txt
./mifospay-desktop/build/compose/binaries/main-release/exe/*.exe
./mifospay-desktop/build/compose/binaries/main-release/msi/*.msi
./mifospay-desktop/build/compose/binaries/main-release/deb/*.deb
./mifospay-desktop/build/compose/binaries/main-release/dmg/*.dmg
- name: Print `git status`
run: git status
@ -144,11 +175,11 @@ jobs:
KEYSTORE_ALIAS_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_ALIAS_PASSWORD }}
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
run: |
./gradlew :mifospay:bundleRelease
./gradlew :mifospay-android:bundleRelease
- name: Deploy to Playstore Internal
run: bundle exec fastlane deploy_internal
- name: Promote Internal to Beta
if: github.event.inputs.beta == 'true'
if: github.event.inputs.release_type == 'beta'
run: bundle exec fastlane promote_to_beta

49
.github/workflows/make_site.yaml vendored Normal file
View File

@ -0,0 +1,49 @@
name: Publish Web App
on:
# Runs on pushes targeting the default branch
push:
branches: ["dev"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build_web_app:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 17
- name: Build Web(JS) App
run: ./gradlew jsBrowserDistribution
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload static files as artifact
uses: actions/upload-pages-artifact@v3
with:
path: './mifospay-web/build/dist/js/productionExecutable/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@ -2,7 +2,7 @@ name: Mobile-Wallet CI[Master/Dev]
on:
push:
branches: [ dev, master, payment_hub ]
branches: [ dev ]
pull_request:
concurrency:
@ -62,6 +62,8 @@ jobs:
**/build/reports/detekt/detekt.md
dependency_guard:
needs: setup
runs-on: ubuntu-latest
@ -120,6 +122,8 @@ jobs:
**/build/reports/lint-results-*.html
**/build/test-results/test*UnitTest/**.xml
build:
needs: [ checks, dependency_guard, tests_and_lint ]
runs-on: ubuntu-latest
@ -144,3 +148,47 @@ jobs:
name: APKs
path: '**/build/outputs/apk/**/*.apk'
build_desktop_app:
needs: [ checks, dependency_guard, tests_and_lint ]
strategy:
matrix:
os:
- windows-latest
- ubuntu-latest
- macos-latest
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 17
- name: Build Desktop App
run: ./gradlew packageDistributionForCurrentOS
- name: Upload Windows Apps
if: matrix.os == 'windows-latest'
uses: actions/upload-artifact@v4
with:
name: Windows-App
path: |
./mifospay-desktop/build/compose/binaries/main/exe/*.exe
./mifospay-desktop/build/compose/binaries/main/msi/*.msi
- name: Upload Linux App
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: Windows-App
path: './mifospay-desktop/build/compose/binaries/main/deb/*.deb'
- name: Upload MacOS App
if: matrix.os == 'macos-latest'
uses: actions/upload-artifact@v4
with:
name: Windows-App
path: './mifospay-desktop/build/compose/binaries/main/dmg/*.dmg'

View File

@ -2,10 +2,8 @@ name: Bump our Calendar Version
on:
workflow_dispatch:
# This is a monthly cron job that runs on the first of the month at 3:30 AM UTC
# Turning off for now
# schedule:
# - cron: '30 3 1 * *'
schedule:
- cron: '30 3 1 * *'
jobs:
tag:
name: Tag Monthly Release

View File

@ -2,10 +2,8 @@ name: Tag Weekly Release
on:
workflow_dispatch:
# This is a weekly cron job that runs every Sunday at 4:00 AM UTC
# Turning off for now
# schedule:
# - cron: '0 4 * * 0'
schedule:
- cron: '0 4 */2 * 0'
jobs:
tag:
name: Tag Weekly Release
@ -33,9 +31,9 @@ jobs:
github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'onPush.yml',
ref: 'master',
workflow_id: 'internal_or_beta_release.yml',
ref: 'dev',
inputs: {
"beta": "true",
"release_type": "beta",
},
})

View File

@ -209,7 +209,10 @@ GEM
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
arm64-darwin-22
x64-mingw-ucrt
x86_64-linux
DEPENDENCIES
fastlane

117
LICENSE Normal file
View File

@ -0,0 +1,117 @@
Copyright 2024 Mifos Initiative
Mozilla Public License Version 2.0 (MPL-2.0)
1. Definitions
1.1. "Contributor"
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used by
a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code Form,
and Modifications of such Source Code Form, in each case including
portions thereof.
1.5. "Executable Form"
means any form of the work other than Source Code Form.
1.6. "Non-Commercial Use"
means any use of the work that is not primarily intended for or directed
towards commercial advantage or monetary compensation.
1.7. "Source Code Form"
means the form of the work preferred for making modifications.
1.8. "You" (or "Your")
means an individual or a legal entity exercising rights under this License.
For legal entities, "You" includes any entity that controls, is controlled
by, or is under common control with You. For purposes of this definition,
"control" means (a) the power, direct or indirect, to cause the direction
or management of such entity, whether by contract or otherwise, or (b)
ownership of more than fifty percent (50%) of the outstanding shares or
beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive
license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available, modify,
display, perform, distribute, and otherwise exploit its Contributions, either
on an unmodified basis, with Modifications, or as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions or
its Contributor Version.
2.2. Non-Commercial Use
You are not permitted to use the Covered Software for commercial purposes
without the prior written permission of RW MobiMedia UK Limited. This
includes, but is not limited to, selling the software, incorporating the
software into a product for sale, or offering services involving the
software. Commercial distribution of the software or its derivatives is
prohibited, including uploading the software to the Apple App Store, Google
Play Store, or any other commercial app marketplace, unless authorised by RW
MobiMedia UK Limited.
2.3. Attribution
You must give appropriate credit to RW MobiMedia UK Limited and any open-source
contributors, provide a link to the license, and indicate if changes were made.
Attribution must be displayed in a prominent manner in any distributed or published
form of the software, including but not limited to the about page of an application
or documentation files. You may do so in any reasonable manner, but not in any way
that suggests RW MobiMedia UK Limited or any contributors endorse you or your use.
2.4. Modifications
If You create Modifications, and such Modifications are not Covered Software,
You agree to release the Modifications under this License or a Compatible
License.
3. Compliance with Laws
You must comply with all applicable laws regarding use of the software.
4. Disclaimer of Warranty
Covered Software is provided under this License on an "as is" basis, without
warranty of any kind, either expressed, implied, or statutory, including,
without limitation, warranties that the Covered Software is free of defects,
merchantable, fit for a particular purpose or non-infringing.
5. Limitation of Liability
To the extent permitted by applicable law, no Contributor will be liable to
You for any damages, including direct, indirect, special, incidental, or
consequential damages arising out of or related to this License or the use or
inability to use the Covered Software (including but not limited to loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor has been
advised of the possibility of such damages.
6. Termination
The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. Upon termination, You must cease all
use of the Covered Software and destroy all copies of it.
7. Miscellaneous
This License represents the complete agreement concerning subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable.

View File

@ -19,7 +19,7 @@ internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
commonExtension.apply {
compileSdk = 34
compileSdk = 35
defaultConfig {
minSdk = 26

View File

@ -2,9 +2,11 @@ package org.mifospay
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
@OptIn(ExperimentalWasmDsl::class, ExperimentalKotlinGradlePluginApi::class)
internal fun Project.configureKotlinMultiplatform() {
extensions.configure<KotlinMultiplatformExtension> {
applyDefaultHierarchyTemplate()
@ -22,19 +24,9 @@ internal fun Project.configureKotlinMultiplatform() {
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")
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}
}
}

View File

@ -9,6 +9,7 @@
*/
package org.mifospay.core.designsystem.component
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
@ -28,6 +29,7 @@ import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
@ -66,6 +68,7 @@ fun MifosOutlinedTextField(
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) {
val isFocused by interactionSource.collectIsFocusedAsState()
val showIcon by rememberUpdatedState(value.isNotEmpty())
MifosCustomTextField(
modifier = modifier.fillMaxWidth(),
@ -81,14 +84,18 @@ fun MifosOutlinedTextField(
singleLine = singleLine,
leadingIcon = leadingIcon,
trailingIcon = @Composable {
if (showClearIcon && isFocused) {
ClearIconButton(
showClearIcon = true,
clearIcon = clearIcon,
onClickClearIcon = onClickClearIcon,
)
} else {
trailingIcon?.invoke()
AnimatedContent(
targetState = showClearIcon && isFocused && showIcon,
) {
if (it) {
ClearIconButton(
showClearIcon = true,
clearIcon = clearIcon,
onClickClearIcon = onClickClearIcon,
)
} else {
trailingIcon?.invoke()
}
}
},
keyboardActions = KeyboardActions {
@ -127,6 +134,7 @@ fun MifosTextField(
leadingIcon: @Composable (() -> Unit)? = null,
) {
val isFocused by interactionSource.collectIsFocusedAsState()
val showIcon by rememberUpdatedState(value.isNotEmpty())
MifosCustomTextField(
value = value,
@ -146,14 +154,18 @@ fun MifosTextField(
leadingIcon = leadingIcon,
isError = isError,
trailingIcon = @Composable {
if (showClearIcon && isFocused) {
ClearIconButton(
showClearIcon = true,
clearIcon = clearIcon,
onClickClearIcon = onClickClearIcon,
)
} else {
trailingIcon?.invoke()
AnimatedContent(
targetState = showClearIcon && isFocused && showIcon,
) {
if (it) {
ClearIconButton(
showClearIcon = true,
clearIcon = clearIcon,
onClickClearIcon = onClickClearIcon,
)
} else {
trailingIcon?.invoke()
}
}
},
supportingText = errorText?.let {

View File

@ -1,2 +1,22 @@
-keep class io.ktor.** { *; }
-keep class kotlinx.serialization.** { *; }
-keep class kotlinx.serialization.** { *; }
-dontwarn io.ktor.client.network.sockets.SocketTimeoutException
-dontwarn java.lang.management.RuntimeMXBean
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keeppackagenames okhttp3.internal.publicsuffix.*
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
-keep class org.mifospay.core.network.services.* { *;}

View File

@ -5,7 +5,7 @@ platform :android do
lane :deploy_internal do
supply(
track: 'internal',
aab: 'app/build/outputs/bundle/prod/app-prod-release.aab',
aab: 'mifospay-android/build/outputs/bundle/prodRelease/mifospay-android-prod-release.aab',
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
@ -40,7 +40,7 @@ platform :android do
client_id: ENV["AMAZON_APPSTORE_CLIENT_ID"],
client_secret: ENV["AMAZON_APPSTORE_CLIENT_SECRET"],
app_id: ENV["AMAZON_APPSTORE_APP_ID"],
apk_path: "app/build/outputs/apk/prod/release/app-prod-release.apk",
apk_path: "mifospay-android/build/outputs/apk/prod/release/mifospay-android-prod-release.apk",
upload_apk: true,
changelogs_path: "fastlane/metadata/android/en-US/changelogs/",
upload_changelogs: true,

View File

@ -29,8 +29,6 @@ kotlin {
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.koin.compose.viewmodel)
implementation(libs.koin.compose)
implementation(libs.jb.kotlin.stdlib)
implementation(libs.kotlin.reflect)
}

View File

@ -10,6 +10,7 @@
package org.mifospay.feature.auth.login
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@ -21,8 +22,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -31,6 +30,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@ -50,6 +50,7 @@ import org.mifospay.core.designsystem.component.MifosBasicDialog
import org.mifospay.core.designsystem.component.MifosButton
import org.mifospay.core.designsystem.component.MifosLoadingDialog
import org.mifospay.core.designsystem.component.MifosOutlinedTextField
import org.mifospay.core.designsystem.component.MifosScaffold
import org.mifospay.core.designsystem.theme.MifosTheme
import org.mifospay.core.designsystem.theme.grey
import org.mifospay.core.designsystem.theme.styleNormal18sp
@ -64,9 +65,10 @@ internal fun LoginScreen(
modifier: Modifier = Modifier,
viewModel: LoginViewModel = koinViewModel(),
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
EventsEffect(viewModel) { event ->
when (event) {
@ -88,18 +90,34 @@ internal fun LoginScreen(
},
)
Scaffold(
snackbarHost = { SnackbarHost(snackbarHostState) },
LoginScreen(
state = state,
snackbarHostState = snackbarHostState,
modifier = modifier,
onAction = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
)
}
@Composable
private fun LoginScreen(
state: LoginState,
snackbarHostState: SnackbarHostState,
modifier: Modifier = Modifier,
onAction: (LoginAction) -> Unit,
) {
MifosScaffold(
snackbarHostState = snackbarHostState,
modifier = modifier.fillMaxSize(),
containerColor = MaterialTheme.colorScheme.background,
) { paddingValues ->
LoginScreenContent(
state = state,
onEvent = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
modifier = modifier.padding(paddingValues),
navigateToSignupScreen = navigateToSignupScreen,
onAction = onAction,
modifier = modifier
.fillMaxSize()
.padding(paddingValues),
)
}
}
@ -128,9 +146,8 @@ private fun LoginDialogs(
@Composable
private fun LoginScreenContent(
state: LoginState,
onEvent: (LoginAction) -> Unit,
modifier: Modifier = Modifier,
navigateToSignupScreen: () -> Unit,
onAction: (LoginAction) -> Unit,
) {
Column(
modifier = modifier
@ -156,7 +173,7 @@ private fun LoginScreenContent(
label = stringResource(Res.string.feature_auth_username),
value = state.username,
onValueChange = {
onEvent(LoginAction.UsernameChanged(it))
onAction(LoginAction.UsernameChanged(it))
},
modifier = Modifier.fillMaxWidth(),
)
@ -165,12 +182,12 @@ private fun LoginScreenContent(
label = stringResource(Res.string.feature_auth_password),
value = state.password,
onValueChange = {
onEvent(LoginAction.PasswordChanged(it))
onAction(LoginAction.PasswordChanged(it))
},
modifier = Modifier.fillMaxWidth(),
showPassword = state.isPasswordVisible,
showPasswordChange = {
onEvent(LoginAction.TogglePasswordVisibility)
onAction(LoginAction.TogglePasswordVisibility)
},
)
val isLoginButtonEnabled = state.username.isNotEmpty() && state.password.isNotEmpty()
@ -180,7 +197,7 @@ private fun LoginScreenContent(
.padding(top = 16.dp),
enabled = isLoginButtonEnabled,
onClick = {
onEvent(LoginAction.LoginClicked)
onAction(LoginAction.LoginClicked)
},
contentPadding = PaddingValues(12.dp),
) {
@ -191,7 +208,11 @@ private fun LoginScreenContent(
)
}
SignupButton { navigateToSignupScreen() }
SignupButton(
navigateToSignupScreen = {
onAction(LoginAction.SignupClicked)
},
)
}
}
@ -211,11 +232,16 @@ private fun SignupButton(
color = MaterialTheme.colorScheme.onSurface,
)
Text(
modifier = Modifier.clickable {
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
) {
navigateToSignupScreen()
},
text = stringResource(Res.string.feature_auth_sign_up),
style = MaterialTheme.typography.titleMedium.copy(
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelLarge.copy(
textDecoration = TextDecoration.Underline,
),
)
@ -226,10 +252,10 @@ private fun SignupButton(
@Composable
private fun LoanScreenPreview() {
MifosTheme {
LoginScreenContent(
LoginScreen(
state = LoginState(dialogState = null),
onEvent = {},
navigateToSignupScreen = {},
snackbarHostState = remember { SnackbarHostState() },
onAction = {},
)
}
}

View File

@ -13,7 +13,7 @@ package org.mifospay.feature.auth.navigation
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import org.mifospay.core.ui.composableWithSlideTransitions
import org.mifospay.feature.auth.mobileVerify.MobileVerificationScreen
const val MOBILE_VERIFICATION_ROUTE = "mobile_verification_route"
@ -22,7 +22,7 @@ fun NavGraphBuilder.mobileVerificationScreen(
onNavigateBack: () -> Unit,
onOtpVerificationSuccess: (String) -> Unit,
) {
composable(
composableWithSlideTransitions(
route = MOBILE_VERIFICATION_ROUTE,
) {
MobileVerificationScreen(

View File

@ -14,8 +14,8 @@ package org.mifospay.feature.auth.navigation
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
import org.mifospay.core.ui.composableWithPushTransitions
import org.mifospay.feature.auth.signup.SignupScreen
const val SIGNUP_ROUTE = "signup_route"
@ -24,7 +24,7 @@ fun NavGraphBuilder.signupScreen(
onNavigateBack: () -> Unit,
onNavigateToLogin: (String) -> Unit,
) {
composable(
composableWithPushTransitions(
route = "$SIGNUP_ROUTE?savingsProductId={savingsProductId}" +
"&mobileNumber={mobileNumber}&businessName={businessName}",
arguments = listOf(

View File

@ -13,11 +13,13 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarHostState
@ -33,6 +35,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.launch
@ -67,7 +71,6 @@ import org.mifospay.core.ui.MifosPasswordField
import org.mifospay.core.ui.PasswordStrengthIndicator
import org.mifospay.core.ui.utils.EventsEffect
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun SignupScreen(
onNavigateBack: () -> Unit,
@ -75,10 +78,10 @@ internal fun SignupScreen(
modifier: Modifier = Modifier,
viewModel: SignupViewModel = koinViewModel(),
) {
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
EventsEffect(viewModel) { event ->
when (event) {
@ -99,9 +102,30 @@ internal fun SignupScreen(
},
)
SignupScreen(
state = state,
snackbarHostState = snackbarHostState,
modifier = modifier,
onAction = remember(viewModel) {
{ viewModel.trySendAction(it) }
},
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SignupScreen(
state: SignUpState,
snackbarHostState: SnackbarHostState,
modifier: Modifier = Modifier,
onAction: (SignUpAction) -> Unit,
) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
MifosScaffold(
snackbarHostState = snackbarHostState,
modifier = modifier,
containerColor = MaterialTheme.colorScheme.background,
topBar = {
MifosTopAppBar(
title = stringResource(Res.string.feature_auth_complete_your_registration),
@ -109,8 +133,8 @@ internal fun SignupScreen(
scrollBehavior = scrollBehavior,
navigationIcon = MifosIcons.Back,
navigationIconContentDescription = "Back",
onNavigationIconClick = remember(viewModel) {
{ viewModel.trySendAction(SignUpAction.CloseClick) }
onNavigationIconClick = {
onAction(SignUpAction.CloseClick)
},
)
},
@ -118,11 +142,222 @@ internal fun SignupScreen(
SignupScreenContent(
modifier = Modifier.padding(it),
state = state,
onAction = viewModel::trySendAction,
onAction = onAction,
)
}
}
@Composable
private fun SignupScreenContent(
modifier: Modifier = Modifier,
state: SignUpState,
onAction: (SignUpAction) -> Unit,
) {
LazyColumn(
modifier = modifier
.fillMaxSize(),
contentPadding = PaddingValues(12.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
MifosOutlinedTextField(
value = state.firstNameInput,
label = stringResource(Res.string.feature_auth_first_name),
modifier = Modifier.fillMaxWidth(),
isError = state.firstNameInput.isEmpty(),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Words,
),
onValueChange = {
onAction(SignUpAction.FirstNameInputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.lastNameInput,
label = stringResource(Res.string.feature_auth_last_name),
modifier = Modifier.fillMaxWidth(),
isError = state.lastNameInput.isEmpty(),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Words,
),
onValueChange = {
onAction(SignUpAction.LastNameInputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.userNameInput,
label = stringResource(Res.string.feature_auth_username),
modifier = Modifier.fillMaxWidth(),
isError = state.userNameInput.isEmpty(),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
),
onValueChange = {
onAction(SignUpAction.UserNameInputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.emailInput,
label = stringResource(Res.string.feature_auth_email),
modifier = Modifier.fillMaxWidth(),
isError = state.emailInput.isEmpty(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
),
onValueChange = {
onAction(SignUpAction.EmailInputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.mobileNumberInput,
label = stringResource(Res.string.feature_auth_mobile_no),
modifier = Modifier.fillMaxWidth(),
isError = state.mobileNumberInput.isEmpty(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Phone,
),
onValueChange = {
onAction(SignUpAction.MobileNumberInputChange(it))
},
)
}
item {
Column {
var showPassword by rememberSaveable { mutableStateOf(false) }
MifosPasswordField(
value = state.passwordInput,
label = stringResource(Res.string.feature_auth_password),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.PasswordInputChange(it))
},
showPassword = showPassword,
showPasswordChange = { showPassword = !showPassword },
)
Spacer(modifier = Modifier.height(4.dp))
PasswordStrengthIndicator(
modifier = Modifier.fillMaxWidth(),
state = state.passwordStrengthState,
currentCharacterCount = state.passwordInput.length,
)
}
}
item {
var showPassword by rememberSaveable { mutableStateOf(false) }
MifosPasswordField(
value = state.confirmPasswordInput,
label = stringResource(Res.string.feature_auth_confirm_password),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.ConfirmPasswordInputChange(it))
},
showPassword = showPassword,
showPasswordChange = { showPassword = !showPassword },
)
}
item {
MifosOutlinedTextField(
value = state.addressLine1Input,
label = stringResource(Res.string.feature_auth_address_line_1),
modifier = Modifier.fillMaxWidth(),
isError = state.addressLine1Input.isEmpty(),
onValueChange = {
onAction(SignUpAction.AddressLine1InputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.addressLine2Input,
modifier = Modifier.fillMaxWidth(),
label = stringResource(Res.string.feature_auth_address_line_2),
isError = state.addressLine2Input.isEmpty(),
onValueChange = {
onAction(SignUpAction.AddressLine2InputChange(it))
},
)
}
item {
MifosOutlinedTextField(
value = state.pinCodeInput,
label = stringResource(Res.string.feature_auth_pin_code),
modifier = Modifier.fillMaxWidth(),
isError = state.pinCodeInput.isEmpty(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
),
onValueChange = {
onAction(SignUpAction.PinCodeInputChange(it))
},
)
}
item {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
MifosOutlinedTextField(
value = state.countryInput,
label = stringResource(Res.string.feature_auth_country),
onValueChange = {
onAction(SignUpAction.CountryInputChange(it))
},
modifier = Modifier.weight(1.5f),
isError = state.countryInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.stateInput,
label = stringResource(Res.string.feature_auth_state),
onValueChange = {
onAction(SignUpAction.StateInputChange(it))
},
modifier = Modifier.weight(1.5f),
isError = state.stateInput.isEmpty(),
)
}
}
item {
MifosButton(
modifier = Modifier
.fillMaxWidth(),
color = MaterialTheme.colorScheme.primary,
enabled = true,
onClick = {
onAction(SignUpAction.SubmitClick)
},
contentPadding = PaddingValues(12.dp),
) {
Text(
text = stringResource(Res.string.feature_auth_complete),
)
}
}
}
}
@Composable
private fun SignUpDialogs(
dialogState: SignUpDialog?,
@ -143,167 +378,3 @@ private fun SignUpDialogs(
null -> Unit
}
}
@Composable
private fun SignupScreenContent(
modifier: Modifier = Modifier,
state: SignUpState,
onAction: (SignUpAction) -> Unit,
) {
Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
MifosOutlinedTextField(
value = state.firstNameInput,
label = stringResource(Res.string.feature_auth_first_name),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.FirstNameInputChange(it))
},
isError = state.firstNameInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.lastNameInput,
label = stringResource(Res.string.feature_auth_last_name),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.LastNameInputChange(it))
},
isError = state.lastNameInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.userNameInput,
label = stringResource(Res.string.feature_auth_username),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.UserNameInputChange(it))
},
isError = state.userNameInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.emailInput,
label = stringResource(Res.string.feature_auth_email),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.EmailInputChange(it))
},
isError = state.emailInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.mobileNumberInput,
label = stringResource(Res.string.feature_auth_mobile_no),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.MobileNumberInputChange(it))
},
isError = state.mobileNumberInput.isEmpty(),
)
var showPassword by rememberSaveable { mutableStateOf(false) }
MifosPasswordField(
value = state.passwordInput,
label = stringResource(Res.string.feature_auth_password),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.PasswordInputChange(it))
},
showPassword = showPassword,
showPasswordChange = { showPassword = !showPassword },
)
PasswordStrengthIndicator(
modifier = Modifier.padding(horizontal = 16.dp),
state = state.passwordStrengthState,
currentCharacterCount = state.passwordInput.length,
)
MifosPasswordField(
value = state.confirmPasswordInput,
label = stringResource(Res.string.feature_auth_confirm_password),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.ConfirmPasswordInputChange(it))
},
showPassword = showPassword,
showPasswordChange = { showPassword = !showPassword },
)
MifosOutlinedTextField(
value = state.addressLine1Input,
label = stringResource(Res.string.feature_auth_address_line_1),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.AddressLine1InputChange(it))
},
isError = state.addressLine1Input.isEmpty(),
)
MifosOutlinedTextField(
value = state.addressLine2Input,
modifier = Modifier.fillMaxWidth(),
label = stringResource(Res.string.feature_auth_address_line_2),
onValueChange = {
onAction(SignUpAction.AddressLine2InputChange(it))
},
isError = state.addressLine2Input.isEmpty(),
)
MifosOutlinedTextField(
value = state.pinCodeInput,
label = stringResource(Res.string.feature_auth_pin_code),
modifier = Modifier.fillMaxWidth(),
onValueChange = {
onAction(SignUpAction.PinCodeInputChange(it))
},
isError = state.pinCodeInput.isEmpty(),
)
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
MifosOutlinedTextField(
value = state.countryInput,
label = stringResource(Res.string.feature_auth_country),
onValueChange = {
onAction(SignUpAction.CountryInputChange(it))
},
modifier = Modifier.weight(1.5f),
isError = state.countryInput.isEmpty(),
)
MifosOutlinedTextField(
value = state.stateInput,
label = stringResource(Res.string.feature_auth_state),
onValueChange = {
onAction(SignUpAction.StateInputChange(it))
},
modifier = Modifier.weight(1.5f),
isError = state.stateInput.isEmpty(),
)
}
MifosButton(
modifier = Modifier
.fillMaxWidth(),
color = MaterialTheme.colorScheme.primary,
enabled = true,
onClick = {
onAction(SignUpAction.SubmitClick)
},
contentPadding = PaddingValues(12.dp),
) {
Text(
text = stringResource(Res.string.feature_auth_complete),
)
}
}
}

View File

@ -25,9 +25,6 @@ kotlin {
implementation(compose.material3)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.koin.compose.viewmodel)
implementation(libs.koin.compose)
}
}
}

View File

@ -21,6 +21,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -212,34 +213,48 @@ private fun SearchBarScreen(
modifier: Modifier = Modifier,
) {
SearchBar(
inputField = {
SearchBarDefaults.InputField(
query = query,
onQueryChange = onQueryChange,
onSearch = onSearch,
expanded = false,
onExpandedChange = {},
enabled = true,
placeholder = {
Text(text = stringResource(Res.string.feature_merchants_search))
},
leadingIcon = {
Icon(
imageVector = MifosIcons.Search,
contentDescription = stringResource(Res.string.feature_merchants_search),
)
},
trailingIcon = {
IconButton(
onClick = onClearQuery,
) {
Icon(
imageVector = MifosIcons.Close,
contentDescription = stringResource(Res.string.feature_merchants_close),
)
}
},
interactionSource = null,
)
},
expanded = false,
onExpandedChange = {},
modifier = modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 16.dp),
query = query,
onQueryChange = onQueryChange,
onSearch = onSearch,
active = false,
onActiveChange = { },
placeholder = {
Text(text = stringResource(Res.string.feature_merchants_search))
},
leadingIcon = {
Icon(
imageVector = MifosIcons.Search,
contentDescription = stringResource(Res.string.feature_merchants_search),
)
},
trailingIcon = {
IconButton(
onClick = onClearQuery,
) {
Icon(
imageVector = MifosIcons.Close,
contentDescription = stringResource(Res.string.feature_merchants_close),
)
}
},
) {}
shape = SearchBarDefaults.inputFieldShape,
colors = SearchBarDefaults.colors(),
tonalElevation = SearchBarDefaults.TonalElevation,
shadowElevation = SearchBarDefaults.ShadowElevation,
windowInsets = SearchBarDefaults.windowInsets,
content = {},
)
}
@Preview

View File

@ -34,14 +34,4 @@ kotlin {
implementation(libs.filekit.compose)
}
}
}
compose.desktop {
application {
nativeDistributions {
linux {
modules("jdk.security.auth")
}
}
}
}

View File

@ -47,13 +47,3 @@ kotlin {
}
}
}
compose.desktop {
application {
nativeDistributions {
linux {
modules("jdk.security.auth")
}
}
}
}

View File

@ -52,4 +52,5 @@ org.jetbrains.compose.experimental.jscanvas.enabled=true
RblClientIdProp=a
RblClientSecretProp=b
kotlin.native.ignoreDisabledTargets=true
kotlin.native.ignoreDisabledTargets=true
kotlin.mpp.androidGradlePluginCompatibility.nowarn=true

View File

@ -2,26 +2,26 @@
accompanist = "0.34.0"
# Android
androidDesugarJdkLibs = "2.1.2"
androidGradlePlugin = "8.5.2"
androidTools = "31.5.2"
androidDesugarJdkLibs = "2.1.3"
androidGradlePlugin = "8.7.2"
androidTools = "31.7.2"
# AndroidX Dependencies
androidx-test-ext-junit = "1.2.1"
androidxActivity = "1.9.3"
androidxBrowser = "1.8.0"
androidxComposeBom = "2024.10.01"
androidxComposeBom = "2024.11.00"
androidxComposeCompiler = "1.5.15"
androidxComposeMaterial3Adaptive = "1.0.0"
androidxComposeRuntimeTracing = "1.7.5"
androidxCoreSplashscreen = "1.0.1"
androidxLifecycle = "2.8.7"
androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.8.3"
androidxNavigation = "2.8.4"
androidxProfileinstaller = "1.4.1"
androidxTracing = "1.3.0-alpha02"
appcompatVersion = "1.7.0"
coreKtxVersion = "1.13.1"
coreKtxVersion = "1.15.0"
# KotlinX Dependencies
lifecycleExtensionsVersion = "2.2.0"
@ -65,28 +65,27 @@ versionCatalogLinterVersion = "1.0.3"
fineractSdk = "1.0.3"
# Firebase
firebaseBom = "33.5.1"
firebaseBom = "33.6.0"
firebaseCrashlyticsPlugin = "3.0.2"
firebasePerfPlugin = "1.4.2"
# Kotlin KMP Dependencies
kotlin = "2.0.20"
kotlin = "2.0.21"
kotlinInject = "0.7.2"
kotlinxCoroutines = "1.9.0"
kotlinxDatetime = "0.6.1"
kotlinxImmutable = "0.3.8"
kotlinxSerializationJson = "1.7.2"
ksp = "2.0.20-1.0.25"
kotlinxSerializationJson = "1.7.3"
ksp = "2.0.21-1.0.27"
# Ktor & Ktorfit
ktorVersion = "3.0.0-rc-1"
ktorfit = "2.1.0"
ktorfitKsp = "2.1.0-1.0.25"
ktorVersion = "3.0.1"
ktorfit = "2.2.0"
ktorfitKsp = "2.2.0-1.0.27"
# Koin CMP Dependencies
koin = "4.0.0-RC2"
koin = "4.0.0"
koinAnnotationsVersion = "1.4.0-RC4"
koinComposeMultiplatform = "1.2.0-Beta4"
# CMP Libraries
compose-plugin = "1.7.0-rc01"
@ -232,9 +231,9 @@ koin-androidx-compose = { group = "io.insert-koin", name = "koin-androidx-compos
koin-androidx-navigation = { group = "io.insert-koin", name = "koin-androidx-navigation", version.ref = "koin" }
koin-annotations = { group = "io.insert-koin", name = "koin-annotations", version.ref = "koinAnnotationsVersion" }
koin-bom = { group = "io.insert-koin", name = "koin-bom", version.ref = "koin" }
koin-compose = { group = "io.insert-koin", name = "koin-compose", version.ref = "koinComposeMultiplatform" }
koin-compose-viewmodel = { group = "io.insert-koin", name = "koin-compose-viewmodel", version.ref = "koinComposeMultiplatform" }
koin-compose-navigation = { group = "io.insert-koin", name = "koin-compose-viewmodel-navigation", version.ref = "koinComposeMultiplatform" }
koin-compose = { group = "io.insert-koin", name = "koin-compose", version.ref = "koin" }
koin-compose-viewmodel = { group = "io.insert-koin", name = "koin-compose-viewmodel", version.ref = "koin" }
koin-compose-navigation = { group = "io.insert-koin", name = "koin-compose-viewmodel-navigation", version.ref = "koin" }
koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" }
koin-core-viewmodel = { group = "io.insert-koin", name = "koin-core-viewmodel", version.ref = "koin" }
koin-ksp-compiler = { group = "io.insert-koin", name = "koin-ksp-compiler", version.ref = "koinAnnotationsVersion" }
@ -278,9 +277,9 @@ ktor-client-winhttp = { group = "io.ktor", name = "ktor-client-winhttp", version
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktorVersion" }
ktor-server-auth = { group = "io.ktor", name = "ktor-server-auth", version.ref = "ktorVersion" }
ktorfit-converters-flow = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-flow", version.ref = "ktorfit" }
ktorfit-ksp = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-ksp", version.ref = "ktorfitKsp" }
ktorfit-lib = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-lib-ktor-3.0.0-beta-2", version.ref = "ktorfit" }
ktorfit-converters-flow = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-flow", version.ref = "ktorfit" }
ktorfit-lib = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-lib", version.ref = "ktorfit" }
coil-core = { group = "io.coil-kt.coil3", name = "coil-core", version.ref = "coil" }
coil-kt = { group = "io.coil-kt.coil3", name = "coil", version.ref = "coil" }

View File

@ -93,29 +93,29 @@ androidx.compose.ui:ui-unit:1.7.5
androidx.compose.ui:ui-util-android:1.7.5
androidx.compose.ui:ui-util:1.7.5
androidx.compose.ui:ui:1.7.5
androidx.compose:compose-bom:2024.10.01
androidx.compose:compose-bom:2024.11.00
androidx.concurrent:concurrent-futures-ktx:1.1.0
androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.13.1
androidx.core:core-ktx:1.15.0
androidx.core:core-splashscreen:1.0.1
androidx.core:core:1.13.1
androidx.core:core:1.15.0
androidx.credentials:credentials-play-services-auth:1.3.0
androidx.credentials:credentials:1.3.0
androidx.cursoradapter:cursoradapter:1.0.0
androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.1.0
androidx.databinding:databinding-adapters:8.5.2
androidx.databinding:databinding-common:8.5.2
androidx.databinding:databinding-ktx:8.5.2
androidx.databinding:databinding-runtime:8.5.2
androidx.databinding:viewbinding:8.5.2
androidx.databinding:databinding-adapters:8.7.2
androidx.databinding:databinding-common:8.7.2
androidx.databinding:databinding-ktx:8.7.2
androidx.databinding:databinding-runtime:8.7.2
androidx.databinding:viewbinding:8.7.2
androidx.documentfile:documentfile:1.0.0
androidx.drawerlayout:drawerlayout:1.0.0
androidx.emoji2:emoji2-views-helper:1.3.0
androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment-ktx:1.8.2
androidx.fragment:fragment:1.8.2
androidx.fragment:fragment-ktx:1.8.3
androidx.fragment:fragment:1.8.3
androidx.graphics:graphics-path:1.0.1
androidx.interpolator:interpolator:1.0.0
androidx.legacy:legacy-support-core-utils:1.0.0
@ -143,13 +143,13 @@ androidx.lifecycle:lifecycle-viewmodel:2.8.7
androidx.loader:loader:1.1.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
androidx.metrics:metrics-performance:1.0.0-beta01
androidx.navigation:navigation-common-ktx:2.8.3
androidx.navigation:navigation-common:2.8.3
androidx.navigation:navigation-compose:2.8.3
androidx.navigation:navigation-fragment-ktx:2.8.3
androidx.navigation:navigation-fragment:2.8.3
androidx.navigation:navigation-runtime-ktx:2.8.3
androidx.navigation:navigation-runtime:2.8.3
androidx.navigation:navigation-common-ktx:2.8.4
androidx.navigation:navigation-common:2.8.4
androidx.navigation:navigation-compose:2.8.4
androidx.navigation:navigation-fragment-ktx:2.8.4
androidx.navigation:navigation-fragment:2.8.4
androidx.navigation:navigation-runtime-ktx:2.8.4
androidx.navigation:navigation-runtime:2.8.4
androidx.print:print:1.0.0
androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05
androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05
@ -175,12 +175,12 @@ co.touchlab:kermit-android:2.0.4
co.touchlab:kermit-core-android:2.0.4
co.touchlab:kermit-core:2.0.4
co.touchlab:kermit:2.0.4
co.touchlab:stately-concurrency-jvm:2.0.7
co.touchlab:stately-concurrency:2.0.7
co.touchlab:stately-concurrent-collections-jvm:2.0.7
co.touchlab:stately-concurrent-collections:2.0.7
co.touchlab:stately-strict-jvm:2.0.7
co.touchlab:stately-strict:2.0.7
co.touchlab:stately-concurrency-jvm:2.1.0
co.touchlab:stately-concurrency:2.1.0
co.touchlab:stately-concurrent-collections-jvm:2.1.0
co.touchlab:stately-concurrent-collections:2.1.0
co.touchlab:stately-strict-jvm:2.1.0
co.touchlab:stately-strict:2.1.0
com.arkivanov.essenty:back-handler-android:2.1.0
com.arkivanov.essenty:back-handler:2.1.0
com.arkivanov.essenty:utils-internal-android:2.1.0
@ -217,7 +217,7 @@ com.google.errorprone:error_prone_annotations:2.28.0
com.google.firebase:firebase-analytics-ktx:22.1.2
com.google.firebase:firebase-analytics:22.1.2
com.google.firebase:firebase-annotations:16.2.0
com.google.firebase:firebase-bom:33.5.1
com.google.firebase:firebase-bom:33.6.0
com.google.firebase:firebase-common-ktx:21.0.0
com.google.firebase:firebase-common:21.0.0
com.google.firebase:firebase-components:18.0.0
@ -250,12 +250,12 @@ com.squareup.okhttp3:okhttp-sse:4.12.0
com.squareup.okhttp3:okhttp:4.12.0
com.squareup.okio:okio-jvm:3.9.1
com.squareup.okio:okio:3.9.1
de.jensklingenberg.ktorfit:ktorfit-annotations-android:2.1.0
de.jensklingenberg.ktorfit:ktorfit-annotations:2.1.0
de.jensklingenberg.ktorfit:ktorfit-lib-ktor-3.0.0-beta-2-android:2.1.0
de.jensklingenberg.ktorfit:ktorfit-lib-ktor-3.0.0-beta-2:2.1.0
de.jensklingenberg.ktorfit:ktorfit-lib-light-ktor-3.0.0-beta-2-android:2.1.0
de.jensklingenberg.ktorfit:ktorfit-lib-light-ktor-3.0.0-beta-2:2.1.0
de.jensklingenberg.ktorfit:ktorfit-annotations-android:2.2.0
de.jensklingenberg.ktorfit:ktorfit-annotations:2.2.0
de.jensklingenberg.ktorfit:ktorfit-lib-android:2.2.0
de.jensklingenberg.ktorfit:ktorfit-lib-light-android:2.2.0
de.jensklingenberg.ktorfit:ktorfit-lib-light:2.2.0
de.jensklingenberg.ktorfit:ktorfit-lib:2.2.0
dev.chrisbanes.material3:material3-window-size-class-multiplatform-android:0.5.0
dev.chrisbanes.material3:material3-window-size-class-multiplatform:0.5.0
dev.chrisbanes.snapper:snapper:0.2.2
@ -279,61 +279,54 @@ io.github.vinceglb:filekit-compose-android:0.8.7
io.github.vinceglb:filekit-compose:0.8.7
io.github.vinceglb:filekit-core-android:0.8.7
io.github.vinceglb:filekit-core:0.8.7
io.insert-koin:koin-android:4.0.0-RC2
io.insert-koin:koin-androidx-compose:4.0.0-RC2
io.insert-koin:koin-androidx-navigation:4.0.0-RC2
io.insert-koin:koin-android:4.0.0
io.insert-koin:koin-androidx-compose:4.0.0
io.insert-koin:koin-androidx-navigation:4.0.0
io.insert-koin:koin-annotations-jvm:1.4.0-RC4
io.insert-koin:koin-annotations:1.4.0-RC4
io.insert-koin:koin-bom:4.0.0-RC2
io.insert-koin:koin-compose-jvm:4.0.0-RC2
io.insert-koin:koin-compose-viewmodel-jvm:4.0.0-RC2
io.insert-koin:koin-compose-viewmodel:4.0.0-RC2
io.insert-koin:koin-compose:4.0.0-RC2
io.insert-koin:koin-core-jvm:4.0.0-RC2
io.insert-koin:koin-core-viewmodel-jvm:4.0.0-RC2
io.insert-koin:koin-core-viewmodel:4.0.0-RC2
io.insert-koin:koin-core:4.0.0-RC2
io.ktor:ktor-client-auth-jvm:3.0.0-rc-1
io.ktor:ktor-client-auth:3.0.0-rc-1
io.ktor:ktor-client-cio-jvm:3.0.0-beta-2
io.ktor:ktor-client-content-negotiation-jvm:3.0.0-rc-1
io.ktor:ktor-client-content-negotiation:3.0.0-rc-1
io.ktor:ktor-client-core-jvm:3.0.0-rc-1
io.ktor:ktor-client-core:3.0.0-rc-1
io.ktor:ktor-client-json-jvm:3.0.0-rc-1
io.ktor:ktor-client-json:3.0.0-rc-1
io.ktor:ktor-client-logging-jvm:3.0.0-rc-1
io.ktor:ktor-client-logging:3.0.0-rc-1
io.ktor:ktor-client-okhttp-jvm:3.0.0-rc-1
io.ktor:ktor-client-okhttp:3.0.0-rc-1
io.ktor:ktor-client-serialization-jvm:3.0.0-rc-1
io.ktor:ktor-client-serialization:3.0.0-rc-1
io.ktor:ktor-events-jvm:3.0.0-rc-1
io.ktor:ktor-events:3.0.0-rc-1
io.ktor:ktor-http-cio-jvm:3.0.0-beta-2
io.ktor:ktor-http-cio:3.0.0-beta-2
io.ktor:ktor-http-jvm:3.0.0-rc-1
io.ktor:ktor-http:3.0.0-rc-1
io.ktor:ktor-io-jvm:3.0.0-rc-1
io.ktor:ktor-io:3.0.0-rc-1
io.ktor:ktor-network-jvm:3.0.0-beta-2
io.ktor:ktor-network-tls-jvm:3.0.0-beta-2
io.ktor:ktor-network-tls:3.0.0-beta-2
io.ktor:ktor-network:3.0.0-beta-2
io.ktor:ktor-serialization-jvm:3.0.0-rc-1
io.ktor:ktor-serialization-kotlinx-json-jvm:3.0.0-rc-1
io.ktor:ktor-serialization-kotlinx-json:3.0.0-rc-1
io.ktor:ktor-serialization-kotlinx-jvm:3.0.0-rc-1
io.ktor:ktor-serialization-kotlinx:3.0.0-rc-1
io.ktor:ktor-serialization:3.0.0-rc-1
io.ktor:ktor-sse-jvm:3.0.0-rc-1
io.ktor:ktor-sse:3.0.0-rc-1
io.ktor:ktor-utils-jvm:3.0.0-rc-1
io.ktor:ktor-utils:3.0.0-rc-1
io.ktor:ktor-websocket-serialization-jvm:3.0.0-rc-1
io.ktor:ktor-websocket-serialization:3.0.0-rc-1
io.ktor:ktor-websockets-jvm:3.0.0-rc-1
io.ktor:ktor-websockets:3.0.0-rc-1
io.insert-koin:koin-bom:4.0.0
io.insert-koin:koin-compose-jvm:4.0.0
io.insert-koin:koin-compose-viewmodel-jvm:4.0.0
io.insert-koin:koin-compose-viewmodel:4.0.0
io.insert-koin:koin-compose:4.0.0
io.insert-koin:koin-core-jvm:4.0.0
io.insert-koin:koin-core-viewmodel-jvm:4.0.0
io.insert-koin:koin-core-viewmodel:4.0.0
io.insert-koin:koin-core:4.0.0
io.ktor:ktor-client-auth-jvm:3.0.1
io.ktor:ktor-client-auth:3.0.1
io.ktor:ktor-client-content-negotiation-jvm:3.0.1
io.ktor:ktor-client-content-negotiation:3.0.1
io.ktor:ktor-client-core-jvm:3.0.1
io.ktor:ktor-client-core:3.0.1
io.ktor:ktor-client-json-jvm:3.0.1
io.ktor:ktor-client-json:3.0.1
io.ktor:ktor-client-logging-jvm:3.0.1
io.ktor:ktor-client-logging:3.0.1
io.ktor:ktor-client-okhttp-jvm:3.0.1
io.ktor:ktor-client-okhttp:3.0.1
io.ktor:ktor-client-serialization-jvm:3.0.1
io.ktor:ktor-client-serialization:3.0.1
io.ktor:ktor-events-jvm:3.0.1
io.ktor:ktor-events:3.0.1
io.ktor:ktor-http-jvm:3.0.1
io.ktor:ktor-http:3.0.1
io.ktor:ktor-io-jvm:3.0.1
io.ktor:ktor-io:3.0.1
io.ktor:ktor-serialization-jvm:3.0.1
io.ktor:ktor-serialization-kotlinx-json-jvm:3.0.1
io.ktor:ktor-serialization-kotlinx-json:3.0.1
io.ktor:ktor-serialization-kotlinx-jvm:3.0.1
io.ktor:ktor-serialization-kotlinx:3.0.1
io.ktor:ktor-serialization:3.0.1
io.ktor:ktor-sse-jvm:3.0.1
io.ktor:ktor-sse:3.0.1
io.ktor:ktor-utils-jvm:3.0.1
io.ktor:ktor-utils:3.0.1
io.ktor:ktor-websocket-serialization-jvm:3.0.1
io.ktor:ktor-websocket-serialization:3.0.1
io.ktor:ktor-websockets-jvm:3.0.1
io.ktor:ktor-websockets:3.0.1
javax.inject:javax.inject:1
org.checkerframework:checker-qual:3.43.0
org.jetbrains.androidx.core:core-bundle-android:1.0.1
@ -370,13 +363,13 @@ org.jetbrains.compose.ui:ui-text:1.7.0-rc01
org.jetbrains.compose.ui:ui-unit:1.7.0-rc01
org.jetbrains.compose.ui:ui-util:1.7.0-rc01
org.jetbrains.compose.ui:ui:1.7.0-rc01
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.20
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.0.20
org.jetbrains.kotlin:kotlin-reflect:2.0.20
org.jetbrains.kotlin:kotlin-stdlib-common:2.0.20
org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.0.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.20
org.jetbrains.kotlin:kotlin-stdlib:2.0.20
org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.21
org.jetbrains.kotlin:kotlin-parcelize-runtime:2.0.21
org.jetbrains.kotlin:kotlin-reflect:2.0.21
org.jetbrains.kotlin:kotlin-stdlib-common:2.0.21
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20
org.jetbrains.kotlin:kotlin-stdlib:2.0.21
org.jetbrains.kotlinx:atomicfu-jvm:0.23.2
org.jetbrains.kotlinx:atomicfu:0.23.2
org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:0.3.8
@ -385,20 +378,21 @@ org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.9.0
org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.9.0
org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1
org.jetbrains.kotlinx:kotlinx-datetime:0.6.1
org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm:0.5.3
org.jetbrains.kotlinx:kotlinx-io-bytestring:0.5.3
org.jetbrains.kotlinx:kotlinx-io-core-jvm:0.5.3
org.jetbrains.kotlinx:kotlinx-io-core:0.5.3
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.2
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.2
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.2
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.2
org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2
org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm:0.5.4
org.jetbrains.kotlinx:kotlinx-io-bytestring:0.5.4
org.jetbrains.kotlinx:kotlinx-io-core-jvm:0.5.4
org.jetbrains.kotlinx:kotlinx-io-core:0.5.4
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json-io:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3
org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3
org.jetbrains:annotations:23.0.0
org.slf4j:slf4j-api:2.0.16
tech.annexflow.compose:constraintlayout-compose-multiplatform-android:0.4.0

View File

@ -1,4 +1,4 @@
package: name='org.mifospay' versionCode='1' versionName='0.0.4-beta.0.7' platformBuildVersionName='14' platformBuildVersionCode='34' compileSdkVersion='34' compileSdkVersionCodename='14'
package: name='org.mifospay' versionCode='1' versionName='0.0.4-beta.0.57' platformBuildVersionName='15' platformBuildVersionCode='35' compileSdkVersion='35' compileSdkVersionCodename='15'
sdkVersion:'26'
targetSdkVersion:'34'
uses-permission: name='android.permission.INTERNET'
@ -6,13 +6,13 @@ uses-permission: name='android.permission.CAMERA'
uses-permission: name='android.permission.READ_EXTERNAL_STORAGE'
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
uses-permission: name='android.permission.READ_CONTACTS'
uses-permission: name='android.permission.VIBRATE'
uses-permission: name='android.permission.FLASHLIGHT'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.POST_NOTIFICATIONS'
uses-permission: name='android.permission.WAKE_LOCK'
uses-permission: name='com.google.android.c2dm.permission.RECEIVE'
uses-permission: name='com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE'
uses-permission: name='android.permission.ACCESS_ADSERVICES_ATTRIBUTION'
uses-permission: name='android.permission.ACCESS_ADSERVICES_AD_ID'
uses-permission: name='com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE'
uses-permission: name='org.mifospay.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION'
application-label:'Mifos Pay'
application-label-af:'Mifos Pay'
@ -51,7 +51,6 @@ application-label-hy:'Mifos Pay'
application-label-in:'Mifos Pay'
application-label-is:'Mifos Pay'
application-label-it:'Mifos Pay'
application-label-it-IT:'Mifos Pay'
application-label-iw:'Mifos Pay'
application-label-ja:'Mifos Pay'
application-label-ka:'Mifos Pay'
@ -80,11 +79,9 @@ application-label-pt-BR:'Mifos Pay'
application-label-pt-PT:'Mifos Pay'
application-label-ro:'Mifos Pay'
application-label-ru:'Mifos Pay'
application-label-ru-RU:'Mifos Pay'
application-label-si:'Mifos Pay'
application-label-sk:'Mifos Pay'
application-label-sl:'Mifos Pay'
application-label-so:'Mifos Pay'
application-label-sq:'Mifos Pay'
application-label-sr:'Mifos Pay'
application-label-sr-Latn:'Mifos Pay'
@ -95,12 +92,10 @@ application-label-te:'Mifos Pay'
application-label-th:'Mifos Pay'
application-label-tl:'Mifos Pay'
application-label-tr:'Mifos Pay'
application-label-tr-TR:'Mifos Pay'
application-label-uk:'Mifos Pay'
application-label-ur:'Mifos Pay'
application-label-uz:'Mifos Pay'
application-label-vi:'Mifos Pay'
application-label-zh:'Mifos Pay'
application-label-zh-CN:'Mifos Pay'
application-label-zh-HK:'Mifos Pay'
application-label-zh-TW:'Mifos Pay'
@ -117,15 +112,18 @@ uses-library-not-required:'androidx.window.extensions'
uses-library-not-required:'androidx.window.sidecar'
uses-library-not-required:'android.ext.adservices'
feature-group: label=''
uses-feature-not-required: name='android.hardware.camera'
uses-feature: name='android.hardware.camera'
uses-feature: name='android.hardware.camera.autofocus'
uses-feature: name='android.hardware.faketouch'
uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'
uses-feature: name='android.hardware.screen.portrait'
uses-implied-feature: name='android.hardware.screen.portrait' reason='one or more activities have specified a portrait orientation'
main
other-activities
other-receivers
other-services
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'af' 'am' 'ar' 'as' 'az' 'be' 'bg' 'bn' 'bs' 'ca' 'cs' 'da' 'de' 'el' 'en-AU' 'en-CA' 'en-GB' 'en-IN' 'en-XC' 'es' 'es-US' 'et' 'eu' 'fa' 'fi' 'fr' 'fr-CA' 'gl' 'gu' 'hi' 'hr' 'hu' 'hy' 'in' 'is' 'it' 'it-IT' 'iw' 'ja' 'ka' 'kk' 'km' 'kn' 'ko' 'ky' 'lo' 'lt' 'lv' 'mk' 'ml' 'mn' 'mr' 'ms' 'my' 'nb' 'ne' 'nl' 'or' 'pa' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'ru-RU' 'si' 'sk' 'sl' 'so' 'sq' 'sr' 'sr-Latn' 'sv' 'sw' 'ta' 'te' 'th' 'tl' 'tr' 'tr-TR' 'uk' 'ur' 'uz' 'vi' 'zh' 'zh-CN' 'zh-HK' 'zh-TW' 'zu'
locales: '--_--' 'af' 'am' 'ar' 'as' 'az' 'be' 'bg' 'bn' 'bs' 'ca' 'cs' 'da' 'de' 'el' 'en-AU' 'en-CA' 'en-GB' 'en-IN' 'en-XC' 'es' 'es-US' 'et' 'eu' 'fa' 'fi' 'fr' 'fr-CA' 'gl' 'gu' 'hi' 'hr' 'hu' 'hy' 'in' 'is' 'it' 'iw' 'ja' 'ka' 'kk' 'km' 'kn' 'ko' 'ky' 'lo' 'lt' 'lv' 'mk' 'ml' 'mn' 'mr' 'ms' 'my' 'nb' 'ne' 'nl' 'or' 'pa' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'si' 'sk' 'sl' 'sq' 'sr' 'sr-Latn' 'sv' 'sw' 'ta' 'te' 'th' 'tl' 'tr' 'uk' 'ur' 'uz' 'vi' 'zh-CN' 'zh-HK' 'zh-TW' 'zu'
densities: '160' '240' '320' '480' '640'
native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64'

View File

@ -1,62 +1,120 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/naman/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# 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
-ignorewarnings
# Rules for: uCrop - Image Cropping Library for Android
-dontwarn com.yalantis.ucrop**
-dontwarn java.lang.management.ManagementFactory
-keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; }
-dontwarn com.sun.tools.javac.code.Symbol$ClassSymbol
-dontwarn com.sun.tools.javac.code.Symbol$PackageSymbol
-dontwarn com.sun.tools.javac.code.Symbol
-dontwarn com.sun.tools.javac.tree.TreeScanner
-dontwarn com.sun.tools.javac.util.Name
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.Modifier
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.util.SimpleTypeVisitor7
-dontwarn groovy.lang.GroovyObject
-dontwarn groovy.lang.MetaClass
-dontwarn java.lang.management.ManagementFactory
-dontwarn javax.management.InstanceNotFoundException
-dontwarn javax.management.MBeanRegistrationException
-dontwarn javax.management.MBeanServer
-dontwarn javax.management.MalformedObjectNameException
-dontwarn javax.management.ObjectInstance
-dontwarn javax.management.ObjectName
-dontwarn javax.naming.Context
-dontwarn javax.naming.InitialContext
-dontwarn javax.naming.NamingException
-dontwarn javax.servlet.ServletContainerInitializer
-dontwarn org.codehaus.groovy.reflection.ClassInfo
-dontwarn org.codehaus.groovy.runtime.BytecodeInterface8
-dontwarn org.codehaus.groovy.runtime.ScriptBytecodeAdapter
-dontwarn org.codehaus.groovy.runtime.callsite.CallSite
-dontwarn org.codehaus.groovy.runtime.callsite.CallSiteArray
-dontwarn org.codehaus.janino.ClassBodyEvaluator
-dontwarn sun.reflect.Reflection
# Proguard Kotlin Example https://github.com/Guardsquare/proguard/blob/master/examples/application-kotlin/proguard.pro
-keepattributes *Annotation*
-keep class kotlin.Metadata { *; }
# Kotlin
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class kotlin.text.RegexOption { *; }
-keep class kotlin.** { *; }
-keep class org.jetbrains.skia.** { *; }
-keep class org.jetbrains.skiko.** { *; }
-assumenosideeffects public class androidx.compose.runtime.ComposerKt {
void sourceInformation(androidx.compose.runtime.Composer,java.lang.String);
void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String);
void sourceInformationMarkerEnd(androidx.compose.runtime.Composer);
boolean isTraceInProgress();
void traceEventEnd();
}
# Kotlinx Coroutines Rules
# https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepclassmembers class kotlinx.coroutines.** {
volatile <fields>;
}
-keepclassmembers class kotlin.coroutines.SafeContinuation {
volatile <fields>;
}
-dontwarn java.lang.instrument.ClassFileTransformer
-dontwarn sun.misc.SignalHandler
-dontwarn java.lang.instrument.Instrumentation
-dontwarn sun.misc.Signal
-dontwarn java.lang.ClassValue
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# https://github.com/Kotlin/kotlinx.coroutines/issues/2046
-dontwarn android.annotation.SuppressLint
# https://github.com/JetBrains/compose-jb/issues/2393
-dontnote kotlin.coroutines.jvm.internal.**
-dontnote kotlin.internal.**
-dontnote kotlin.jvm.internal.**
-dontnote kotlin.reflect.**
-dontnote kotlinx.coroutines.debug.internal.**
-dontnote kotlinx.coroutines.internal.**
-keep class kotlin.coroutines.Continuation
-keep class kotlinx.coroutines.CancellableContinuation
-keep class kotlinx.coroutines.channels.Channel
-keep class kotlinx.coroutines.CoroutineDispatcher
-keep class kotlinx.coroutines.CoroutineScope
# this is a weird one, but breaks build on some combinations of OS and JDK (reproduced on Windows 10 + Corretto 16)
-dontwarn org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules_MatchStatementSet*
### kotlinx.serialization rules
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
# Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
-dontnote kotlinx.serialization.**
# Serialization core uses `java.lang.ClassValue` for caching inside these specified classes.
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
# However, since in this case they will not be used, we can disable these warnings
-dontwarn kotlinx.serialization.internal.ClassValueReferences
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keeppackagenames okhttp3.internal.publicsuffix.*
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**

View File

@ -21,7 +21,7 @@ kotlin {
withJava()
}
jvmToolchain(21)
jvmToolchain(17)
sourceSets {
val desktopMain by getting {
@ -42,22 +42,74 @@ kotlin {
}
}
fun String.formatToValidVersion(): String {
// Remove any text after '-' or '+'
val cleanVersion = this.split(Regex("[-+]")).first()
// Split version numbers
val parts = cleanVersion.split(".")
return when {
// If starts with 0, change to 1
parts[0] == "0" -> {
val newParts = parts.toMutableList()
newParts[0] = "1"
// Take only up to 3 parts (MAJOR.MINOR.PATCH)
newParts.take(3).joinToString(".")
}
// If valid, take only up to 3 parts
else -> parts.take(3).joinToString(".")
}
}
val Project.dynamicVersion
get() = project.version.toString().formatToValidVersion()
val productName = "MifosWallet"
val productNameSpace = "org.mifos.pay"
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "org.mifospay.desktop"
packageVersion = "1.0.0"
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Exe, TargetFormat.Deb)
packageName = productName
packageVersion = project.dynamicVersion
description = "Mifos Wallet Desktop Application"
copyright = "© 2024 Mifos Initiative. All rights reserved."
vendor = "Mifos Initiative"
licenseFile.set(project.file("../LICENSE"))
includeAllModules = true
macOS {
bundleID = productNameSpace
dockName = productName
iconFile.set(project.file("icons/ic_launcher.icns"))
notarization {
val providers = project.providers
appleID.set(providers.environmentVariable("NOTARIZATION_APPLE_ID"))
password.set(providers.environmentVariable("NOTARIZATION_PASSWORD"))
teamID.set(providers.environmentVariable("NOTARIZATION_TEAM_ID"))
}
}
windows {
// a version for all Windows distributables
packageVersion = "1.0.0"
// a version only for the msi package
msiPackageVersion = "1.0.0"
// a version only for the exe package
exePackageVersion = "1.0.0"
menu = true
menuGroup = productName
shortcut = true
dirChooser = true
perUserInstall = true
iconFile.set(project.file("icons/ic_launcher.ico"))
}
linux {
modules("jdk.security.auth")
iconFile.set(project.file("icons/ic_launcher.png"))
}
}
buildTypes.release.proguard {
configurationFiles.from(file("compose-desktop.pro"))
obfuscate.set(true)
optimize.set(true)
}
}
}
}

View File

@ -0,0 +1,170 @@
-ignorewarnings
-dontwarn kotlinx.coroutines.debug.*
-keep class kotlin.** { *; }
-keep class kotlinx.coroutines.** { *; }
-keep class org.jetbrains.skia.** { *; }
-keep class org.jetbrains.skiko.** { *; }
-keep class com.arkivanov.essenty.** { *; }
-keep class org.sqlite.** { *; }
# Webcam
-keep class com.github.sarxos.webcam.** { *; }
-keep class org.bridj.** { *; }
# Windows folders
-keep class com.sun.jna.* { *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }
# Keep Ktor classes
-keep class io.ktor.** { *; }
-dontnote io.ktor.**
# Keep all DTO classes in the package
-keep class com.rwmobi.kunigami.data.source.network.dto.** { *; }
-dontnote com.rwmobi.kunigami.data.source.network.dto.**
-keep class com.rwmobi.kunigami.domain.model.** { *; }
-dontnote com.rwmobi.kunigami.domain.model.**
# Apollo workarounds
-dontnote okio.**
-keep class com.apollographql.apollo.** { *; }
-dontnote com.apollographql.**
-keep class okhttp3.** { *; }
-keep class org.bouncycastle.** { *; }
-dontnote okhttp3.internal.platform.**
-dontwarn okhttp3.internal.platform.**
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keeppackagenames okhttp3.internal.publicsuffix.*
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
# Keep the class and fields of kotlinx.datetime.Instant
-keep class kotlinx.datetime.Instant { *; }
-dontnote kotlinx.datetime.Instant
# Kotlinx Serialization
-keep class kotlinx.serialization.** { *; }
-dontwarn kotlinx.serialization.**
-keepnames class kotlinx.serialization.internal.** { *; }
# Do not warn about missing annotations and metadata
-dontwarn kotlin.Metadata
-dontwarn kotlin.jvm.internal.**
-dontwarn kotlin.reflect.jvm.internal.**
# Keep necessary Kotlin attributes
-keepattributes Signature, *Annotation*
# JNA classes
-keep class com.sun.jna.** { *; }
-keepclassmembers class * extends com.sun.jna.** { public *; }
-keep class * implements com.sun.jna.** { *; }
-dontnote com.sun.**
# Logging classes, if logging is required
-keep class org.slf4j.** { *; }
-keep class org.slf4j.impl.** { *; }
-keep class ch.qos.logback.** { *; }
-dontwarn org.slf4j.**
# OSHI classes
-keep class oshi.** { *; }
-dontnote oshi.**
# Keep the entire MacOSThemeDetector class and its nested classes
-keep class com.jthemedetecor.** { *; }
-keep class com.jthemedetecor.MacOSThemeDetector$* { *; }
# Annotated interfaces (including methods which are also kept in implementing classes)
-keepattributes Annotation
-keepattributes *Annotation*
# ServiceLoader support for kotlinx.coroutines
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
# Keeping the implementations of exception handlers and Main dispatchers
-keep class * implements kotlinx.coroutines.internal.MainDispatcherFactory
-keep class * implements kotlinx.coroutines.CoroutineExceptionHandler
# Most of volatile fields are updated with AFU and should not be mangled
-keepclassmembers class kotlinx.coroutines.** {
volatile <fields>;
}
# Same story for the standard library's SafeContinuation that also uses AtomicReferenceFieldUpdater
-keepclassmembers class kotlin.coroutines.SafeContinuation {
volatile <fields>;
}
# These classes are only required by kotlinx.coroutines.debug.AgentPremain, which is only loaded when
# kotlinx-coroutines-core is used as a Java agent, so these are not needed in contexts where ProGuard is used.
-dontwarn java.lang.instrument.ClassFileTransformer
-dontwarn sun.misc.SignalHandler
-dontwarn java.lang.instrument.Instrumentation
-dontwarn sun.misc.Signal
# Only used in `kotlinx.coroutines.internal.ExceptionsConstructor`.
# The case when it is not available is hidden in a `try`-`catch`, as well as a check for Android.
-dontwarn java.lang.ClassValue
# An annotation used for build tooling, won't be directly accessed.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Additional dontwarn rules for common issues
-dontwarn java.awt.**
-dontwarn javax.annotation.**
-keeppackagenames com.google.protobuf.**
-keep class com.sun.jna.** { *; }
-keep class * implements com.sun.jna.** { *; }
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
# Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
-dontnote kotlinx.serialization.**
# Serialization core uses `java.lang.ClassValue` for caching inside these specified classes.
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
# However, since in this case they will not be used, we can disable these warnings
-dontwarn kotlinx.serialization.internal.ClassValueReferences
# disable optimisation for descriptor field because in some versions of ProGuard, optimization generates incorrect bytecode that causes a verification error
# see https://github.com/Kotlin/kotlinx.serialization/issues/2719
-keepclassmembers public class **$$serializer {
private ** descriptor;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,20 +1,17 @@
//
// ContentView.swift
// mifospay-ios
//
// Created by Apple on 14/08/24.
//
import UIKit
import SwiftUI
import shared
import ComposeApp
struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MifosViewControllerKt.MifosViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
struct ContentView: View {
var body: some View {
Text(Greeting().greet())
.padding()
ComposeView().ignoresSafeArea(.all)
}
}
#Preview {
ContentView()
}
}

View File

@ -1,10 +1,3 @@
//
// iosAppApp.swift
// mifospay-ios
//
// Created by Apple on 14/08/24.
//
import SwiftUI
@main

View File

@ -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.shared
import androidx.compose.ui.window.ComposeUIViewController
import org.mifospay.shared.di.initKoin
@Suppress("ktlint:standard:function-naming")
fun MifosViewController() = ComposeUIViewController(
configure = {
initKoin()
},
) {
MifosPaySharedApp()
}

View File

@ -1,4 +1,5 @@
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
plugins {
alias(libs.plugins.kotlinMultiplatform)
@ -20,9 +21,19 @@ kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
moduleName = "mifospay-wasm"
val projectPath: String = project.rootDir.path
browser {
commonWebpackConfig {
outputFileName = "mifospay-wasm.js"
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
static = (static ?: mutableListOf()).apply {
add(projectPath)
add("$projectPath/mifospay-shared/")
add("$projectPath/mifospay-web/")
add("$projectPath/core/designsystem")
add("$projectPath/core/ui")
}
}
}
}
binaries.executable()

View File

@ -1,11 +1,10 @@
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.window.CanvasBasedWindow
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.configureWebResources
import org.mifospay.shared.MifosPaySharedApp
import org.mifospay.shared.di.initKoin
@OptIn(ExperimentalComposeUiApi::class, ExperimentalResourceApi::class)
@OptIn(ExperimentalComposeUiApi::class)
fun main() {
initKoin()

View File

@ -10,17 +10,4 @@
<body>
<canvas id="ComposeTarget"></canvas>
</body>
<script type="application/javascript">
const unhandledError = (event, error) => {
if (error instanceof WebAssembly.CompileError) {
document.getElementById("warning").style.display="initial";
// Hide a Scary Webpack Overlay which is less informative in this case.
const webpackOverlay = document.getElementById("webpack-dev-server-client-overlay");
if (webpackOverlay != null) webpackOverlay.style.display="none";
}
}
addEventListener("error", (event) => unhandledError(event, event.error));
addEventListener("unhandledrejection", (event) => unhandledError(event, event.reason));
</script>
</html>

View File

@ -0,0 +1,31 @@
// Replace paths unavailable during compilation with `null`, so they will not be shown in devtools
;
(() => {
const fs = require("fs");
const path = require("path");
const outDir = __dirname + "/kotlin/"
const projecName = path.basename(__dirname);
const mapFile = outDir + projecName + ".wasm.map"
const sourcemap = JSON.parse(fs.readFileSync(mapFile))
const sources = sourcemap["sources"]
srcLoop: for (let i in sources) {
const srcFilePath = sources[i];
if (srcFilePath == null) continue;
const srcFileCandidates = [
outDir + srcFilePath,
outDir + srcFilePath.substring("../".length),
outDir + "../" + srcFilePath,
];
for (let srcFile of srcFileCandidates) {
if (fs.existsSync(srcFile)) continue srcLoop;
}
sources[i] = null;
}
fs.writeFileSync(mapFile, JSON.stringify(sourcemap));
})();